Offboard mode: velocity setpoint not working in PX4 + ROS2 + Gazebo simulation

Hi everyone,

I’m running a simulation using PX4 + ROS2 + Gazebo, controlling a drone in offboard mode via the trajectory_setpoint ROS2 topic. Everything works as expected - except for one issue: I can’t get the velocity setpoint to work.

In short, I want to publish a position setpoint but also specify a desired velocity.
According to the PX4 documentation: https://docs.px4.io/main/en/flight_modes/offboard.html
This should be possible by setting position=True and velocity=False in the offboard control heartbeat signal, and then publishing both position and velocity in the trajectory_setpoint message.

However, I’m seeing strange behavior:

  • When I don’t specify a velocity, the position setpoint works perfectly.

  • When I do specify a velocity setpoint, not only does it not control the drone’s velocity, but it offsets the drone’s position by the amount given in the velocity field (similar to the issue described here: https://discuss.px4.io/t/offboard-mode-set-velocity-not-working/30104)

I’ve tried all combinations of True/False for the position and velocity flags, but no luck so far.

Here’s how I publish both the offboard control heartbeat and the trajectory setpoint:

def publish_offboard_control_heartbeat_signal(self):
    # Publish the offboard control mode.
    # See: https://docs.px4.io/main/en/flight_modes/offboard.html
    msg = OffboardControlMode()
    msg.position = True 
    msg.velocity = False
    msg.acceleration = False
    msg.attitude = False
    msg.body_rate = False
    msg.timestamp = int(self.get_clock().now().nanoseconds / 1000)
    self.offboard_control_mode_publisher.publish(msg)

def publish_position_setpoint_local(self, x: float, y: float, z: float, velocity: float = 1.0):
    # Publish the trajectory setpoint.
    msg = TrajectorySetpoint()
    msg.position = [x, y, z]
    msg.velocity = [velocity, velocity, velocity]  # DOES NOT WORK FOR WHATEVER REASON
    # msg.yaw = 1.57079  # (90 degrees)
    msg.timestamp = int(self.get_clock().now().nanoseconds / 1000)
    self.trajectory_setpoint_publisher.publish(msg)

Any help or insight would be greatly appreciated!