Skip to content

Commit dfc69b5

Browse files
committed
offboard: give watchdog grace period from when setpoints start
process_heartbeat() stops setpoint streaming when the vehicle is not in offboard mode more than 3 seconds after _last_started. However, _last_started is only ever written in start(), so before the first start() it is still default-initialized (epoch 0) and the 3-second guard is always satisfied: any heartbeat arriving between the first set_*() and start() resets the setpoint state, and start() then fails with NoSetpointSet. In real-time use the window between set_*() and start() is rarely hit at 1 Hz heartbeats. In lockstep simulation with a speed factor this becomes frequent: at 30x, PX4's heartbeats arrive every ~33 ms of wall time, and the PX4 SITL integration tests failed on Offboard::start() roughly one run in three. Stamp _last_started whenever streaming transitions out of NotActive, so the watchdog's grace period covers the gap between the first setpoint and start(), as intended by the existing 'don't stop too eagerly' comment. We also rename _last_started because the name isn't quite right. Signed-off-by: Julian Oes <julian@oes.ch>
1 parent 4dd3167 commit dfc69b5

2 files changed

Lines changed: 24 additions & 4 deletions

File tree

cpp/src/mavsdk/plugins/offboard/offboard_impl.cpp

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ Offboard::Result OffboardImpl::start()
5151
if (_mode == Mode::NotActive) {
5252
return Offboard::Result::NoSetpointSet;
5353
}
54-
_last_started = _time.steady_time();
54+
_watchdog_grace_start = _time.steady_time();
5555
}
5656

5757
return offboard_result_from_command_result(_system_impl->set_flight_mode(FlightMode::Offboard));
@@ -81,7 +81,7 @@ void OffboardImpl::start_async(Offboard::ResultCallback callback)
8181
}
8282
return;
8383
}
84-
_last_started = _time.steady_time();
84+
_watchdog_grace_start = _time.steady_time();
8585
}
8686

8787
_system_impl->set_flight_mode_async(
@@ -134,6 +134,7 @@ Offboard::Result OffboardImpl::set_position_ned(Offboard::PositionNedYaw positio
134134
_call_every_cookie =
135135
_system_impl->add_call_every([this]() { send_position_ned(); }, SEND_INTERVAL_S);
136136

137+
note_setpoints_started();
137138
_mode = Mode::PositionNed;
138139
} else {
139140
// We're already sending these kind of setpoints. Since the setpoint change, let's
@@ -159,6 +160,7 @@ Offboard::Result OffboardImpl::set_position_global(Offboard::PositionGlobalYaw p
159160
_call_every_cookie =
160161
_system_impl->add_call_every([this]() { send_position_global(); }, SEND_INTERVAL_S);
161162

163+
note_setpoints_started();
162164
_mode = Mode::PositionGlobalAltRel;
163165
} else {
164166
// We're already sending these kind of setpoints. Since the setpoint change, let's
@@ -184,6 +186,7 @@ Offboard::Result OffboardImpl::set_velocity_ned(Offboard::VelocityNedYaw velocit
184186
_call_every_cookie =
185187
_system_impl->add_call_every([this]() { send_velocity_ned(); }, SEND_INTERVAL_S);
186188

189+
note_setpoints_started();
187190
_mode = Mode::VelocityNed;
188191
} else {
189192
// We're already sending these kind of setpoints. Since the setpoint change, let's
@@ -210,6 +213,7 @@ Offboard::Result OffboardImpl::set_position_velocity_ned(
210213
_call_every_cookie = _system_impl->add_call_every(
211214
[this]() { send_position_velocity_ned(); }, SEND_INTERVAL_S);
212215

216+
note_setpoints_started();
213217
_mode = Mode::PositionVelocityNed;
214218
} else {
215219
// We're already sending these kind of setpoints. Since the setpoint change, let's
@@ -240,6 +244,7 @@ Offboard::Result OffboardImpl::set_position_velocity_acceleration_ned(
240244
_call_every_cookie = _system_impl->add_call_every(
241245
[this]() { send_position_velocity_acceleration_ned(); }, SEND_INTERVAL_S);
242246

247+
note_setpoints_started();
243248
_mode = Mode::PositionVelocityAccelerationNed;
244249
} else {
245250
// We're already sending these kind of setpoints. Since the setpoint change, let's
@@ -265,6 +270,7 @@ Offboard::Result OffboardImpl::set_acceleration_ned(Offboard::AccelerationNed ac
265270
_call_every_cookie = _system_impl->add_call_every(
266271
[this]() { send_acceleration_ned(); }, SEND_INTERVAL_S);
267272

273+
note_setpoints_started();
268274
_mode = Mode::AccelerationNed;
269275
} else {
270276
// We're already sending these kind of setpoints. Since the setpoint change, let's
@@ -291,6 +297,7 @@ OffboardImpl::set_velocity_body(Offboard::VelocityBodyYawspeed velocity_body_yaw
291297
_call_every_cookie =
292298
_system_impl->add_call_every([this]() { send_velocity_body(); }, SEND_INTERVAL_S);
293299

300+
note_setpoints_started();
294301
_mode = Mode::VelocityBody;
295302
} else {
296303
// We're already sending these kind of setpoints. Since the setpoint change, let's
@@ -316,6 +323,7 @@ Offboard::Result OffboardImpl::set_attitude(Offboard::Attitude attitude)
316323
_call_every_cookie =
317324
_system_impl->add_call_every([this]() { send_attitude(); }, SEND_INTERVAL_S);
318325

326+
note_setpoints_started();
319327
_mode = Mode::Attitude;
320328
} else {
321329
// We're already sending these kind of setpoints. Since the setpoint change, let's
@@ -341,6 +349,7 @@ Offboard::Result OffboardImpl::set_attitude_rate(Offboard::AttitudeRate attitude
341349
_call_every_cookie =
342350
_system_impl->add_call_every([this]() { send_attitude_rate(); }, SEND_INTERVAL_S);
343351

352+
note_setpoints_started();
344353
_mode = Mode::AttitudeRate;
345354
} else {
346355
// We're already sending these kind of setpoints. Since the setpoint change, let's
@@ -366,6 +375,7 @@ Offboard::Result OffboardImpl::set_actuator_control(Offboard::ActuatorControl ac
366375
_call_every_cookie = _system_impl->add_call_every(
367376
[this]() { send_actuator_control(); }, SEND_INTERVAL_S);
368377

378+
note_setpoints_started();
369379
_mode = Mode::ActuatorControl;
370380
} else {
371381
// We're already sending these kind of values. Since the value changes, let's
@@ -851,14 +861,23 @@ void OffboardImpl::process_heartbeat(const mavlink_message_t& message)
851861
// possibly stale heartbeats for some time.
852862
std::lock_guard<std::mutex> lock(_mutex);
853863
if (!offboard_mode_active && _mode != Mode::NotActive &&
854-
_time.elapsed_since_s(_last_started) > 3.0) {
864+
_time.elapsed_since_s(_watchdog_grace_start) > 3.0) {
855865
// It seems that we are no longer in offboard mode but still trying to send
856866
// setpoints. Let's stop for now.
857867
stop_sending_setpoints();
858868
}
859869
}
860870
}
861871

872+
void OffboardImpl::note_setpoints_started()
873+
{
874+
// We assume that we already acquired the mutex in this function.
875+
876+
if (_mode == Mode::NotActive) {
877+
_watchdog_grace_start = _time.steady_time();
878+
}
879+
}
880+
862881
void OffboardImpl::stop_sending_setpoints()
863882
{
864883
// We assume that we already acquired the mutex in this function.

cpp/src/mavsdk/plugins/offboard/offboard_impl.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ class OffboardImpl : public PluginImplBase {
6868
offboard_result_from_command_result(MavlinkCommandSender::Result result);
6969

7070
void stop_sending_setpoints();
71+
void note_setpoints_started();
7172

7273
Time _time{};
7374

@@ -94,7 +95,7 @@ class OffboardImpl : public PluginImplBase {
9495
Offboard::Attitude _attitude{};
9596
Offboard::AttitudeRate _attitude_rate{};
9697
Offboard::ActuatorControl _actuator_control{};
97-
SteadyTimePoint _last_started{};
98+
SteadyTimePoint _watchdog_grace_start{};
9899

99100
CallEveryHandler::Cookie _call_every_cookie{};
100101

0 commit comments

Comments
 (0)