Skip to content

Add rover setpoints and rover example #140

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 11 commits into
base: main
Choose a base branch
from

Conversation

chfriedrich98
Copy link

@chfriedrich98 chfriedrich98 commented Aug 13, 2025

This PR adds the rover setpoints that were exposed to DDS in PX4/PX4-Autopilot#25074 to the available setpoints.
All the rover setpoints are in their own folder/group to clearly separate them from the regular setpoints as they will have no effect on other vehicle types.

It also adds a mode example for rovers: Rover Velocity Mode.
This manual mode fits between Stabilized and Position mode:
Based on the manual input this mode publishes a RoverVelocitySetpoints and a RoverRateSetpoint.
Unlike Stabilized mode, this mode can utilize closed loop speed control and unlike Position mode, this mode does not requrie a position estimate.

New mode was tested in SITL with the ackermann rover: https://review.px4.io/plot_app?log=b3074d19-c15d-46e4-9bfe-5e505cf668eb
image

@chfriedrich98 chfriedrich98 self-assigned this Aug 13, 2025
@chfriedrich98 chfriedrich98 force-pushed the pr-rover_setpoints branch 2 times, most recently from a8cab35 to f92c1eb Compare August 13, 2025 13:22
@chfriedrich98 chfriedrich98 marked this pull request as ready for review August 14, 2025 07:20
Copy link
Collaborator

@bkueng bkueng left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice.
The setpoint classes do not need to map 1:1 to a PX4 message. They can also have multiple update methods.
Can you design the setpoint types according to different usages, and combine the thrust and yaw accordingly?
You can look at the fixed-wing sp for an example.

Since more vehicle types are being added, can you move the fixedwing and goto setpoint types also into their respective subdirectories?

Comment on lines 39 to 47
const float speed = _manual_control_input->throttle() * kMaxSpeed;
_rover_velocity_setpoint->update(speed, NAN, NAN);

// Rate is not updated through the setpoint type to avoid overriding vehicle control mode.
const float yaw_rate = _manual_control_input->roll() * kMaxYawRate * M_PI / 180.f;
px4_msgs::msg::RoverRateSetpoint sp{};
sp.yaw_rate_setpoint = yaw_rate;
sp.timestamp = 0; // Let PX4 set the timestamp
_rover_rate_setpoint_pub->publish(sp);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it is possible to combine them I would rather do that in the RoverVelocitySetpointType,
e.g. add a method update(velocity, yaw_rate). Then it's clear how it can be used.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I combined the setpoints in 78a7fe7. Not quite like you suggested, see #140 (comment) for reasoning.

@@ -40,6 +40,12 @@ set(HEADER_FILES
include/px4_ros2/control/setpoint_types/experimental/attitude.hpp
include/px4_ros2/control/setpoint_types/experimental/rates.hpp
include/px4_ros2/control/setpoint_types/experimental/trajectory.hpp
include/px4_ros2/control/setpoint_types/rover/rover_position.hpp
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd remove the redundant prefix

Suggested change
include/px4_ros2/control/setpoint_types/rover/rover_position.hpp
include/px4_ros2/control/setpoint_types/rover/position.hpp

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implemented in 78a7fe7

~RoverAttitudeSetpointType() override = default;

Configuration getConfiguration() override;
float desiredUpdateRateHz() override {return 100.f;}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

30 is probably enough for all of them (?)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reduced it to 30 in e9ef220

/**
* @brief Send a rover attitude setpoint to the flight controller.
*
* @param yaw_setpoint [rad] [@range -inf, inf] [@frame NED] Yaw setpoint
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you remove the @range and expand them? Doxygen does not like these.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed descriptions in d2638ff

*
* @param yaw_setpoint [rad] [@range -inf, inf] [@frame NED] Yaw setpoint
*/
void update(float yaw_setpoint);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How is thrust controlled then?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Combined the setpoints in 78a7fe7.

*
* @param position_ned [m] [@range -inf, inf] [@frame NED] Target position
* @param start_ned [m] [@range -inf, inf] [@frame NED] [@invalid NaN Defaults to vehicle position] Start position which specifies a line for the rover to track
* @param cruising_speed [m/s] [@range 0, inf] [@invalid NaN Defaults to maximum speed] Cruising speed
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you use std::optional instead of NaN for optional arguments?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implemented in d2638ff

@chfriedrich98
Copy link
Author

chfriedrich98 commented Aug 20, 2025

@bkueng Thank you for the review!

The setpoint classes do not need to map 1:1 to a PX4 message. They can also have multiple update methods.
Can you design the setpoint types according to different usages, and combine the thrust and yaw accordingly?

This actually prompted me to have another look at the rover setpoints on PX4 side and I made some adjustments s.t. it is easier to understand which combination of setpoints are valid (for reference PX4/PX4-Autopilot#25447).
TLDR: The rover modules use a hierarchical structure to propogate setpoints (i.e. the "highest" valid setpoint will override the rest):
rover_graphics-rover_control_structure_update2 drawio
With this hierarchy there are now clear rules for accessing rover setpoints through the API:
Publishing a position setpoint will override all other setpoints and for all other cases we require the following:
One of the setpoints on the "left" (speed or throttle) and one of the setpoints on the "right" (attitude, rate or steering) have to be specified. All combinations of "left" and "right" setpoints are valid.

In 78a7fe7 I exposed all of these valid combinations as their own setpoint.
The reason I did not combine them by having multiple update methods is because they all have different configs.
(Is there a way to change configs when different update functions are called?)

@@ -0,0 +1,32 @@
cmake_minimum_required(VERSION 3.5)
project(rover_velocity_mode_cpp)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's not an issue but I just saw difference in built target names) so maybe it's gonna be better:
project(example_rover_velocity_mode_cpp)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense, changed in 53fbe9c

@chfriedrich98
Copy link
Author

CI checks seem to fail because they are not using the latest version of px4_msgs which includes the message change RoverVelocitySetpoint $$\rightarrow$$ RoverSpeedSetpoint. 🤔

@chfriedrich98 chfriedrich98 requested a review from bkueng August 20, 2025 14:18
Copy link
Collaborator

@bkueng bkueng left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason I did not combine them by having multiple update methods is because they all have different configs.
(Is there a way to change configs when different update functions are called?)

It makes sense as you have it now. Different configs require different setpoint types (although you could create a class that combines multiple), as different configs (i.e. active controllers) are typically sufficiently different in their uses.

CI checks seem to fail because they are not using the latest version of px4_msgs which includes the message change

The message sync takes a while, but now they should be available.

Can you later on also add some docs to https://docs.px4.io/main/en/ros2/px4_ros2_control_interface.html#setpoint-types?

Comment on lines +26 to +31
{"fmu/in/rover_attitude_setpoint"}, \
{"fmu/in/rover_position_setpoint"}, \
{"fmu/in/rover_rate_setpoint"}, \
{"fmu/in/rover_speed_setpoint"}, \
{"fmu/in/rover_steering_setpoint"}, \
{"fmu/in/rover_throttle_setpoint"}, \
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How stable do you think these messages are?
They should (eventually) be versioned by moving them under versioned and adding uint32 MESSAGE_VERSION = 0 (https://github.com/PX4/PX4-Autopilot/blob/main/msg/versioned/ActuatorMotors.msg#L6).
If you expect changes, I'd move the setpoint classes here under experimental

Copy link
Author

@chfriedrich98 chfriedrich98 Aug 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We decided against adding the rover setpoints to versioned because there is still the possiblity that we extend them to all ground vehicles (PX4/PX4-Autopilot#25074 (comment)).
Added them to experimental in 91b79f7 as you suggested.

* @brief Send a rover position setpoint to the flight controller.
*
* @param position_ned [m] Target position in NED frame. Takes values in [-inf, inf].
* @param start_ned [m] Start position which specifies a line for the rover to track (Optional, defaults to vehicle position). Takes values in [-inf, inf].
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can also use std::optional if it's optional

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

implemented in f68797f

@chfriedrich98 chfriedrich98 requested a review from bkueng August 22, 2025 11:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants