Skip to content

[Bug] Rover Differential - Doesn't turn in Mission Mode (v1.17 Stable) #27497

@DanieleAzz

Description

@DanieleAzz

Describe the bug

Hi there,

I've built a differential rover and flashed a custom 'rover.px4board' target for it. After the initial configuration, I am unable to get it to navigate successfully in Mission mode.

Actual Behavior:

The rover moves back and forth, trying to reach the first waypoint without success. It looks like it tries to make a turn, fails to do so, and ends up driving back and forth over the same spot.

Expected Behavior:

The rover should calculate the heading to the waypoint, turn, and drive straight to it, similar to how it behaves in SITL.

Troubleshooting & Context

  • Manual/RC Modes: In Manual, Stabilized, and Position modes, the rover drives forward and turns perfectly following RC commands (I just need to fine-tune the PID). Note: I noticed it doesn't turn at full throttle, likely because there is no motor headroom left to distribute power for differential steering.
  • ROS 2 Custom Mode: Following the documentation, the rover turns perfectly when using RoverSpeedSteeringSetpointType. However, it fails to turn using RoverPositionSetpointType. I wrote a script to simulate a GoTo mode (reading 9 GPS coordinates, translating to NED, and sending them via position_setpoint_->update()), and it exhibits the same back-and-forth behavior as Mission mode.
  • SITL: Running make px4_sitl gz_rover_differential, every test I’ve made using ROS2 Custom mode works perfectly. The issue only happens on real hardware.

Because it works in SITL and manual modes, my guess is that there is an issue with the position controller, or I have a misconfigured parameter causing the rover to fail its navigation loop.

Thank you for your help!

Flight Log / Additional Information

This is my Hardware configuration:

  • Frame: Lynxmotion A4WD3
  • Motor Controller: Sabertooth 2x12
  • Flight Controller: Cubepilot Orange Plus
  • Carrier Board: Airbot mini carrier board PRO v2
  • GPS: Here4
  • Companion Computer: RPi 5

Software & Firmware Details

PX4 Version: v1.17 Stable (Branch: release/1.17)
Custom Board Target: rover.px4board (I would love to contribute this back! 😄)
rover.px4board build flags:

CONFIG_MODULES_AIRSPEED_SELECTOR=n
CONFIG_MODULES_FLIGHT_MODE_MANAGER=n
CONFIG_MODULES_FW_ATT_CONTROL=n
CONFIG_MODULES_FW_AUTOTUNE_ATTITUDE_CONTROL=n
CONFIG_MODULES_FW_MODE_MANAGER=n
CONFIG_MODULES_FW_LATERAL_LONGITUDINAL_CONTROL=n
CONFIG_MODULES_FW_RATE_CONTROL=n
CONFIG_MODULES_MC_ATT_CONTROL=n
CONFIG_MODULES_MC_AUTOTUNE_ATTITUDE_CONTROL=n
CONFIG_MODULES_MC_HOVER_THRUST_ESTIMATOR=n
CONFIG_MODULES_MC_POS_CONTROL=n
CONFIG_MODULES_MC_RATE_CONTROL=n
CONFIG_MODULES_VTOL_ATT_CONTROL=n
CONFIG_DRIVERS_ROBOCLAW=y
CONFIG_MODULES_ROVER_ACKERMANN=y
CONFIG_MODULES_ROVER_DIFFERENTIAL=y
CONFIG_MODULES_ROVER_MECANUM=y

Mavlink Shell Output

nsh> ver all
HW arch: CUBEPILOT_CUBEORANGEPLUS
PX4 git-hash: 812b0fbca6bfa32f475e93cc521978df333e2cd0
PX4 version: 1.17.0 0 (17891328)
PX4 git-branch: release/1.17
OS: NuttX
OS version: Release 11.0.0 (184549631)
OS git-hash: fb2fadf6f599c1406f052db013efd00a2518e72c
Build datetime: May 27 2026 12:51:44
Build uri: localhost
Build variant: rover
Toolchain: GNU GCC, 10.2.1 20201103 (release)
PX4GUID: 000600000000373434333233510d00290022
MCU: STM32H7[4|5]xxx, rev. V

Flight Logs

  • Test 1 (Position/GoTo Mode): Flight Review Log
    • Behavior: Outside using the Custom mode called "ROS2 Go To". The rover moves very slowly back and forth. You can see it trying hard to turn but failing.
  • Test 2 (Speed/Steering Mode): Flight Review Log
    • Behavior: Outside using the Custom mode called "ROS 2 Circle". The rover acts as expected, driving a circle until it hit an object and almost flipped (hence the high vibrations).

Code Snippets

  • Test 1 (Position/GoTo Mode):
static const std::string kName = "ROS2 Go To";

class MyGotoMode : public px4_ros2::ModeBase
{
public:
    MyGotoMode(rclcpp::Node& node) : ModeBase(node, kName) {
        position_setpoint_ = std::make_shared<px4_ros2::RoverPositionSetpointType>(*this);
    };

    void onActivate() override { 
        active_ = true; 
        RCLCPP_INFO(node().get_logger(), "==> 'ROS 2 Go To' Mode Activated via QGC!");
    }

    void onDeactivate() override { 
        active_ = false; 
        RCLCPP_INFO(node().get_logger(), "==> 'ROS 2 Go To' Mode Deactivated!");
    }

    bool isActive() const { 
        return active_; 
    }

    void updatePosition(float x, float y){
        // Pack x North and Y East in meters into a Eigen 2D vector:
        Eigen::Vector2f target_position_ned(x,y);

        float cruising_speed = .5;
        
        // Update the position setpoint with it
        position_setpoint_->update(target_position_ned, std::nullopt, cruising_speed);
    }

private:
    bool active_ = false;
    std::shared_ptr<px4_ros2::RoverPositionSetpointType> position_setpoint_;
};
  • Test 2 (Speed/Steering Mode):
static const std::string kName = "ROS 2 Circle";

class MyCircleMode : public px4_ros2::ModeBase
{
public:
    MyCircleMode(rclcpp::Node& node) : ModeBase(node, kName) {
        steering_setpoint_ = std::make_shared<px4_ros2::RoverSpeedSteeringSetpointType>(*this);
    };

    void onActivate() override { 
        active_ = true; 
        RCLCPP_INFO(node().get_logger(), "==> 'ROS 2 Circle' Mode Activated via QGC!");
    }

    void onDeactivate() override { 
        active_ = false; 
        RCLCPP_INFO(node().get_logger(), "==> 'ROS 2 Circle' Mode Deactivated!");
    }

    bool isActive() const { return active_; }

    void updateVelocity(float speed, float steering){
        steering_setpoint_->update(speed, steering);
    }

private:
    bool active_ = false;
    std::shared_ptr<px4_ros2::RoverSpeedSteeringSetpointType> steering_setpoint_;
};

Metadata

Metadata

Assignees

No one assigned

    Labels

    kind:bugSomething is broken or behaving incorrectly.vehicle:roverRover-specific behavior.

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions