Skip to content

Commit 09626b9

Browse files
committed
Merged main int branch
2 parents a516569 + 59640d6 commit 09626b9

File tree

8 files changed

+131
-49
lines changed

8 files changed

+131
-49
lines changed

include/controller.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ class Controller : public ParamListenerInterface
6565
inline float max_thrust() const { return max_thrust_; }
6666

6767
void init();
68-
void run();
68+
void run(const float dt);
6969

7070
void calculate_max_thrust();
7171
void calculate_equilbrium_torque_from_rc();
@@ -78,8 +78,8 @@ class Controller : public ParamListenerInterface
7878
public:
7979
PID();
8080
void init(float kp, float ki, float kd, float max, float min, float tau);
81-
float run(float dt, float x, float x_c, bool update_integrator);
82-
float run(float dt, float x, float x_c, bool update_integrator, float xdot);
81+
float run(const float dt, float x, float x_c, bool update_integrator);
82+
float run(const float dt, float x, float x_c, bool update_integrator, float xdot);
8383

8484
private:
8585
float kp_;
@@ -97,7 +97,7 @@ class Controller : public ParamListenerInterface
9797

9898
ROSflight & RF_;
9999

100-
Controller::Output run_pid_loops(uint32_t dt, const Estimator::State & state,
100+
Controller::Output run_pid_loops(const float dt, const Estimator::State & state,
101101
const control_t & command, bool update_integrators);
102102

103103
Output output_;

include/estimator.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ class Estimator : public ParamListenerInterface
6969

7070
void init();
7171
void param_change_callback(uint16_t param_id) override;
72-
void run();
72+
void run(const float dt);
7373
void reset_state();
7474
void reset_adaptive_bias();
7575
void set_external_attitude_update(const turbomath::Quaternion & q);
@@ -80,7 +80,7 @@ class Estimator : public ParamListenerInterface
8080
ROSflight & RF_;
8181
State state_;
8282

83-
uint64_t last_time_;
83+
bool is_initialized_ = false;
8484
uint64_t last_acc_update_us_;
8585
uint64_t last_extatt_update_us_;
8686

include/rosflight.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,6 @@ class ROSflight
6868
Sensors sensors_;
6969
StateManager state_manager_;
7070

71-
uint32_t loop_time_us;
72-
7371
/**
7472
* @brief Main initialization routine for the ROSflight autopilot flight stack
7573
*/
@@ -82,10 +80,20 @@ class ROSflight
8280

8381
uint32_t get_loop_time_us();
8482

83+
/**
84+
* @brief Checks to make sure time is going forward. Raises an error if time is detected
85+
* to be going backwards.
86+
*/
87+
bool check_time_going_forwards();
88+
8589
private:
8690
static constexpr size_t num_param_listeners_ = 7;
8791
ParamListenerInterface * const param_listeners_[num_param_listeners_] = {
8892
&comm_manager_, &command_manager_, &controller_, &estimator_, &mixer_, &rc_, &sensors_};
93+
94+
uint32_t loop_time_us_;
95+
int64_t last_time_;
96+
float dt_;
8997
};
9098

9199
} // namespace rosflight_firmware

src/controller.cpp

Lines changed: 6 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -107,28 +107,15 @@ bool Controller::is_throttle_high(float threshold) {
107107
RF_.command_manager_.combined_control().Fz.value > threshold;
108108
}
109109

110-
void Controller::run()
110+
void Controller::run(const float dt)
111111
{
112-
// Time calculation
113-
if (prev_time_us_ == 0) {
114-
prev_time_us_ = RF_.estimator_.state().timestamp_us;
115-
return;
116-
}
117-
118-
int32_t dt_us = (RF_.estimator_.state().timestamp_us - prev_time_us_);
119-
if (dt_us < 0) {
120-
RF_.state_manager_.set_error(StateManager::ERROR_TIME_GOING_BACKWARDS);
121-
return;
122-
}
123-
prev_time_us_ = RF_.estimator_.state().timestamp_us;
124-
125112
// Check if integrators should be updated
126113
bool update_integrators = (RF_.state_manager_.state().armed)
127-
&& is_throttle_high(0.1f) && dt_us < 10000;
114+
&& is_throttle_high(0.1f) && dt < 0.01;
128115

129116
// Run the PID loops
130117
Controller::Output pid_output = run_pid_loops(
131-
dt_us, RF_.estimator_.state(), RF_.command_manager_.combined_control(), update_integrators);
118+
dt, RF_.estimator_.state(), RF_.command_manager_.combined_control(), update_integrators);
132119

133120
// Add feedforward torques
134121
output_.Qx = pid_output.Qx + RF_.params_.get_param_float(PARAM_X_EQ_TORQUE);
@@ -225,14 +212,12 @@ void Controller::param_change_callback(uint16_t param_id)
225212
}
226213
}
227214

228-
Controller::Output Controller::run_pid_loops(uint32_t dt_us, const Estimator::State & state,
215+
Controller::Output Controller::run_pid_loops(const float dt, const Estimator::State & state,
229216
const control_t & command, bool update_integrators)
230217
{
231218
// Based on the control types coming from the command manager, run the appropriate PID loops
232219
Controller::Output out;
233220

234-
float dt = 1e-6 * dt_us;
235-
236221
// ROLL
237222
if (command.Qx.type == RATE) {
238223
out.Qx = roll_rate_.run(dt, state.angular_velocity.x, command.Qx.value, update_integrators);
@@ -330,7 +315,7 @@ void Controller::PID::init(float kp, float ki, float kd, float max, float min, f
330315
tau_ = tau;
331316
}
332317

333-
float Controller::PID::run(float dt, float x, float x_c, bool update_integrator)
318+
float Controller::PID::run(const float dt, float x, float x_c, bool update_integrator)
334319
{
335320
float xdot;
336321
if (dt > 0.0001f) {
@@ -348,7 +333,7 @@ float Controller::PID::run(float dt, float x, float x_c, bool update_integrator)
348333
return run(dt, x, x_c, update_integrator, xdot);
349334
}
350335

351-
float Controller::PID::run(float dt, float x, float x_c, bool update_integrator, float xdot)
336+
float Controller::PID::run(const float dt, float x, float x_c, bool update_integrator, float xdot)
352337
{
353338
// Calculate Error
354339
float error = x_c - x;

src/estimator.cpp

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ void Estimator::reset_adaptive_bias()
9191

9292
void Estimator::init()
9393
{
94-
last_time_ = 0;
94+
is_initialized_ = 0;
9595
last_acc_update_us_ = 0;
9696
last_extatt_update_us_ = 0;
9797
reset_state();
@@ -119,31 +119,22 @@ void Estimator::set_external_attitude_update(const turbomath::Quaternion & q)
119119
q_extatt_ = q;
120120
}
121121

122-
void Estimator::run()
122+
void Estimator::run(const float dt)
123123
{
124124
//
125125
// Timing Setup
126126
//
127127

128128
const uint64_t now_us = RF_.sensors_.get_imu()->header.timestamp;
129-
if (last_time_ == 0) {
130-
last_time_ = now_us;
129+
state_.timestamp_us = now_us;
130+
131+
if (!is_initialized_) {
131132
last_acc_update_us_ = now_us;
132133
last_extatt_update_us_ = now_us;
133-
return;
134-
} else if (now_us < last_time_) {
135-
// this shouldn't happen
136-
RF_.state_manager_.set_error(StateManager::ERROR_TIME_GOING_BACKWARDS);
137-
last_time_ = now_us;
134+
is_initialized_ = true;
138135
return;
139136
}
140137

141-
RF_.state_manager_.clear_error(StateManager::ERROR_TIME_GOING_BACKWARDS);
142-
143-
float dt = (now_us - last_time_) * 1e-6f;
144-
last_time_ = now_us;
145-
state_.timestamp_us = now_us;
146-
147138
// Low-pass filter accel and gyro measurements
148139
run_LPF();
149140

src/rosflight.cpp

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ ROSflight::ROSflight(Board & board, CommLinkInterface & comm_link)
4646
, rc_(*this)
4747
, sensors_(*this)
4848
, state_manager_(*this)
49+
, loop_time_us_(0)
50+
, last_time_(0)
51+
, dt_(0)
4952
{
5053
comm_link.set_listener(&comm_manager_);
5154
params_.set_listeners(param_listeners_, num_param_listeners_);
@@ -109,13 +112,13 @@ void ROSflight::run()
109112

110113
got_flags got = sensors_.run(); // IMU, GNSS, Baro, Mag, Pitot, SONAR, Battery
111114

112-
if (got.imu) {
115+
if (got.imu && check_time_going_forwards()) { // dt_ is computed by check_time_going_forwards
113116
uint64_t start = board_.clock_micros();
114-
estimator_.run();
115-
controller_.run();
117+
estimator_.run(dt_);
118+
controller_.run(dt_);
116119
mixer_.mix_output();
117120
board_.pwm_write(mixer_.raw_outputs(), Mixer::NUM_TOTAL_OUTPUTS);
118-
loop_time_us = board_.clock_micros() - start;
121+
loop_time_us_ = board_.clock_micros() - start;
119122
}
120123

121124
/*********************/
@@ -140,6 +143,31 @@ void ROSflight::run()
140143
command_manager_.run();
141144
}
142145

143-
uint32_t ROSflight::get_loop_time_us() { return loop_time_us; }
146+
uint32_t ROSflight::get_loop_time_us() { return loop_time_us_; }
147+
148+
/**
149+
* @fn bool check_time_going_forwards()
150+
* @brief Checks to make sure time is going forward. Raises an error if time is detected
151+
* to be going backwards.
152+
*/
153+
bool ROSflight::check_time_going_forwards()
154+
{
155+
const int64_t now_us = static_cast<int64_t>(sensors_.get_imu()->header.timestamp);
156+
if (last_time_ == 0) {
157+
last_time_ = now_us;
158+
return false;
159+
}
160+
dt_ = (now_us - last_time_) * 1e-6f;
161+
last_time_ = now_us;
162+
163+
// Check if time is going backwards
164+
if (dt_ < 0.0) {
165+
state_manager_.set_error(StateManager::ERROR_TIME_GOING_BACKWARDS);
166+
return false;
167+
}
168+
169+
state_manager_.clear_error(StateManager::ERROR_TIME_GOING_BACKWARDS);
170+
return true;
171+
}
144172

145173
} // namespace rosflight_firmware

test/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ add_executable(unit_tests
2323
command_manager_test.cpp
2424
estimator_test.cpp
2525
parameters_test.cpp
26+
rosflight_test.cpp
2627
)
2728
2829
target_include_directories(unit_tests PUBLIC .)

test/rosflight_test.cpp

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
#include "common.h"
2+
#include "mavlink.h"
3+
#include "test_board.h"
4+
#include "state_manager.h"
5+
6+
#include "rosflight.h"
7+
8+
9+
using namespace rosflight_firmware;
10+
11+
class ROSflightTest : public ::testing::Test
12+
{
13+
public:
14+
testBoard board;
15+
Mavlink mavlink;
16+
ROSflight rf;
17+
18+
ROSflightTest()
19+
: mavlink(board)
20+
, rf(board, mavlink)
21+
{}
22+
23+
void SetUp() override
24+
{
25+
// Initialize firmware with no errors
26+
board.backup_memory_clear();
27+
rf.init();
28+
rf.state_manager_.clear_error(
29+
rf.state_manager_.state().error_codes); // Clear All Errors to Start
30+
rf.params_.set_param_int(PARAM_PRIMARY_MIXER, 10);
31+
rf.params_.set_param_int(PARAM_CALIBRATE_GYRO_ON_ARM, false); // default to turning this off
32+
rf.params_.set_param_float(PARAM_FAILSAFE_THROTTLE, 0.0f);
33+
}
34+
};
35+
36+
TEST_F(ROSflightTest, MainLoopSetAndClearTimeGoingBackwards)
37+
{
38+
// Set initial time and step
39+
board.set_time(100);
40+
rf.sensors_.run();
41+
board.set_time(500);
42+
rf.run();
43+
44+
// Step time backward
45+
board.set_time(100);
46+
rf.run();
47+
48+
EXPECT_EQ(rf.state_manager_.state().error_codes, StateManager::ERROR_TIME_GOING_BACKWARDS);
49+
50+
// Step time forward
51+
board.set_time(500);
52+
rf.run();
53+
EXPECT_EQ(rf.state_manager_.state().error_codes, StateManager::ERROR_NONE);
54+
}
55+
56+
TEST_F(ROSflightTest, CheckTimeGoingForward)
57+
{
58+
board.set_time(10000);
59+
rf.sensors_.run();
60+
EXPECT_EQ(rf.sensors_.get_imu()->header.timestamp, 10000);
61+
rf.check_time_going_forwards();
62+
63+
board.set_time(1000);
64+
rf.sensors_.run();
65+
rf.check_time_going_forwards();
66+
67+
EXPECT_EQ(rf.sensors_.get_imu()->header.timestamp, 1000);
68+
EXPECT_EQ(rf.state_manager_.state().error_codes, StateManager::ERROR_TIME_GOING_BACKWARDS);
69+
}

0 commit comments

Comments
 (0)