Compare commits

...

4 Commits

Author SHA1 Message Date
Thad House
d84240d8e9 Bump opencv version to 3.4.4-4 (#1489) 2018-12-14 20:17:51 -08:00
Thad House
1823cb2b68 Fix periodic can packets not being received properly (#1488)
Constant calls would result in timeout, because a valid packet wasn't being returned early.

Also fix data copies (was copying in wrong direction).
2018-12-14 17:43:48 -08:00
Tyler Veness
41596608cc Suppress Watchdog's generic timeout message in MotorSafety (#1486) 2018-12-14 10:53:33 -08:00
Thad House
0c3b488e18 Make ntcore instances not smart pointers (#1485)
During static shutdown, the instances hang on windows 7, so let them leak instead.
2018-12-13 21:33:58 -08:00
10 changed files with 79 additions and 19 deletions

View File

@@ -196,6 +196,7 @@ void HAL_ReadCANPacketNew(HAL_CANHandle handle, int32_t apiId, uint8_t* data,
auto& msg = can->receives[messageId];
msg.length = dataSize;
msg.lastTimeStamp = timestamp;
// The NetComm call placed in data, copy into the msg
std::memcpy(msg.data, data, dataSize);
}
*length = dataSize;
@@ -226,11 +227,13 @@ void HAL_ReadCANPacketLatest(HAL_CANHandle handle, int32_t apiId, uint8_t* data,
*length = dataSize;
msg.lastTimeStamp = timestamp;
*receivedTimestamp = timestamp;
// The NetComm call placed in data, copy into the msg
std::memcpy(msg.data, data, dataSize);
} else {
auto i = can->receives.find(messageId);
if (i != can->receives.end()) {
std::memcpy(i->second.data, data, i->second.length);
// Read the data from the stored message into the output
std::memcpy(data, i->second.data, i->second.length);
*length = i->second.length;
*receivedTimestamp = i->second.lastTimeStamp;
*status = 0;
@@ -263,6 +266,7 @@ void HAL_ReadCANPacketTimeout(HAL_CANHandle handle, int32_t apiId,
*length = dataSize;
msg.lastTimeStamp = timestamp;
*receivedTimestamp = timestamp;
// The NetComm call placed in data, copy into the msg
std::memcpy(msg.data, data, dataSize);
} else {
auto i = can->receives.find(messageId);
@@ -275,7 +279,8 @@ void HAL_ReadCANPacketTimeout(HAL_CANHandle handle, int32_t apiId,
*status = HAL_CAN_TIMEOUT;
return;
}
std::memcpy(i->second.data, data, i->second.length);
// Read the data from the stored message into the output
std::memcpy(data, i->second.data, i->second.length);
*length = i->second.length;
*receivedTimestamp = i->second.lastTimeStamp;
*status = 0;
@@ -304,9 +309,11 @@ void HAL_ReadCANPeriodicPacket(HAL_CANHandle handle, int32_t apiId,
if (now - i->second.lastTimeStamp <
static_cast<uint64_t>(periodMs) * 1000) {
*status = 0;
std::memcpy(i->second.data, data, i->second.length);
// Read the data from the stored message into the output
std::memcpy(data, i->second.data, i->second.length);
*length = i->second.length;
*receivedTimestamp = i->second.lastTimeStamp;
return;
}
}
}
@@ -325,6 +332,7 @@ void HAL_ReadCANPeriodicPacket(HAL_CANHandle handle, int32_t apiId,
*length = dataSize;
msg.lastTimeStamp = timestamp;
*receivedTimestamp = timestamp;
// The NetComm call placed in data, copy into the msg
std::memcpy(msg.data, data, dataSize);
} else {
auto i = can->receives.find(messageId);
@@ -337,7 +345,8 @@ void HAL_ReadCANPeriodicPacket(HAL_CANHandle handle, int32_t apiId,
*status = HAL_CAN_TIMEOUT;
return;
}
std::memcpy(i->second.data, data, i->second.length);
// Read the data from the stored message into the output
std::memcpy(data, i->second.data, i->second.length);
*length = i->second.length;
*receivedTimestamp = i->second.lastTimeStamp;
*status = 0;

View File

@@ -190,6 +190,7 @@ void HAL_ReadCANPacketNew(HAL_CANHandle handle, int32_t apiId, uint8_t* data,
auto& msg = can->receives[messageId];
msg.length = dataSize;
msg.lastTimeStamp = timestamp;
// The NetComm call placed in data, copy into the msg
std::memcpy(msg.data, data, dataSize);
}
*length = dataSize;
@@ -220,11 +221,13 @@ void HAL_ReadCANPacketLatest(HAL_CANHandle handle, int32_t apiId, uint8_t* data,
*length = dataSize;
msg.lastTimeStamp = timestamp;
*receivedTimestamp = timestamp;
// The NetComm call placed in data, copy into the msg
std::memcpy(msg.data, data, dataSize);
} else {
auto i = can->receives.find(messageId);
if (i != can->receives.end()) {
std::memcpy(i->second.data, data, i->second.length);
// Read the data from the stored message into the output
std::memcpy(data, i->second.data, i->second.length);
*length = i->second.length;
*receivedTimestamp = i->second.lastTimeStamp;
*status = 0;
@@ -257,6 +260,7 @@ void HAL_ReadCANPacketTimeout(HAL_CANHandle handle, int32_t apiId,
*length = dataSize;
msg.lastTimeStamp = timestamp;
*receivedTimestamp = timestamp;
// The NetComm call placed in data, copy into the msg
std::memcpy(msg.data, data, dataSize);
} else {
auto i = can->receives.find(messageId);
@@ -269,7 +273,8 @@ void HAL_ReadCANPacketTimeout(HAL_CANHandle handle, int32_t apiId,
*status = HAL_CAN_TIMEOUT;
return;
}
std::memcpy(i->second.data, data, i->second.length);
// Read the data from the stored message into the output
std::memcpy(data, i->second.data, i->second.length);
*length = i->second.length;
*receivedTimestamp = i->second.lastTimeStamp;
*status = 0;
@@ -286,6 +291,7 @@ void HAL_ReadCANPeriodicPacket(HAL_CANHandle handle, int32_t apiId,
*status = HAL_HANDLE_ERROR;
return;
}
uint32_t messageId = CreateCANId(can.get(), apiId);
{
@@ -297,9 +303,11 @@ void HAL_ReadCANPeriodicPacket(HAL_CANHandle handle, int32_t apiId,
if (now - i->second.lastTimeStamp <
static_cast<uint64_t>(periodMs) * 1000) {
*status = 0;
std::memcpy(i->second.data, data, i->second.length);
// Read the data from the stored message into the output
std::memcpy(data, i->second.data, i->second.length);
*length = i->second.length;
*receivedTimestamp = i->second.lastTimeStamp;
return;
}
}
}
@@ -318,6 +326,7 @@ void HAL_ReadCANPeriodicPacket(HAL_CANHandle handle, int32_t apiId,
*length = dataSize;
msg.lastTimeStamp = timestamp;
*receivedTimestamp = timestamp;
// The NetComm call placed in data, copy into the msg
std::memcpy(msg.data, data, dataSize);
} else {
auto i = can->receives.find(messageId);
@@ -330,7 +339,8 @@ void HAL_ReadCANPeriodicPacket(HAL_CANHandle handle, int32_t apiId,
*status = HAL_CAN_TIMEOUT;
return;
}
std::memcpy(i->second.data, data, i->second.length);
// Read the data from the stored message into the output
std::memcpy(data, i->second.data, i->second.length);
*length = i->second.length;
*receivedTimestamp = i->second.lastTimeStamp;
*status = 0;

View File

@@ -11,7 +11,7 @@ using namespace nt;
std::atomic<int> InstanceImpl::s_default{-1};
std::atomic<InstanceImpl*> InstanceImpl::s_fast_instances[10];
wpi::UidVector<std::unique_ptr<InstanceImpl>, 10> InstanceImpl::s_instances;
wpi::UidVector<InstanceImpl*, 10> InstanceImpl::s_instances;
wpi::mutex InstanceImpl::s_mutex;
using namespace std::placeholders;
@@ -54,7 +54,7 @@ InstanceImpl* InstanceImpl::Get(int inst) {
// vector
if (static_cast<unsigned int>(inst) < s_instances.size()) {
return s_instances[inst].get();
return s_instances[inst];
}
// doesn't exist
@@ -84,9 +84,9 @@ int InstanceImpl::Alloc() {
}
int InstanceImpl::AllocImpl() {
unsigned int inst = s_instances.emplace_back();
unsigned int inst = s_instances.emplace_back(nullptr);
InstanceImpl* ptr = new InstanceImpl(inst);
s_instances[inst].reset(ptr);
s_instances[inst] = ptr;
if (inst < (sizeof(s_fast_instances) / sizeof(s_fast_instances[0]))) {
s_fast_instances[inst] = ptr;
@@ -104,5 +104,6 @@ void InstanceImpl::Destroy(int inst) {
s_fast_instances[inst] = nullptr;
}
delete s_instances[inst];
s_instances.erase(inst);
}

View File

@@ -51,7 +51,7 @@ class InstanceImpl {
static std::atomic<int> s_default;
static std::atomic<InstanceImpl*> s_fast_instances[10];
static wpi::UidVector<std::unique_ptr<InstanceImpl>, 10> s_instances;
static wpi::UidVector<InstanceImpl*, 10> s_instances;
static wpi::mutex s_mutex;
};

View File

@@ -1,4 +1,4 @@
def opencvVersion = '3.4.4-3'
def opencvVersion = '3.4.4-4'
if (project.hasProperty('useCpp') && project.useCpp) {
model {

View File

@@ -19,12 +19,14 @@ using namespace frc;
MotorSafety::MotorSafety(MotorSafety&& rhs)
: ErrorBase(std::move(rhs)), m_enabled(std::move(rhs.m_enabled)) {
m_watchdog = Watchdog(rhs.m_watchdog.GetTimeout(), [this] { TimeoutFunc(); });
m_watchdog.SuppressTimeoutMessage(true);
}
MotorSafety& MotorSafety::operator=(MotorSafety&& rhs) {
ErrorBase::operator=(std::move(rhs));
m_watchdog = Watchdog(rhs.m_watchdog.GetTimeout(), [this] { TimeoutFunc(); });
m_watchdog.SuppressTimeoutMessage(true);
m_enabled = std::move(rhs.m_enabled);
return *this;

View File

@@ -51,10 +51,12 @@ void Watchdog::Thread::Main() {
auto now = hal::fpga_clock::now();
if (now - watchdog->m_lastTimeoutPrintTime > kMinPrintPeriod) {
watchdog->m_lastTimeoutPrintTime = now;
wpi::outs() << "Watchdog not fed within "
<< wpi::format("%.6f",
watchdog->m_timeout.count() / 1.0e6)
<< "s\n";
if (!watchdog->m_suppressTimeoutMessage) {
wpi::outs() << "Watchdog not fed within "
<< wpi::format("%.6f",
watchdog->m_timeout.count() / 1.0e6)
<< "s\n";
}
}
lock.unlock();
watchdog->m_callback();
@@ -159,6 +161,10 @@ void Watchdog::Disable() {
thr->m_cond.notify_all();
}
void Watchdog::SuppressTimeoutMessage(bool suppress) {
m_suppressTimeoutMessage = suppress;
}
bool Watchdog::operator>(const Watchdog& rhs) {
return m_expirationTime > rhs.m_expirationTime;
}

View File

@@ -104,6 +104,16 @@ class Watchdog {
*/
void Disable();
/**
* Enable or disable suppression of the generic timeout message.
*
* This may be desirable if the user-provided callback already prints a more
* specific message.
*
* @param suppress Whether to suppress generic timeout message.
*/
void SuppressTimeoutMessage(bool suppress);
private:
// Used for timeout print rate-limiting
static constexpr std::chrono::milliseconds kMinPrintPeriod{1000};
@@ -118,6 +128,8 @@ class Watchdog {
wpi::StringMap<std::chrono::microseconds> m_epochs;
bool m_isExpired = false;
bool m_suppressTimeoutMessage = false;
class Thread;
wpi::SafeThreadOwner<Thread>* m_owner;

View File

@@ -20,6 +20,10 @@ public abstract class MotorSafety {
private boolean m_enabled;
private final Object m_thisMutex = new Object();
public MotorSafety() {
m_watchdog.suppressTimeoutMessage(true);
}
/**
* Feed the motor safety object.
*

View File

@@ -23,6 +23,7 @@ import java.util.concurrent.locks.ReentrantLock;
*
* <p>The watchdog is initialized disabled, so the user needs to call enable() before use.
*/
@SuppressWarnings("PMD.TooManyMethods")
public class Watchdog implements Closeable, Comparable<Watchdog> {
// Used for timeout print rate-limiting
private static final long kMinPrintPeriod = 1000000; // us
@@ -38,6 +39,8 @@ public class Watchdog implements Closeable, Comparable<Watchdog> {
private final Map<String, Long> m_epochs = new HashMap<>();
boolean m_isExpired;
boolean m_suppressTimeoutMessage;
static {
startDaemonThread(() -> schedulerFunc());
}
@@ -201,6 +204,17 @@ public class Watchdog implements Closeable, Comparable<Watchdog> {
}
}
/**
* Enable or disable suppression of the generic timeout message.
*
* <p>This may be desirable if the user-provided callback already prints a more specific message.
*
* @param suppress Whether to suppress generic timeout message.
*/
public void suppressTimeoutMessage(boolean suppress) {
m_suppressTimeoutMessage = suppress;
}
private static Thread startDaemonThread(Runnable target) {
Thread inst = new Thread(target);
inst.setDaemon(true);
@@ -229,7 +243,9 @@ public class Watchdog implements Closeable, Comparable<Watchdog> {
long now = RobotController.getFPGATime();
if (now - watchdog.m_lastTimeoutPrintTime > kMinPrintPeriod) {
watchdog.m_lastTimeoutPrintTime = now;
System.out.format("Watchdog not fed within %.6fs\n", watchdog.m_timeout / 1.0e6);
if (!watchdog.m_suppressTimeoutMessage) {
System.out.format("Watchdog not fed within %.6fs\n", watchdog.m_timeout / 1.0e6);
}
}
m_queueMutex.unlock();
watchdog.m_callback.run();