mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-10-03 14:58:53 +08:00
battery_simulator: add support for failure injection
For failsafe triggering in automated tests
This commit is contained in:
@@ -70,6 +70,8 @@ void BatterySimulator::Run()
|
|||||||
updateParams();
|
updateParams();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateCommands();
|
||||||
|
|
||||||
if (_vehicle_status_sub.updated()) {
|
if (_vehicle_status_sub.updated()) {
|
||||||
vehicle_status_s vehicle_status;
|
vehicle_status_s vehicle_status;
|
||||||
|
|
||||||
@@ -99,6 +101,11 @@ void BatterySimulator::Run()
|
|||||||
_battery_percentage = math::max(_battery_percentage, _param_bat_min_pct.get() / 100.f);
|
_battery_percentage = math::max(_battery_percentage, _param_bat_min_pct.get() / 100.f);
|
||||||
float vbatt = math::interpolate(_battery_percentage, 0.f, 1.f, _battery.empty_cell_voltage(),
|
float vbatt = math::interpolate(_battery_percentage, 0.f, 1.f, _battery.empty_cell_voltage(),
|
||||||
_battery.full_cell_voltage());
|
_battery.full_cell_voltage());
|
||||||
|
|
||||||
|
if (_force_empty_battery) {
|
||||||
|
vbatt = _battery.empty_cell_voltage();
|
||||||
|
}
|
||||||
|
|
||||||
vbatt *= _battery.cell_count();
|
vbatt *= _battery.cell_count();
|
||||||
|
|
||||||
_battery.setConnected(true);
|
_battery.setConnected(true);
|
||||||
@@ -109,6 +116,60 @@ void BatterySimulator::Run()
|
|||||||
perf_end(_loop_perf);
|
perf_end(_loop_perf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BatterySimulator::updateCommands()
|
||||||
|
{
|
||||||
|
vehicle_command_s vehicle_command;
|
||||||
|
|
||||||
|
while (_vehicle_command_sub.update(&vehicle_command)) {
|
||||||
|
if (vehicle_command.command != vehicle_command_s::VEHICLE_CMD_INJECT_FAILURE) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool handled = false;
|
||||||
|
bool supported = false;
|
||||||
|
|
||||||
|
const int failure_unit = static_cast<int>(vehicle_command.param1 + 0.5f);
|
||||||
|
const int failure_type = static_cast<int>(vehicle_command.param2 + 0.5f);
|
||||||
|
const int instance = static_cast<int>(vehicle_command.param3 + 0.5f);
|
||||||
|
|
||||||
|
if (failure_unit == vehicle_command_s::FAILURE_UNIT_SYSTEM_BATTERY) {
|
||||||
|
|
||||||
|
if (failure_type == vehicle_command_s::FAILURE_TYPE_OK) {
|
||||||
|
handled = true;
|
||||||
|
PX4_INFO("CMD_INJECT_FAILURE, battery ok");
|
||||||
|
supported = false;
|
||||||
|
|
||||||
|
if (instance == 0) {
|
||||||
|
supported = true;
|
||||||
|
_force_empty_battery = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (failure_type == vehicle_command_s::FAILURE_TYPE_OFF) {
|
||||||
|
// Force battery empty for FAILURE_TYPE_OFF - not perfectly accurate, but what we want to achieve
|
||||||
|
handled = true;
|
||||||
|
PX4_WARN("CMD_INJECT_FAILURE, battery empty");
|
||||||
|
supported = false;
|
||||||
|
|
||||||
|
if (instance == 0) {
|
||||||
|
supported = true;
|
||||||
|
_force_empty_battery = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (handled) {
|
||||||
|
vehicle_command_ack_s ack{};
|
||||||
|
ack.command = vehicle_command.command;
|
||||||
|
ack.from_external = false;
|
||||||
|
ack.result = supported ?
|
||||||
|
vehicle_command_ack_s::VEHICLE_CMD_RESULT_ACCEPTED :
|
||||||
|
vehicle_command_ack_s::VEHICLE_CMD_RESULT_UNSUPPORTED;
|
||||||
|
ack.timestamp = hrt_absolute_time();
|
||||||
|
_command_ack_pub.publish(ack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int BatterySimulator::task_spawn(int argc, char *argv[])
|
int BatterySimulator::task_spawn(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
BatterySimulator *instance = new BatterySimulator();
|
BatterySimulator *instance = new BatterySimulator();
|
||||||
|
|||||||
@@ -45,6 +45,8 @@
|
|||||||
#include <uORB/topics/battery_status.h>
|
#include <uORB/topics/battery_status.h>
|
||||||
#include <uORB/topics/parameter_update.h>
|
#include <uORB/topics/parameter_update.h>
|
||||||
#include <uORB/topics/vehicle_status.h>
|
#include <uORB/topics/vehicle_status.h>
|
||||||
|
#include <uORB/topics/vehicle_command.h>
|
||||||
|
#include <uORB/topics/vehicle_command_ack.h>
|
||||||
|
|
||||||
using namespace time_literals;
|
using namespace time_literals;
|
||||||
|
|
||||||
@@ -67,6 +69,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void Run() override;
|
void Run() override;
|
||||||
|
void updateCommands();
|
||||||
|
|
||||||
static constexpr uint32_t BATTERY_SIMLATOR_SAMPLE_FREQUENCY_HZ = 100; // Hz
|
static constexpr uint32_t BATTERY_SIMLATOR_SAMPLE_FREQUENCY_HZ = 100; // Hz
|
||||||
static constexpr uint32_t BATTERY_SIMLATOR_SAMPLE_INTERVAL_US = 1_s / BATTERY_SIMLATOR_SAMPLE_FREQUENCY_HZ;
|
static constexpr uint32_t BATTERY_SIMLATOR_SAMPLE_INTERVAL_US = 1_s / BATTERY_SIMLATOR_SAMPLE_FREQUENCY_HZ;
|
||||||
@@ -76,12 +79,17 @@ private:
|
|||||||
uORB::SubscriptionInterval _parameter_update_sub{ORB_ID(parameter_update), 1_s};
|
uORB::SubscriptionInterval _parameter_update_sub{ORB_ID(parameter_update), 1_s};
|
||||||
uORB::Subscription _vehicle_status_sub{ORB_ID(vehicle_status)};
|
uORB::Subscription _vehicle_status_sub{ORB_ID(vehicle_status)};
|
||||||
|
|
||||||
|
uORB::Subscription _vehicle_command_sub{ORB_ID(vehicle_command)};
|
||||||
|
uORB::Publication<vehicle_command_ack_s> _command_ack_pub{ORB_ID(vehicle_command_ack)};
|
||||||
|
|
||||||
Battery _battery;
|
Battery _battery;
|
||||||
|
|
||||||
uint64_t _last_integration_us{0};
|
uint64_t _last_integration_us{0};
|
||||||
float _battery_percentage{1.f};
|
float _battery_percentage{1.f};
|
||||||
bool _armed{false};
|
bool _armed{false};
|
||||||
|
|
||||||
|
bool _force_empty_battery{false};
|
||||||
|
|
||||||
perf_counter_t _loop_perf{perf_alloc(PC_ELAPSED, MODULE_NAME": cycle")};
|
perf_counter_t _loop_perf{perf_alloc(PC_ELAPSED, MODULE_NAME": cycle")};
|
||||||
|
|
||||||
DEFINE_PARAMETERS(
|
DEFINE_PARAMETERS(
|
||||||
|
|||||||
Reference in New Issue
Block a user