modules/sih: move to px4 work queue (wq:rate_ctrl)

- respect IMU_GYRO_RATEMAX for configured interval
 - optionally compile at higher optimization level per board (${MAX_CUSTOM_OPT_LEVEL})
This commit is contained in:
Daniel Agar 2020-07-06 15:20:38 -04:00 committed by Lorenz Meier
parent c01d459011
commit bb7dd0cf00
4 changed files with 115 additions and 150 deletions

View File

@ -1,6 +1,6 @@
############################################################################
#
# Copyright (c) 2019 PX4 Development Team. All rights reserved.
# Copyright (c) 2019-2020 PX4 Development Team. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
@ -34,14 +34,16 @@
px4_add_module(
MODULE modules__sih
MAIN sih
STACK_MAX 1024
COMPILE_FLAGS
${MAX_CUSTOM_OPT_LEVEL}
SRCS
sih.cpp
sih.hpp
DEPENDS
mathlib
drivers_accelerometer
drivers_barometer
drivers_gyroscope
drivers_magnetometer
px4_work_queue
)

View File

@ -1,6 +1,6 @@
/****************************************************************************
*
* Copyright (c) 2019 PX4 Development Team. All rights reserved.
* Copyright (c) 2019-2020 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@ -47,61 +47,19 @@
#include <drivers/drv_pwm_output.h> // to get PWM flags
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <termios.h>
using namespace math;
using namespace matrix;
int Sih::custom_command(int argc, char *argv[])
{
return print_usage("unknown command");
}
int Sih::task_spawn(int argc, char *argv[])
{
_task_id = px4_task_spawn_cmd("sih",
SCHED_DEFAULT,
SCHED_PRIORITY_MAX,
1024,
(px4_main_t)&run_trampoline,
(char *const *)argv);
if (_task_id < 0) {
_task_id = -1;
return -errno;
}
return 0;
}
Sih *Sih::instantiate(int argc, char *argv[])
{
Sih *instance = new Sih();
if (instance == nullptr) {
PX4_ERR("alloc failed");
}
return instance;
}
using namespace time_literals;
Sih::Sih() :
ModuleParams(nullptr),
_loop_perf(perf_alloc(PC_ELAPSED, MODULE_NAME": execution")),
_sampling_perf(perf_alloc(PC_ELAPSED, MODULE_NAME": sampling"))
ScheduledWorkItem(MODULE_NAME, px4::wq_configurations::rate_ctrl)
{
}
void Sih::run()
{
// initialize parameters
parameters_update_poll();
_px4_accel.set_temperature(T1_C);
_px4_gyro.set_temperature(T1_C);
_px4_mag.set_temperature(T1_C);
parameters_updated();
init_variables();
init_sensors();
@ -109,39 +67,47 @@ void Sih::run()
_last_run = task_start;
_gps_time = task_start;
_serial_time = task_start;
}
px4_sem_init(&_data_semaphore, 0, 0);
Sih::~Sih()
{
perf_free(_loop_perf);
perf_free(_loop_interval_perf);
}
hrt_call_every(&_timer_call, LOOP_INTERVAL, LOOP_INTERVAL, timer_callback, &_data_semaphore);
bool Sih::init()
{
int rate = _imu_gyro_ratemax.get();
perf_begin(_sampling_perf);
// default to 250 Hz (4000 us interval)
if (rate <= 0) {
rate = 250;
}
while (!should_exit()) {
px4_sem_wait(&_data_semaphore); // periodic real time wakeup
// 200 - 2000 Hz
int interval_us = math::constrain(int(roundf(1e6f / rate)), 500, 5000);
ScheduleOnInterval(interval_us);
perf_end(_sampling_perf);
perf_begin(_sampling_perf);
return true;
}
void Sih::Run()
{
perf_count(_loop_interval_perf);
// check for parameter updates
if (_parameter_update_sub.updated()) {
// clear update
parameter_update_s pupdate;
_parameter_update_sub.copy(&pupdate);
// update parameters from storage
updateParams();
parameters_updated();
}
perf_begin(_loop_perf);
inner_loop(); // main execution function
perf_end(_loop_perf);
}
hrt_cancel(&_timer_call); // close the periodic timer interruption
px4_sem_destroy(&_data_semaphore);
}
// timer_callback() is used as a real time callback to post the semaphore
void Sih::timer_callback(void *sem)
{
px4_sem_post((px4_sem_t *)sem);
}
// this is the main execution waken up periodically by the semaphore
void Sih::inner_loop()
{
_now = hrt_absolute_time();
_dt = (_now - _last_run) * 1e-6f;
_last_run = _now;
@ -154,35 +120,39 @@ void Sih::inner_loop()
reconstruct_sensors_signals();
send_IMU();
// update IMU every iteration
_px4_accel.update(_now, _acc(0), _acc(1), _acc(2));
_px4_gyro.update(_now, _gyro(0), _gyro(1), _gyro(2));
if (_now - _gps_time >= 50000) { // gps published at 20Hz
// magnetometer published at 50 Hz
if (_now - _mag_time >= 20_ms) {
_mag_time = _now;
_px4_mag.update(_now, _mag(0), _mag(1), _mag(2));
}
// baro published at 20 Hz
if (_now - _baro_time >= 50_ms) {
_baro_time = _now;
_px4_baro.set_temperature(_baro_temp_c);
_px4_baro.update(_now, _baro_p_mBar);
}
// gps published at 20Hz
if (_now - _gps_time >= 50_ms) {
_gps_time = _now;
send_gps();
}
// send uart message every 40 ms
if (_now - _serial_time >= 40000) {
if (_now - _serial_time >= 40_ms) {
_serial_time = _now;
publish_sih(); // publish _sih message for debug purpose
parameters_update_poll(); // update the parameters if needed
}
}
void Sih::parameters_update_poll()
{
// check for parameter updates
if (_parameter_update_sub.updated()) {
// clear update
parameter_update_s pupdate;
_parameter_update_sub.copy(&pupdate);
// update parameters from storage
updateParams();
parameters_updated();
}
perf_end(_loop_perf);
}
// store the parameters in a more convenient form
@ -330,25 +300,6 @@ void Sih::reconstruct_sensors_signals()
_gps_vel = _v_I + noiseGauss3f(0.06f, 0.077f, 0.158f);
}
void Sih::send_IMU()
{
// gyro
_px4_gyro.set_temperature(T1_C);
_px4_gyro.update(_now, _gyro(0), _gyro(1), _gyro(2));
// accel
_px4_accel.set_temperature(T1_C);
_px4_accel.update(_now, _acc(0), _acc(1), _acc(2));
// magnetometer
_px4_mag.set_temperature(T1_C);
_px4_mag.update(_now, _mag(0), _mag(1), _mag(2));
// baro
_px4_baro.set_temperature(_baro_temp_c);
_px4_baro.update(_now, _baro_p_mBar);
}
void Sih::send_gps()
{
_sensor_gps.timestamp = _now;
@ -430,9 +381,32 @@ Vector3f Sih::noiseGauss3f(float stdx, float stdy, float stdz)
return Vector3f(generate_wgn() * stdx, generate_wgn() * stdy, generate_wgn() * stdz);
}
int sih_main(int argc, char *argv[])
int Sih::task_spawn(int argc, char *argv[])
{
return Sih::main(argc, argv);
Sih *instance = new Sih();
if (instance) {
_object.store(instance);
_task_id = task_id_is_work_queue;
if (instance->init()) {
return PX4_OK;
}
} else {
PX4_ERR("alloc failed");
}
delete instance;
_object.store(nullptr);
_task_id = -1;
return PX4_ERROR;
}
int Sih::custom_command(int argc, char *argv[])
{
return print_usage("unknown command");
}
int Sih::print_usage(const char *reason)
@ -468,3 +442,8 @@ Most of the variables are declared global in the .hpp file to avoid stack overfl
return 0;
}
extern "C" __EXPORT int sih_main(int argc, char *argv[])
{
return Sih::main(argc, argv);
}

View File

@ -1,6 +1,6 @@
/****************************************************************************
*
* Copyright (c) 2019 PX4 Development Team. All rights reserved.
* Copyright (c) 2019-2020 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@ -36,16 +36,17 @@
#include <px4_platform_common/module.h>
#include <px4_platform_common/module_params.h>
#include <px4_platform_common/posix.h>
#include <px4_platform_common/px4_work_queue/ScheduledWorkItem.hpp>
#include <matrix/matrix/math.hpp> // matrix, vectors, dcm, quaterions
#include <conversion/rotation.h> // math::radians,
#include <ecl/geo/geo.h> // to get the physical constants
#include <lib/ecl/geo/geo.h> // to get the physical constants
#include <drivers/drv_hrt.h> // to get the real time
#include <lib/drivers/accelerometer/PX4Accelerometer.hpp>
#include <lib/drivers/barometer/PX4Barometer.hpp>
#include <lib/drivers/gyroscope/PX4Gyroscope.hpp>
#include <lib/drivers/magnetometer/PX4Magnetometer.hpp>
#include <perf/perf_counter.h>
#include <lib/perf/perf_counter.h>
#include <uORB/Publication.hpp>
#include <uORB/Subscription.hpp>
#include <uORB/SubscriptionInterval.hpp>
@ -58,46 +59,31 @@
using namespace time_literals;
extern "C" __EXPORT int sih_main(int argc, char *argv[]);
class Sih : public ModuleBase<Sih>, public ModuleParams
class Sih : public ModuleBase<Sih>, public ModuleParams, public px4::ScheduledWorkItem
{
public:
Sih();
virtual ~Sih() = default;
~Sih() override;
/** @see ModuleBase */
static int task_spawn(int argc, char *argv[]);
/** @see ModuleBase */
static Sih *instantiate(int argc, char *argv[]);
/** @see ModuleBase */
static int custom_command(int argc, char *argv[]);
/** @see ModuleBase */
static int print_usage(const char *reason = nullptr);
/** @see ModuleBase::run() */
void run() override;
static float generate_wgn(); // generate white Gaussian noise sample
// generate white Gaussian noise sample as a 3D vector with specified std
static matrix::Vector3f noiseGauss3f(float stdx, float stdy, float stdz);
// timer called periodically to post the semaphore
static void timer_callback(void *sem);
bool init();
private:
void Run() override;
/**
* Check for parameter changes and update them if needed.
* @param parameter_update_sub uorb subscription to parameter_update
* @param force for a parameter update
*/
void parameters_update_poll();
void parameters_updated();
// simulated sensor instances
@ -130,7 +116,6 @@ private:
static constexpr float T1_C = 15.0f; // ground temperature in celcius
static constexpr float T1_K = T1_C - CONSTANTS_ABSOLUTE_NULL_CELSIUS; // ground temperature in Kelvin
static constexpr float TEMP_GRADIENT = -6.5f / 1000.0f; // temperature gradient in degrees per metre
static constexpr hrt_abstime LOOP_INTERVAL = 4000; // 4ms => 250 Hz real-time
void init_variables();
void init_sensors();
@ -138,22 +123,19 @@ private:
void generate_force_and_torques();
void equations_of_motion();
void reconstruct_sensors_signals();
void send_IMU();
void send_gps();
void publish_sih();
void inner_loop();
perf_counter_t _loop_perf;
perf_counter_t _sampling_perf;
perf_counter_t _loop_perf{perf_alloc(PC_ELAPSED, MODULE_NAME": cycle")};
perf_counter_t _loop_interval_perf{perf_alloc(PC_INTERVAL, MODULE_NAME": cycle interval")};
px4_sem_t _data_semaphore;
hrt_call _timer_call;
hrt_abstime _last_run;
hrt_abstime _gps_time;
hrt_abstime _serial_time;
hrt_abstime _now;
float _dt; // sampling time [s]
hrt_abstime _last_run{0};
hrt_abstime _baro_time{0};
hrt_abstime _gps_time{0};
hrt_abstime _mag_time{0};
hrt_abstime _serial_time{0};
hrt_abstime _now{0};
float _dt{0}; // sampling time [s]
bool _grounded{true};// whether the vehicle is on the ground
matrix::Vector3f _T_B; // thrust force in body frame [N]
@ -194,6 +176,8 @@ private:
// parameters defined in sih_params.c
DEFINE_PARAMETERS(
(ParamInt<px4::params::IMU_GYRO_RATEMAX>) _imu_gyro_ratemax,
(ParamFloat<px4::params::SIH_MASS>) _sih_mass,
(ParamFloat<px4::params::SIH_IXX>) _sih_ixx,
(ParamFloat<px4::params::SIH_IYY>) _sih_iyy,

View File

@ -1,6 +1,6 @@
/****************************************************************************
*
* Copyright (c) 2013-2019 PX4 Development Team. All rights reserved.
* Copyright (c) 2019-2020 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions