[hal] Add SimValue reset() function (#3064)

This enables correct behavior for resetting incremental sensor values like
encoder counts or gyro accumulated angle with WebSockets.
This commit is contained in:
Peter Johnson
2021-01-12 00:38:58 -08:00
committed by GitHub
parent 9c3b51ca0f
commit bc80c55353
20 changed files with 324 additions and 11 deletions

View File

@@ -40,6 +40,8 @@ void HAL_GetSimValue(HAL_SimValueHandle handle, struct HAL_Value* value) {
void HAL_SetSimValue(HAL_SimValueHandle handle, const struct HAL_Value* value) {
}
void HAL_ResetSimValue(HAL_SimValueHandle handle) {}
hal::SimDevice::SimDevice(const char* name, int index) {}
hal::SimDevice::SimDevice(const char* name, int index, int channel) {}

View File

@@ -63,6 +63,15 @@ int32_t HALSIM_RegisterSimValueChangedCallback(HAL_SimValueHandle handle,
void HALSIM_CancelSimValueChangedCallback(int32_t uid) {}
int32_t HALSIM_RegisterSimValueResetCallback(HAL_SimValueHandle handle,
void* param,
HALSIM_SimValueCallback callback,
HAL_Bool initialNotify) {
return 0;
}
void HALSIM_CancelSimValueResetCallback(int32_t uid) {}
HAL_SimValueHandle HALSIM_GetSimValueHandle(HAL_SimDeviceHandle device,
const char* name) {
return 0;

View File

@@ -225,4 +225,16 @@ Java_edu_wpi_first_hal_SimDeviceJNI_setSimValueNative
HAL_SetSimValue(handle, ValueFromJava(type, value1, value2));
}
/*
* Class: edu_wpi_first_hal_SimDeviceJNI
* Method: resetSimValue
* Signature: (I)V
*/
JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_SimDeviceJNI_resetSimValue
(JNIEnv*, jclass, jint handle)
{
HAL_ResetSimValue(handle);
}
} // extern "C"

View File

@@ -600,6 +600,32 @@ Java_edu_wpi_first_hal_simulation_SimDeviceDataJNI_cancelSimValueChangedCallback
FreeValueCallback(env, uid, &HALSIM_CancelSimValueChangedCallback);
}
/*
* Class: edu_wpi_first_hal_simulation_SimDeviceDataJNI
* Method: registerSimValueResetCallback
* Signature: (ILjava/lang/Object;Z)I
*/
JNIEXPORT jint JNICALL
Java_edu_wpi_first_hal_simulation_SimDeviceDataJNI_registerSimValueResetCallback
(JNIEnv* env, jclass, jint handle, jobject callback, jboolean initialNotify)
{
return AllocateValueCallback(env, static_cast<HAL_SimValueHandle>(handle),
callback, true, initialNotify,
&HALSIM_RegisterSimValueResetCallback);
}
/*
* Class: edu_wpi_first_hal_simulation_SimDeviceDataJNI
* Method: cancelSimValueResetCallback
* Signature: (I)V
*/
JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_simulation_SimDeviceDataJNI_cancelSimValueResetCallback
(JNIEnv* env, jclass, jint uid)
{
FreeValueCallback(env, uid, &HALSIM_CancelSimValueResetCallback);
}
/*
* Class: edu_wpi_first_hal_simulation_SimDeviceDataJNI
* Method: getSimValueHandle

View File

@@ -327,6 +327,17 @@ inline void HAL_SetSimValueBoolean(HAL_SimValueHandle handle, HAL_Bool value) {
HAL_SetSimValue(handle, &v);
}
/**
* Resets a simulated double or integral value to 0.
* Has no effect on other value types.
* Use this instead of Set(0) for resetting incremental sensor values like
* encoder counts or gyro accumulated angle to ensure correct behavior in a
* distributed system (e.g. WebSockets).
*
* @param handle simulated value handle
*/
void HAL_ResetSimValue(HAL_SimValueHandle handle);
/** @} */
#ifdef __cplusplus
@@ -420,6 +431,13 @@ class SimInt : public SimValue {
* @param value the value to set
*/
void Set(int32_t value) { HAL_SetSimValueInt(m_handle, value); }
/**
* Resets the simulated value to 0. Use this instead of Set(0) for resetting
* incremental sensor values like encoder counts or gyro accumulated angle
* to ensure correct behavior in a distributed system (e.g. WebSockets).
*/
void Reset() { HAL_ResetSimValue(m_handle); }
};
/**
@@ -454,6 +472,13 @@ class SimLong : public SimValue {
* @param value the value to set
*/
void Set(int64_t value) { HAL_SetSimValueLong(m_handle, value); }
/**
* Resets the simulated value to 0. Use this instead of Set(0) for resetting
* incremental sensor values like encoder counts or gyro accumulated angle
* to ensure correct behavior in a distributed system (e.g. WebSockets).
*/
void Reset() { HAL_ResetSimValue(m_handle); }
};
/**
@@ -488,6 +513,13 @@ class SimDouble : public SimValue {
* @param value the value to set
*/
void Set(double value) { HAL_SetSimValueDouble(m_handle, value); }
/**
* Resets the simulated value to 0. Use this instead of Set(0) for resetting
* incremental sensor values like encoder counts or gyro accumulated angle
* to ensure correct behavior in a distributed system (e.g. WebSockets).
*/
void Reset() { HAL_ResetSimValue(m_handle); }
};
/**

View File

@@ -57,6 +57,21 @@ int32_t HALSIM_RegisterSimValueChangedCallback(HAL_SimValueHandle handle,
void HALSIM_CancelSimValueChangedCallback(int32_t uid);
/**
* Register a callback for HAL_SimValueReset(). The callback is called with
* the old value.
*
* @param handle simulated value handle
* @param callback callback
* @param initialNotify ignored (present for consistency)
*/
int32_t HALSIM_RegisterSimValueResetCallback(HAL_SimValueHandle handle,
void* param,
HALSIM_SimValueCallback callback,
HAL_Bool initialNotify);
void HALSIM_CancelSimValueResetCallback(int32_t uid);
HAL_SimValueHandle HALSIM_GetSimValueHandle(HAL_SimDeviceHandle device,
const char* name);

View File

@@ -61,6 +61,10 @@ void HAL_SetSimValue(HAL_SimValueHandle handle, const struct HAL_Value* value) {
SimSimDeviceData->SetValue(handle, *value);
}
void HAL_ResetSimValue(HAL_SimValueHandle handle) {
SimSimDeviceData->ResetValue(handle);
}
hal::SimDevice::SimDevice(const char* name, int index) {
wpi::SmallString<128> fullname;
wpi::raw_svector_ostream os(fullname);

View File

@@ -220,6 +220,47 @@ void SimDeviceData::SetValue(HAL_SimValueHandle handle,
valueImpl->direction, &value);
}
void SimDeviceData::ResetValue(HAL_SimValueHandle handle) {
std::scoped_lock lock(m_mutex);
Value* valueImpl = LookupValue(handle);
if (!valueImpl) {
return;
}
// don't notify reset if we aren't going to actually reset anything
switch (valueImpl->value.type) {
case HAL_INT:
case HAL_LONG:
case HAL_DOUBLE:
break;
default:
return;
}
// notify reset callbacks (done here so they're called with the old value)
valueImpl->reset(valueImpl->name.c_str(), valueImpl->handle,
valueImpl->direction, &valueImpl->value);
// set user-facing value to 0
switch (valueImpl->value.type) {
case HAL_INT:
valueImpl->value.data.v_int = 0;
break;
case HAL_LONG:
valueImpl->value.data.v_long = 0;
break;
case HAL_DOUBLE:
valueImpl->value.data.v_double = 0;
break;
default:
return;
}
// notify changed callbacks
valueImpl->changed(valueImpl->name.c_str(), valueImpl->handle,
valueImpl->direction, &valueImpl->value);
}
int32_t SimDeviceData::RegisterDeviceCreatedCallback(
const char* prefix, void* param, HALSIM_SimDeviceCallback callback,
bool initialNotify) {
@@ -368,6 +409,35 @@ void SimDeviceData::CancelValueChangedCallback(int32_t uid) {
valueImpl->changed.Cancel(uid & 0x7f);
}
int32_t SimDeviceData::RegisterValueResetCallback(
HAL_SimValueHandle handle, void* param, HALSIM_SimValueCallback callback,
bool initialNotify) {
std::scoped_lock lock(m_mutex);
Value* valueImpl = LookupValue(handle);
if (!valueImpl) {
return -1;
}
// register callback
int32_t index = valueImpl->reset.Register(callback, param);
// encode device and value into uid
return (((handle >> 16) & 0xfff) << 19) | ((handle & 0xfff) << 7) |
(index & 0x7f);
}
void SimDeviceData::CancelValueResetCallback(int32_t uid) {
if (uid <= 0) {
return;
}
std::scoped_lock lock(m_mutex);
Value* valueImpl = LookupValue(((uid >> 19) << 16) | ((uid >> 7) & 0xfff));
if (!valueImpl) {
return;
}
valueImpl->reset.Cancel(uid & 0x7f);
}
HAL_SimValueHandle SimDeviceData::GetValueHandle(HAL_SimDeviceHandle device,
const char* name) {
std::scoped_lock lock(m_mutex);
@@ -517,6 +587,18 @@ void HALSIM_CancelSimValueChangedCallback(int32_t uid) {
SimSimDeviceData->CancelValueChangedCallback(uid);
}
int32_t HALSIM_RegisterSimValueResetCallback(HAL_SimValueHandle handle,
void* param,
HALSIM_SimValueCallback callback,
HAL_Bool initialNotify) {
return SimSimDeviceData->RegisterValueResetCallback(handle, param, callback,
initialNotify);
}
void HALSIM_CancelSimValueResetCallback(int32_t uid) {
SimSimDeviceData->CancelValueResetCallback(uid);
}
HAL_SimValueHandle HALSIM_GetSimValueHandle(HAL_SimDeviceHandle device,
const char* name) {
return SimSimDeviceData->GetValueHandle(device, name);

View File

@@ -150,6 +150,7 @@ class SimDeviceData {
std::vector<const char*> cstrEnumOptions;
std::vector<double> enumOptionValues;
impl::SimUnnamedCallbackRegistry<HALSIM_SimValueCallback> changed;
impl::SimUnnamedCallbackRegistry<HALSIM_SimValueCallback> reset;
};
struct Device {
@@ -188,6 +189,7 @@ class SimDeviceData {
const HAL_Value& initialValue);
HAL_Value GetValue(HAL_SimValueHandle handle);
void SetValue(HAL_SimValueHandle handle, const HAL_Value& value);
void ResetValue(HAL_SimValueHandle handle);
int32_t RegisterDeviceCreatedCallback(const char* prefix, void* param,
HALSIM_SimDeviceCallback callback,
@@ -218,6 +220,12 @@ class SimDeviceData {
void CancelValueChangedCallback(int32_t uid);
int32_t RegisterValueResetCallback(HAL_SimValueHandle handle, void* param,
HALSIM_SimValueCallback callback,
bool initialNotify);
void CancelValueResetCallback(int32_t uid);
HAL_SimValueHandle GetValueHandle(HAL_SimDeviceHandle device,
const char* name);