fix(vertiq): Parameter Setting Reliability Update (#26521)

Updates to the backend to allow faster and more reliable parameter configuration.

---------

Co-authored-by: Jordan <jordan.leiber@vertiq.co>
This commit is contained in:
vertiq-jack
2026-03-11 11:08:05 -04:00
committed by GitHub
parent 20ded97d8a
commit a2808a991c
8 changed files with 55 additions and 46 deletions
@@ -35,7 +35,18 @@
VertiqConfigurationHandler::VertiqConfigurationHandler(VertiqSerialInterface *ser, VertiqConfigurationHandler::VertiqConfigurationHandler(VertiqSerialInterface *ser,
VertiqClientManager *client_manager) : VertiqClientManager *client_manager) :
_serial_interface(ser), _serial_interface(ser),
_client_manager(client_manager) _client_manager(client_manager),
_prop_input_parser_client(0)
#ifdef CONFIG_USE_IFCI_CONFIGURATION
, _ifci_client(0)
#endif
#ifdef CONFIG_USE_PULSING_CONFIGURATION
, _voltage_superposition_client(0)
, _pulsing_rectangular_input_parser_client(0)
#endif
{ {
} }
@@ -43,47 +54,47 @@ void VertiqConfigurationHandler::InitConfigurationClients(uint8_t object_id)
{ {
_object_id_now = object_id; //Make sure we store the initial object ID _object_id_now = object_id; //Make sure we store the initial object ID
_prop_input_parser_client = new EscPropellerInputParserClient(object_id); _prop_input_parser_client.UpdateEntryIds(object_id);
_client_manager->AddNewClient(_prop_input_parser_client); _client_manager->AddNewClient(&_prop_input_parser_client);
#ifdef CONFIG_USE_IFCI_CONFIGURATION #ifdef CONFIG_USE_IFCI_CONFIGURATION
_ifci_client = new IQUartFlightControllerInterfaceClient(object_id); _ifci_client.UpdateEntryIds(object_id);
_client_manager->AddNewClient(_ifci_client); _client_manager->AddNewClient(&_ifci_client);
#endif //CONFIG_USE_IFCI_CONFIGURATION #endif //CONFIG_USE_IFCI_CONFIGURATION
#ifdef CONFIG_USE_PULSING_CONFIGURATION #ifdef CONFIG_USE_PULSING_CONFIGURATION
_voltage_superposition_client = new VoltageSuperPositionClient(object_id); _voltage_superposition_client.UpdateEntryIds(object_id);
_client_manager->AddNewClient(_voltage_superposition_client); _client_manager->AddNewClient(&_voltage_superposition_client);
_pulsing_rectangular_input_parser_client = new PulsingRectangularInputParserClient(object_id); _pulsing_rectangular_input_parser_client.UpdateEntryIds(object_id);
_client_manager->AddNewClient(_pulsing_rectangular_input_parser_client); _client_manager->AddNewClient(&_pulsing_rectangular_input_parser_client);
#endif //CONFIG_USE_PULSING_CONFIGURATION #endif //CONFIG_USE_PULSING_CONFIGURATION
} }
void VertiqConfigurationHandler::InitClientEntryWrappers() void VertiqConfigurationHandler::InitClientEntryWrappers()
{ {
AddNewClientEntry<float, float>(param_find("VTQ_MAX_VELOCITY"), &(_prop_input_parser_client->velocity_max_)); AddNewClientEntry<float, float>(param_find("VTQ_MAX_VELOCITY"), &(_prop_input_parser_client.velocity_max_));
AddNewClientEntry<float, float>(param_find("VTQ_MAX_VOLTS"), &(_prop_input_parser_client->volts_max_)); AddNewClientEntry<float, float>(param_find("VTQ_MAX_VOLTS"), &(_prop_input_parser_client.volts_max_));
AddNewClientEntry<uint8_t, int32_t>(param_find("VTQ_CONTROL_MODE"), &(_prop_input_parser_client->mode_)); AddNewClientEntry<uint8_t, int32_t>(param_find("VTQ_CONTROL_MODE"), &(_prop_input_parser_client.mode_));
AddNewClientEntry<uint8_t, int32_t>(param_find("VTQ_MOTOR_DIR"), &(_prop_input_parser_client->sign_)); AddNewClientEntry<uint8_t, int32_t>(param_find("VTQ_MOTOR_DIR"), &(_prop_input_parser_client.sign_));
AddNewClientEntry<uint8_t, int32_t>(param_find("VTQ_FC_DIR"), &(_prop_input_parser_client->flip_negative_)); AddNewClientEntry<uint8_t, int32_t>(param_find("VTQ_FC_DIR"), &(_prop_input_parser_client.flip_negative_));
#ifdef CONFIG_USE_IFCI_CONFIGURATION #ifdef CONFIG_USE_IFCI_CONFIGURATION
AddNewClientEntry<uint8_t, int32_t>(param_find("VTQ_THROTTLE_CVI"), &(_ifci_client->throttle_cvi_)); AddNewClientEntry<uint8_t, int32_t>(param_find("VTQ_THROTTLE_CVI"), &(_ifci_client.throttle_cvi_));
#endif //CONFIG_USE_IFCI_CONFIGURATION #endif //CONFIG_USE_IFCI_CONFIGURATION
#ifdef CONFIG_USE_PULSING_CONFIGURATION #ifdef CONFIG_USE_PULSING_CONFIGURATION
AddNewClientEntry<uint8_t, int32_t> (param_find("VTQ_PULSE_V_MODE"), AddNewClientEntry<uint8_t, int32_t> (param_find("VTQ_PULSE_V_MODE"),
&(_pulsing_rectangular_input_parser_client->pulsing_voltage_mode_)); &(_pulsing_rectangular_input_parser_client.pulsing_voltage_mode_));
AddNewClientEntry<uint8_t, int32_t>(param_find("VTQ_X_CVI"), &(_ifci_client->x_cvi_)); AddNewClientEntry<uint8_t, int32_t>(param_find("VTQ_X_CVI"), &(_ifci_client.x_cvi_));
AddNewClientEntry<uint8_t, int32_t>(param_find("VTQ_Y_CVI"), &(_ifci_client->y_cvi_)); AddNewClientEntry<uint8_t, int32_t>(param_find("VTQ_Y_CVI"), &(_ifci_client.y_cvi_));
AddNewClientEntry<float, float>(param_find("VTQ_ZERO_ANGLE"), &(_voltage_superposition_client->zero_angle_)); AddNewClientEntry<float, float>(param_find("VTQ_ZERO_ANGLE"), &(_voltage_superposition_client.zero_angle_));
AddNewClientEntry<float, float>(param_find("VTQ_VELO_CUTOFF"), AddNewClientEntry<float, float>(param_find("VTQ_VELO_CUTOFF"),
&(_voltage_superposition_client->velocity_cutoff_)); &(_voltage_superposition_client.velocity_cutoff_));
AddNewClientEntry<float, float>(param_find("VTQ_TQUE_OFF_ANG"), AddNewClientEntry<float, float>(param_find("VTQ_TQUE_OFF_ANG"),
&(_voltage_superposition_client->propeller_torque_offset_angle_)); &(_voltage_superposition_client.propeller_torque_offset_angle_));
AddNewClientEntry<float, float>(param_find("VTQ_PULSE_V_LIM"), AddNewClientEntry<float, float>(param_find("VTQ_PULSE_V_LIM"),
&(_pulsing_rectangular_input_parser_client->pulsing_voltage_limit_)); &(_pulsing_rectangular_input_parser_client.pulsing_voltage_limit_));
#endif //CONFIG_USE_PULSING_CONFIGURATION #endif //CONFIG_USE_PULSING_CONFIGURATION
} }
@@ -91,15 +102,15 @@ void VertiqConfigurationHandler::UpdateClientsToNewObjId(uint8_t new_object_id)
{ {
_object_id_now = new_object_id; _object_id_now = new_object_id;
DestroyAndRecreateClient<EscPropellerInputParserClient>(_prop_input_parser_client, new_object_id); _prop_input_parser_client.UpdateEntryIds(new_object_id);
#ifdef CONFIG_USE_IFCI_CONFIGURATION #ifdef CONFIG_USE_IFCI_CONFIGURATION
DestroyAndRecreateClient<IQUartFlightControllerInterfaceClient>(_ifci_client, new_object_id); _ifci_client.UpdateEntryIds(new_object_id);
#endif #endif
#ifdef CONFIG_USE_PULSING_CONFIGURATION #ifdef CONFIG_USE_PULSING_CONFIGURATION
DestroyAndRecreateClient<VoltageSuperPositionClient>(_voltage_superposition_client, new_object_id); _voltage_superposition_client.UpdateEntryIds(new_object_id);
DestroyAndRecreateClient<PulsingRectangularInputParserClient>(_pulsing_rectangular_input_parser_client, new_object_id); _pulsing_rectangular_input_parser_client.UpdateEntryIds(new_object_id);
#endif #endif
} }
@@ -114,8 +125,6 @@ void VertiqConfigurationHandler::UpdateIquartConfigParams()
{ {
for (uint8_t i = 0; i < _added_configuration_entry_wrappers; i++) { for (uint8_t i = 0; i < _added_configuration_entry_wrappers; i++) {
_configuration_entry_wrappers[i]->SendGet(_serial_interface); _configuration_entry_wrappers[i]->SendGet(_serial_interface);
//Ensure that these get messages get out
_client_manager->HandleClientCommunication();
} }
//Now go ahead and grab responses, and update everyone to be on the same page, but do it quickly. //Now go ahead and grab responses, and update everyone to be on the same page, but do it quickly.
@@ -89,7 +89,7 @@ public:
* *
* @param timeout The maximum amount of time we can keep trying to get responses * @param timeout The maximum amount of time we can keep trying to get responses
*/ */
void CoordinateIquartWithPx4Params(hrt_abstime timeout = 100_ms); void CoordinateIquartWithPx4Params(hrt_abstime timeout = 10_ms);
/** /**
* @brief Gives access to the object ID currently being used * @brief Gives access to the object ID currently being used
@@ -157,16 +157,16 @@ private:
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
//Vertiq Client information //Vertiq Client information
//Known Configuration Clients can be created as pointers to certain types of clients //Known Configuration Clients can be created as pointers to certain types of clients
EscPropellerInputParserClient *_prop_input_parser_client; EscPropellerInputParserClient _prop_input_parser_client;
#ifdef CONFIG_USE_IFCI_CONFIGURATION #ifdef CONFIG_USE_IFCI_CONFIGURATION
//Make all of the clients that we need to talk to the IFCI config params //Make all of the clients that we need to talk to the IFCI config params
IQUartFlightControllerInterfaceClient *_ifci_client; IQUartFlightControllerInterfaceClient _ifci_client;
#endif //CONFIG_USE_IFCI_CONFIGURATION #endif //CONFIG_USE_IFCI_CONFIGURATION
#ifdef CONFIG_USE_PULSING_CONFIGURATION #ifdef CONFIG_USE_PULSING_CONFIGURATION
VoltageSuperPositionClient *_voltage_superposition_client; VoltageSuperPositionClient _voltage_superposition_client;
PulsingRectangularInputParserClient *_pulsing_rectangular_input_parser_client; PulsingRectangularInputParserClient _pulsing_rectangular_input_parser_client;
#endif //CONFIG_USE_PULSING_CONFIGURATION #endif //CONFIG_USE_PULSING_CONFIGURATION
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
@@ -153,7 +153,7 @@ void VertiqIo::Run()
void VertiqIo::parameters_update() void VertiqIo::parameters_update()
{ {
//If someone has changed any parameter in our module. Checked at 1Hz //If someone has changed any parameter in our module. Checked periodically
if (_parameter_update_sub.updated()) { if (_parameter_update_sub.updated()) {
//Grab the changed parameter with copy (which lowers the "changed" flag) //Grab the changed parameter with copy (which lowers the "changed" flag)
parameter_update_s param_update; parameter_update_s param_update;
@@ -167,7 +167,7 @@ private:
uORB::Publication<esc_status_s> _esc_status_pub{ORB_ID(esc_status)}; //We want to publish our ESC Status to anyone who will listen uORB::Publication<esc_status_s> _esc_status_pub{ORB_ID(esc_status)}; //We want to publish our ESC Status to anyone who will listen
// Subscriptions // Subscriptions
uORB::SubscriptionInterval _parameter_update_sub{ORB_ID(parameter_update), 1_s}; uORB::SubscriptionInterval _parameter_update_sub{ORB_ID(parameter_update), 10_ms};
//We need to know what's going on with the actuator test to make sure we handle it properly //We need to know what's going on with the actuator test to make sure we handle it properly
uORB::Subscription _actuator_test_sub{ORB_ID(actuator_test)}; uORB::Subscription _actuator_test_sub{ORB_ID(actuator_test)};
@@ -203,7 +203,7 @@ void VertiqSerialInterface::ProcessSerialRx(ClientAbstract **client_array, uint8
ReOpenSerial(); ReOpenSerial();
//We have bytes //We have bytes
if (CheckForRx()) { while (CheckForRx()) {
uint8_t *data_ptr = ReadAndSetRxBytes(); uint8_t *data_ptr = ReadAndSetRxBytes();
//While we've got packets to look at, give the packet to each of the clients so that each //While we've got packets to look at, give the packet to each of the clients so that each
@@ -35,7 +35,8 @@
VertiqTelemetryManager::VertiqTelemetryManager(VertiqClientManager *client_manager) : VertiqTelemetryManager::VertiqTelemetryManager(VertiqClientManager *client_manager) :
_client_manager(client_manager), _client_manager(client_manager),
_telem_state(UNPAUSED) _telem_state(UNPAUSED),
_telem_interface(0)
{ {
} }
@@ -45,8 +46,8 @@ void VertiqTelemetryManager::Init(uint64_t telem_bitmask, uint8_t module_id)
_telem_bitmask = telem_bitmask; _telem_bitmask = telem_bitmask;
FindTelemetryModuleIds(); FindTelemetryModuleIds();
_telem_interface = new IQUartFlightControllerInterfaceClient(module_id); _telem_interface.UpdateEntryIds(module_id);
_client_manager->AddNewClient(_telem_interface); _client_manager->AddNewClient(&_telem_interface);
} }
void VertiqTelemetryManager::FindTelemetryModuleIds() void VertiqTelemetryManager::FindTelemetryModuleIds()
@@ -106,9 +107,9 @@ uint16_t VertiqTelemetryManager::UpdateTelemetry()
bool timed_out = (time_now - _time_of_last_telem_request) > _telem_timeout; bool timed_out = (time_now - _time_of_last_telem_request) > _telem_timeout;
//We got a telemetry response //We got a telemetry response
if (_telem_interface->telemetry_.IsFresh()) { if (_telem_interface.telemetry_.IsFresh()) {
//grab the data //grab the data
IFCITelemetryData telem_response = _telem_interface->telemetry_.get_reply(); IFCITelemetryData telem_response = _telem_interface.telemetry_.get_reply();
// also update our internal report for logging // also update our internal report for logging
_esc_status.esc[_current_module_id_target_index].esc_address = _module_ids_in_use[_number_of_module_ids_for_telem]; _esc_status.esc[_current_module_id_target_index].esc_address = _module_ids_in_use[_number_of_module_ids_for_telem];
@@ -148,9 +149,8 @@ uint16_t VertiqTelemetryManager::UpdateTelemetry()
uint16_t next_telem = FindNextMotorForTelemetry(); uint16_t next_telem = FindNextMotorForTelemetry();
if (next_telem != _impossible_module_id) { if (next_telem != _impossible_module_id) {
//We need to update the module ID we're going to listen to. So, kill the old one, and make it anew. //We need to update the module ID we're going to listen to
delete _telem_interface; _telem_interface.UpdateEntryIds(next_telem);
_telem_interface = new IQUartFlightControllerInterfaceClient(next_telem);
} }
//update the telem target //update the telem target
@@ -133,7 +133,7 @@ private:
VertiqClientManager *_client_manager; VertiqClientManager *_client_manager;
vertiq_telemetry_pause_states _telem_state; //Keep track of whether or not we've paused telemetry vertiq_telemetry_pause_states _telem_state; //Keep track of whether or not we've paused telemetry
IQUartFlightControllerInterfaceClient *_telem_interface; //Used for reading responses from our telemetry targets IQUartFlightControllerInterfaceClient _telem_interface; //Used for reading responses from our telemetry targets
esc_status_s _esc_status; //We want to publish our ESC Status to anyone who will listen esc_status_s _esc_status; //We want to publish our ESC Status to anyone who will listen
static const uint8_t MAX_SUPPORTABLE_MODULE_IDS = 63; //[0, 62] //The max number of module IDs that we can support static const uint8_t MAX_SUPPORTABLE_MODULE_IDS = 63; //[0, 62] //The max number of module IDs that we can support
static const uint8_t MAX_ESC_STATUS_ENTRIES = static const uint8_t MAX_ESC_STATUS_ENTRIES =