Skip to content

Commit 12d2f69

Browse files
committed
differential: centralize mode management, resets and checks
1 parent fb96504 commit 12d2f69

23 files changed

+1243
-752
lines changed

src/modules/rover_differential/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ add_subdirectory(DifferentialRateControl)
3636
add_subdirectory(DifferentialAttControl)
3737
add_subdirectory(DifferentialVelControl)
3838
add_subdirectory(DifferentialPosControl)
39+
add_subdirectory(DifferentialDriveModes)
3940

4041
px4_add_module(
4142
MODULE modules__rover_differential
@@ -49,6 +50,9 @@ px4_add_module(
4950
DifferentialAttControl
5051
DifferentialVelControl
5152
DifferentialPosControl
53+
DifferentialAutoMode
54+
DifferentialManualMode
55+
DifferentialOffboardMode
5256
px4_work_queue
5357
rover_control
5458
pure_pursuit

src/modules/rover_differential/DifferentialActControl/DifferentialActControl.cpp

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -99,21 +99,6 @@ Vector2f DifferentialActControl::computeInverseKinematics(float throttle, const
9999
throttle + speed_diff_normalized);
100100
}
101101

102-
void DifferentialActControl::manualManualMode()
103-
{
104-
manual_control_setpoint_s manual_control_setpoint{};
105-
_manual_control_setpoint_sub.copy(&manual_control_setpoint);
106-
rover_steering_setpoint_s rover_steering_setpoint{};
107-
rover_steering_setpoint.timestamp = hrt_absolute_time();
108-
rover_steering_setpoint.normalized_speed_diff = manual_control_setpoint.roll;
109-
_rover_steering_setpoint_pub.publish(rover_steering_setpoint);
110-
rover_throttle_setpoint_s rover_throttle_setpoint{};
111-
rover_throttle_setpoint.timestamp = hrt_absolute_time();
112-
rover_throttle_setpoint.throttle_body_x = manual_control_setpoint.throttle;
113-
rover_throttle_setpoint.throttle_body_y = 0.f;
114-
_rover_throttle_setpoint_pub.publish(rover_throttle_setpoint);
115-
}
116-
117102
void DifferentialActControl::stopVehicle()
118103
{
119104
actuator_motors_s actuator_motors{};

src/modules/rover_differential/DifferentialActControl/DifferentialActControl.hpp

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -67,11 +67,6 @@ class DifferentialActControl : public ModuleParams
6767
*/
6868
void updateActControl();
6969

70-
/**
71-
* @brief Publish roverThrottleSetpoint and roverSteeringSetpoint from manualControlSetpoint.
72-
*/
73-
void manualManualMode();
74-
7570
/**
7671
* @brief Stop the vehicle by sending 0 commands to motors and servos.
7772
*/
@@ -96,12 +91,9 @@ class DifferentialActControl : public ModuleParams
9691
uORB::Subscription _actuator_motors_sub{ORB_ID(actuator_motors)};
9792
uORB::Subscription _rover_steering_setpoint_sub{ORB_ID(rover_steering_setpoint)};
9893
uORB::Subscription _rover_throttle_setpoint_sub{ORB_ID(rover_throttle_setpoint)};
99-
uORB::Subscription _manual_control_setpoint_sub{ORB_ID(manual_control_setpoint)};
10094

10195
// uORB publications
102-
uORB::Publication<actuator_motors_s> _actuator_motors_pub{ORB_ID(actuator_motors)};
103-
uORB::Publication<rover_steering_setpoint_s> _rover_steering_setpoint_pub{ORB_ID(rover_steering_setpoint)};
104-
uORB::Publication<rover_throttle_setpoint_s> _rover_throttle_setpoint_pub{ORB_ID(rover_throttle_setpoint)};
96+
uORB::Publication<actuator_motors_s> _actuator_motors_pub{ORB_ID(actuator_motors)};
10597

10698
// Variables
10799
hrt_abstime _timestamp{0};

src/modules/rover_differential/DifferentialAttControl/DifferentialAttControl.cpp

Lines changed: 19 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,6 @@ using namespace time_literals;
3838
DifferentialAttControl::DifferentialAttControl(ModuleParams *parent) : ModuleParams(parent)
3939
{
4040
_rover_rate_setpoint_pub.advertise();
41-
_rover_throttle_setpoint_pub.advertise();
42-
_rover_attitude_setpoint_pub.advertise();
4341
_rover_attitude_status_pub.advertise();
4442
updateParams();
4543
}
@@ -52,21 +50,20 @@ void DifferentialAttControl::updateParams()
5250
_max_yaw_rate = _param_ro_yaw_rate_limit.get() * M_DEG_TO_RAD_F;
5351
}
5452

53+
// Set up PID controller
5554
_pid_yaw.setGains(_param_ro_yaw_p.get(), 0.f, 0.f);
5655
_pid_yaw.setIntegralLimit(_max_yaw_rate);
5756
_pid_yaw.setOutputLimit(_max_yaw_rate);
57+
58+
// Set up slew rate
5859
_adjusted_yaw_setpoint.setSlewRate(_max_yaw_rate);
5960
}
6061

6162
void DifferentialAttControl::updateAttControl()
6263
{
63-
const hrt_abstime timestamp_prev = _timestamp;
64+
hrt_abstime timestamp_prev = _timestamp;
6465
_timestamp = hrt_absolute_time();
65-
_dt = math::constrain(_timestamp - timestamp_prev, 1_ms, 5000_ms) * 1e-6f;
66-
67-
if (_vehicle_control_mode_sub.updated()) {
68-
_vehicle_control_mode_sub.copy(&_vehicle_control_mode);
69-
}
66+
const float dt = math::constrain(_timestamp - timestamp_prev, 1_ms, 5000_ms) * 1e-6f;
7067

7168
if (_vehicle_attitude_sub.updated()) {
7269
vehicle_attitude_s vehicle_attitude{};
@@ -75,17 +72,20 @@ void DifferentialAttControl::updateAttControl()
7572
_vehicle_yaw = matrix::Eulerf(vehicle_attitude_quaternion).psi();
7673
}
7774

78-
if (_vehicle_control_mode.flag_control_attitude_enabled && _vehicle_control_mode.flag_armed && runSanityChecks()) {
79-
80-
if (_vehicle_control_mode.flag_control_manual_enabled || _vehicle_control_mode.flag_control_offboard_enabled) {
81-
generateAttitudeAndThrottleSetpoint();
82-
}
75+
if (_rover_attitude_setpoint_sub.updated()) {
76+
rover_attitude_setpoint_s rover_attitude_setpoint{};
77+
_rover_attitude_setpoint_sub.copy(&rover_attitude_setpoint);
78+
_yaw_setpoint = rover_attitude_setpoint.yaw_setpoint;
79+
}
8380

84-
generateRateSetpoint();
81+
if (PX4_ISFINITE(_yaw_setpoint)) {
82+
const float yaw_rate_setpoint = RoverControl::attitudeControl(_adjusted_yaw_setpoint, _pid_yaw, _max_yaw_rate,
83+
_vehicle_yaw, _yaw_setpoint, dt);
84+
rover_rate_setpoint_s rover_rate_setpoint{};
85+
rover_rate_setpoint.timestamp = _timestamp;
86+
rover_rate_setpoint.yaw_rate_setpoint = math::constrain(yaw_rate_setpoint, -_max_yaw_rate, _max_yaw_rate);
87+
_rover_rate_setpoint_pub.publish(rover_rate_setpoint);
8588

86-
} else { // Reset pid and slew rate when attitude control is not active
87-
_pid_yaw.resetIntegral();
88-
_adjusted_yaw_setpoint.setForcedValue(0.f);
8989
}
9090

9191
// Publish attitude controller status (logging only)
@@ -97,96 +97,6 @@ void DifferentialAttControl::updateAttControl()
9797

9898
}
9999

100-
void DifferentialAttControl::generateAttitudeAndThrottleSetpoint()
101-
{
102-
const bool stab_mode_enabled = _vehicle_control_mode.flag_control_manual_enabled
103-
&& !_vehicle_control_mode.flag_control_position_enabled && _vehicle_control_mode.flag_control_attitude_enabled;
104-
105-
if (stab_mode_enabled && _manual_control_setpoint_sub.updated()) { // Stab Mode
106-
manual_control_setpoint_s manual_control_setpoint{};
107-
108-
if (_manual_control_setpoint_sub.update(&manual_control_setpoint)) {
109-
110-
rover_throttle_setpoint_s rover_throttle_setpoint{};
111-
rover_throttle_setpoint.timestamp = _timestamp;
112-
rover_throttle_setpoint.throttle_body_x = manual_control_setpoint.throttle;
113-
rover_throttle_setpoint.throttle_body_y = 0.f;
114-
_rover_throttle_setpoint_pub.publish(rover_throttle_setpoint);
115-
116-
const float yaw_delta = math::interpolate<float>(math::deadzone(manual_control_setpoint.roll,
117-
_param_ro_yaw_stick_dz.get()), -1.f, 1.f, -_max_yaw_rate / _param_ro_yaw_p.get(),
118-
_max_yaw_rate / _param_ro_yaw_p.get());
119-
120-
if (fabsf(yaw_delta) > FLT_EPSILON
121-
|| fabsf(rover_throttle_setpoint.throttle_body_x) < FLT_EPSILON) { // Closed loop yaw rate control
122-
_stab_yaw_ctl = false;
123-
const float yaw_setpoint = matrix::wrap_pi(_vehicle_yaw + yaw_delta);
124-
rover_attitude_setpoint_s rover_attitude_setpoint{};
125-
rover_attitude_setpoint.timestamp = _timestamp;
126-
rover_attitude_setpoint.yaw_setpoint = yaw_setpoint;
127-
_rover_attitude_setpoint_pub.publish(rover_attitude_setpoint);
128-
129-
} else { // Closed loop yaw control if the yaw rate input is zero (keep current yaw)
130-
if (!_stab_yaw_ctl) {
131-
_stab_yaw_setpoint = _vehicle_yaw;
132-
_stab_yaw_ctl = true;
133-
}
134-
135-
rover_attitude_setpoint_s rover_attitude_setpoint{};
136-
rover_attitude_setpoint.timestamp = _timestamp;
137-
rover_attitude_setpoint.yaw_setpoint = _stab_yaw_setpoint;
138-
_rover_attitude_setpoint_pub.publish(rover_attitude_setpoint);
139-
}
140-
141-
142-
}
143-
144-
} else if (_vehicle_control_mode.flag_control_offboard_enabled) { // Offboard attitude control
145-
trajectory_setpoint_s trajectory_setpoint{};
146-
_trajectory_setpoint_sub.copy(&trajectory_setpoint);
147-
148-
if (_offboard_control_mode_sub.updated()) {
149-
_offboard_control_mode_sub.copy(&_offboard_control_mode);
150-
}
151-
152-
const bool offboard_att_control = _offboard_control_mode.attitude && !_offboard_control_mode.position
153-
&& !_offboard_control_mode.velocity;
154-
155-
if (offboard_att_control && PX4_ISFINITE(trajectory_setpoint.yaw)) {
156-
rover_attitude_setpoint_s rover_attitude_setpoint{};
157-
rover_attitude_setpoint.timestamp = _timestamp;
158-
rover_attitude_setpoint.yaw_setpoint = trajectory_setpoint.yaw;
159-
_rover_attitude_setpoint_pub.publish(rover_attitude_setpoint);
160-
}
161-
}
162-
}
163-
164-
void DifferentialAttControl::generateRateSetpoint()
165-
{
166-
if (_rover_attitude_setpoint_sub.updated()) {
167-
_rover_attitude_setpoint_sub.copy(&_rover_attitude_setpoint);
168-
}
169-
170-
if (_rover_rate_setpoint_sub.updated()) {
171-
_rover_rate_setpoint_sub.copy(&_rover_rate_setpoint);
172-
}
173-
174-
// Check if a new rate setpoint was already published from somewhere else
175-
if (_rover_rate_setpoint.timestamp > _last_rate_setpoint_update
176-
&& _rover_rate_setpoint.timestamp > _rover_attitude_setpoint.timestamp) {
177-
return;
178-
}
179-
180-
const float yaw_rate_setpoint = RoverControl::attitudeControl(_adjusted_yaw_setpoint, _pid_yaw, _max_yaw_rate,
181-
_vehicle_yaw, _rover_attitude_setpoint.yaw_setpoint, _dt);
182-
183-
_last_rate_setpoint_update = _timestamp;
184-
rover_rate_setpoint_s rover_rate_setpoint{};
185-
rover_rate_setpoint.timestamp = _timestamp;
186-
rover_rate_setpoint.yaw_rate_setpoint = math::constrain(yaw_rate_setpoint, -_max_yaw_rate, _max_yaw_rate);
187-
_rover_rate_setpoint_pub.publish(rover_rate_setpoint);
188-
}
189-
190100
bool DifferentialAttControl::runSanityChecks()
191101
{
192102
bool ret = true;
@@ -197,13 +107,9 @@ bool DifferentialAttControl::runSanityChecks()
197107

198108
if (_param_ro_yaw_p.get() < FLT_EPSILON) {
199109
ret = false;
200-
201-
if (_prev_param_check_passed) {
202-
events::send<float>(events::ID("differential_att_control_conf_invalid_yaw_p"), events::Log::Error,
203-
"Invalid configuration of necessary parameter RO_YAW_P", _param_ro_yaw_p.get());
204-
}
110+
events::send<float>(events::ID("differential_att_control_conf_invalid_yaw_p"), events::Log::Error,
111+
"Invalid configuration of necessary parameter RO_YAW_P", _param_ro_yaw_p.get());
205112
}
206113

207-
_prev_param_check_passed = ret;
208114
return ret;
209115
}

src/modules/rover_differential/DifferentialAttControl/DifferentialAttControl.hpp

Lines changed: 15 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -48,15 +48,9 @@
4848
#include <uORB/Publication.hpp>
4949
#include <uORB/Subscription.hpp>
5050
#include <uORB/topics/rover_rate_setpoint.h>
51-
#include <uORB/topics/rover_throttle_setpoint.h>
52-
#include <uORB/topics/vehicle_control_mode.h>
53-
#include <uORB/topics/manual_control_setpoint.h>
51+
#include <uORB/topics/rover_attitude_setpoint.h>
5452
#include <uORB/topics/vehicle_attitude.h>
5553
#include <uORB/topics/rover_attitude_status.h>
56-
#include <uORB/topics/rover_attitude_setpoint.h>
57-
#include <uORB/topics/actuator_motors.h>
58-
#include <uORB/topics/offboard_control_mode.h>
59-
#include <uORB/topics/trajectory_setpoint.h>
6054

6155
/**
6256
* @brief Class for differential attitude control.
@@ -72,63 +66,41 @@ class DifferentialAttControl : public ModuleParams
7266
~DifferentialAttControl() = default;
7367

7468
/**
75-
* @brief Update attitude controller.
69+
* @brief Generate and publish roverRateSetpoint from roverAttitudeSetpoint.
7670
*/
7771
void updateAttControl();
7872

79-
protected:
80-
/**
81-
* @brief Update the parameters of the module.
82-
*/
83-
void updateParams() override;
84-
85-
private:
8673
/**
87-
* @brief Generate and publish roverAttitudeSetpoint and roverThrottleSetpoint from manualControlSetpoint (Stab Mode)
88-
* or trajectorySetpoint (Offboard attitude control).
74+
* @brief Reset attitude controller.
8975
*/
90-
void generateAttitudeAndThrottleSetpoint();
91-
92-
/**
93-
* @brief Generate and publish roverRateSetpoint from roverAttitudeSetpoint.
94-
*/
95-
void generateRateSetpoint();
76+
void reset() {_pid_yaw.resetIntegral(); _yaw_setpoint = NAN;};
9677

9778
/**
9879
* @brief Check if the necessary parameters are set.
9980
* @return True if all checks pass.
10081
*/
10182
bool runSanityChecks();
10283

84+
protected:
85+
/**
86+
* @brief Update the parameters of the module.
87+
*/
88+
void updateParams() override;
89+
90+
private:
10391
// uORB subscriptions
104-
uORB::Subscription _vehicle_control_mode_sub{ORB_ID(vehicle_control_mode)};
105-
uORB::Subscription _manual_control_setpoint_sub{ORB_ID(manual_control_setpoint)};
106-
uORB::Subscription _trajectory_setpoint_sub{ORB_ID(trajectory_setpoint)};
107-
uORB::Subscription _offboard_control_mode_sub{ORB_ID(offboard_control_mode)};
10892
uORB::Subscription _vehicle_attitude_sub{ORB_ID(vehicle_attitude)};
109-
uORB::Subscription _actuator_motors_sub{ORB_ID(actuator_motors)};
11093
uORB::Subscription _rover_attitude_setpoint_sub{ORB_ID(rover_attitude_setpoint)};
111-
uORB::Subscription _rover_rate_setpoint_sub{ORB_ID(rover_rate_setpoint)};
112-
vehicle_control_mode_s _vehicle_control_mode{};
113-
rover_attitude_setpoint_s _rover_attitude_setpoint{};
114-
rover_rate_setpoint_s _rover_rate_setpoint{};
115-
offboard_control_mode_s _offboard_control_mode{};
11694

11795
// uORB publications
118-
uORB::Publication<rover_rate_setpoint_s> _rover_rate_setpoint_pub{ORB_ID(rover_rate_setpoint)};
119-
uORB::Publication<rover_throttle_setpoint_s> _rover_throttle_setpoint_pub{ORB_ID(rover_throttle_setpoint)};
120-
uORB::Publication<rover_attitude_setpoint_s> _rover_attitude_setpoint_pub{ORB_ID(rover_attitude_setpoint)};
121-
uORB::Publication<rover_attitude_status_s> _rover_attitude_status_pub{ORB_ID(rover_attitude_status)};
96+
uORB::Publication<rover_rate_setpoint_s> _rover_rate_setpoint_pub{ORB_ID(rover_rate_setpoint)};
97+
uORB::Publication<rover_attitude_status_s> _rover_attitude_status_pub{ORB_ID(rover_attitude_status)};
12298

12399
// Variables
124-
hrt_abstime _timestamp{0};
125-
hrt_abstime _last_rate_setpoint_update{0};
126100
float _vehicle_yaw{0.f};
127-
float _dt{0.f};
101+
hrt_abstime _timestamp{0};
128102
float _max_yaw_rate{0.f};
129-
float _stab_yaw_setpoint{0.f}; // Yaw setpoint if rover is doing yaw control in stab mode
130-
bool _stab_yaw_ctl{false}; // Indicates if rover is doing yaw control in stab mode
131-
bool _prev_param_check_passed{true};
103+
float _yaw_setpoint{NAN};
132104

133105
// Controllers
134106
PID _pid_yaw;
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
############################################################################
2+
#
3+
# Copyright (c) 2025 PX4 Development Team. All rights reserved.
4+
#
5+
# Redistribution and use in source and binary forms, with or without
6+
# modification, are permitted provided that the following conditions
7+
# are met:
8+
#
9+
# 1. Redistributions of source code must retain the above copyright
10+
# notice, this list of conditions and the following disclaimer.
11+
# 2. Redistributions in binary form must reproduce the above copyright
12+
# notice, this list of conditions and the following disclaimer in
13+
# the documentation and/or other materials provided with the
14+
# distribution.
15+
# 3. Neither the name PX4 nor the names of its contributors may be
16+
# used to endorse or promote products derived from this software
17+
# without specific prior written permission.
18+
#
19+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20+
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21+
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22+
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23+
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24+
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25+
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
26+
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27+
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28+
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29+
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30+
# POSSIBILITY OF SUCH DAMAGE.
31+
#
32+
############################################################################
33+
34+
add_subdirectory(DifferentialAutoMode)
35+
add_subdirectory(DifferentialManualMode)
36+
add_subdirectory(DifferentialOffboardMode)

0 commit comments

Comments
 (0)