ros-controls / ros-controls/ros2_controllers

bug(tricycle_controller): strict inequality for M_PI_2 boundary causes speed scale to drop to ~0 instead of 0.01 limit

Open Beginner friendly
#2,391 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug
Dominant language
C++
Stars
834
Forks
530
Avg merge
18h 3m
Merged PRs (30d)
19

Description

Describe the bug
In TricycleController::update(), there is an attenuation mechanism that scales down the wheel speed (Ws_write) based on the steering angle error (alpha_delta) between the target wheel angle (alpha_write) and the current reading (alpha_read).

However, there is an edge case at the boundary of M_PI_2 (90 degrees) where a strict inequality check (alpha_delta > M_PI_2) prevents the controller from applying the intended 1% speed limit (0.01). Instead, it falls through to the else branch and calculates cos(alpha_delta) where alpha_delta is exactly M_PI_2. Due to floating-point precision, cos(M_PI_2) yields a value near zero (~6.12e-17), which virtually halts the wheel instead of scaling it to the intended 1% creep speed.

To Reproduce

  1. Command a spin action (set linear.x = 0.0 m/s, angular.z = 0.5 rad/s).
  2. The controller sets alpha_write to exactly M_PI_2 (~1.5707963268 rad).
  3. At the initial transition state (where current steering angle alpha_read is 0.0 rad), alpha_delta becomes exactly M_PI_2.
  4. The condition alpha_delta > M_PI_2 evaluates to false because they are equal.
  5. The execution flow falls through to the else block, calculating scale = cos(M_PI_2).
  6. The output wheel speed is scaled to near-zero (e.g., 2.47e-16 rad/s for an unattenuated target speed of 4.04 rad/s) during the first control cycle, instead of the intended 1% speed limit (0.04 rad/s).

Here is the empirical CSV printout captured from the cmd_ackermann topic at a 50Hz control rate:

# steering_angle, steering_angle_velocity, speed, acceleration, jerk
0.0,0.0,2.915452003479004,0.0,0.0   # straight driving
0.0,0.0,0.0,0.0,0.0                 # timeout stop
1.5707963705062866,0.0,2.4725010844361235e-16,0.0,0.0  # Transition transient (cos boundary error!)
1.5707963705062866,0.0,4.037900924682617,0.0,0.0       # Steady state (angle tracking complete)
Expected behavior

When the steering error is exactly at or larger than M_PI_2, the speed scale should be limited to 0.01 to allow a slow creep motion rather than dropping to 10^-16 (virtually a zero-command dead zone).

Code Reference

https://github.com/ros-controls/ros2_controllers/blob/jazzy/tricycle_controller/src/tricycle_controller.cpp#L185-L188

Proposed Solution

Change the strict inequality > to >= in the boundary check to catch the exact boundary case:

-  else if (alpha_delta > M_PI_2)
+  else if (alpha_delta >= M_PI_2)
   {
     scale = 0.01;
   }
Environment
  • OS: Ubuntu 24.04 LTS (Noble Numbat)
  • ROS 2 Distro: Jazzy Jalisco
  • Version or commit hash: ros2_controllers version 4.40.1

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in tricycle_controller/src/tricycle_controller.cpp at TricycleController::update(), around the referenced boundary check, and trace how alpha_delta determines the speed scale. Verify the exact M_PI_2 transition behavior against the reported CSV values; done means the boundary uses the intended 0.01 limit rather than a near-zero cosine result.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
robotics
Issue type
Bug
Difficulty
1/5
Estimated time
Under an hour
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
84/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.