Description
TurtleBot4 Jazzy simulation can publish /odom.twist.twist velocity samples whose adjacent-sample acceleration exceeds the configured Create3 diffdrive acceleration limits, even when the recorded /diffdrive_controller/cmd_vel evidence is not strong enough to prove that the internal command topic itself is the direct cause.
This is distinct from the command-path issue where /diffdrive_controller/cmd_vel visibly exceeds the configured acceleration envelope. In this class, the externally published /cmd_vel is still safe and the odometry stream still violates the acceleration envelope, but the available command-path observation does not by itself isolate the bug to the limited-command topic. That points to a separate possible root location in the Gazebo physics, wheel simulation, odometry integration, or controller output path.
Impact: Consumers of /odom may observe motion dynamics that violate the Create3/TurtleBot4 controller's declared acceleration limits. Navigation, safety monitors, and downstream estimators can make incorrect assumptions if odometry acceleration is allowed to exceed the configured motion envelope under safe commands.
Environment
- Operating system: Ubuntu 24.04
- ROS version: ROS 2 Jazzy
- TurtleBot4 model:
standard
- Gazebo: Harmonic / ROS-GZ simulation
- Packages:
ros-jazzy-turtlebot4-simulator
ros-jazzy-irobot-create-nodes
ros_gz_bridge
- Launch path used by the reproducer:
- Gazebo server via
ros_gz_sim
- TurtleBot4/Create3 nodes via TurtleBot4 Jazzy bringup
- RoboFuzz split headless adapter:
src_jazzy/launch/turtlebot4_fuzz_spawn.launch.py
- Discovered via automated fuzzing:
- RoboFuzz Jazzy fork, target profile
turtlebot4_jazzy
- 1000-round campaigns:
tb4_headless_p0_p1_1000 and tb4_headless_semantic3_1000
Declared Limits
The Create3 diffdrive controller configuration declares:
linear.x.has_acceleration_limits: true
linear.x.max_acceleration: 0.9
angular.z.has_acceleration_limits: true
angular.z.max_acceleration: 7.725
angular.z.min_acceleration: -7.725
The same config publishes odometry and wheel data:
publish_rate: 62.0
open_loop: false
publish_cmd: true
publish_wheel_data: true
Therefore /odom.twist.twist should not persistently show dynamics outside the configured acceleration envelope under safe commands.
Steps to Reproduce
- Start TurtleBot4 Jazzy simulation with Gazebo and the Create3/TurtleBot4 nodes.
- Record:
/cmd_vel
/diffdrive_controller/cmd_vel
/odom
/wheel_vels
/clock
- Publish one of the following safe
geometry_msgs/msg/TwistStamped sequences.
Representative linear odom-only repro from frame 1782630920.9406638:
| step |
linear.x (m/s) |
angular.z (rad/s) |
| 1 |
-0.116 |
-0.738 |
| 2 |
+0.050 |
-0.179 |
| 3 |
-0.074 |
+0.517 |
| 4 |
+0.030 |
-0.650 |
| 5 |
-0.040 |
+0.655 |
| 6 |
-0.106 |
-0.487 |
| 7 |
+0.010 |
+0.342 |
| 8 |
+0.030 |
-0.650 |
Representative angular odom-only repro from frame 1782633493.955823:
| step |
linear.x (m/s) |
angular.z (rad/s) |
| 1 |
-0.017 |
+0.199 |
| 2 |
+0.030 |
+0.545 |
| 3 |
+0.041 |
-0.262 |
| 4 |
+0.050 |
+0.125 |
| 5 |
+0.030 |
-0.484 |
| 6 |
+0.086 |
+0.450 |
| 7 |
+0.097 |
-0.272 |
| 8 |
-0.076 |
+0.242 |
Representative combined odom-only repro from frame 1782643396.2443988:
All inputs are inside the velocity envelope:
|linear.x| <= 0.150 m/s, below linear.x.max_velocity = 0.46 m/s
|angular.z| <= 0.800 rad/s, below angular.z.max_velocity = 1.9 rad/s
Expected Behavior
The odometry velocity stream should remain consistent with the configured acceleration envelope:
|d(odom.twist.twist.linear.x)/dt| <= 0.9 m/s^2
|d(odom.twist.twist.angular.z)/dt| <= 7.725 rad/s^2
Minor numerical noise or one-sample timing jitter should not create sustained acceleration-limit violations.
Actual Behavior
The odometry stream shows sustained acceleration-envelope violations under safe commands.
Representative frame 1782630920.9406638:
TB4 linear acceleration envelope violated:
accel = 1.912 m/s^2
ratio = 2.12x
limit = 0.900 m/s^2
Representative frame 1782633493.955823:
TB4 angular acceleration envelope violated:
accel = -10.011 rad/s^2
ratio = 1.30x
limit = [-7.725, 7.725] rad/s^2
Representative frame 1782643396.2443988:
TB4 linear acceleration envelope violated:
accel = 1.822 m/s^2
ratio = 2.02x
limit = 0.900 m/s^2
TB4 angular acceleration envelope violated:
accel = -14.349 rad/s^2
ratio = 1.86x
limit = [-7.725, 7.725] rad/s^2
Latest 1000-round campaign (tb4_headless_semantic3_1000) contained these odom-only classes:
| Class |
Count |
| linear odom-only acceleration |
39 |
| angular odom-only acceleration |
1 |
| combined odom-only acceleration |
3 |
The previous 1000-round campaign (tb4_headless_p0_p1_1000) contained the same class at larger volume:
| Class |
Count |
| linear odom-only acceleration |
22 |
| angular odom-only acceleration |
47 |
| combined odom-only acceleration |
44 |
Across the latest run, the maximum observed odometry acceleration ratios were:
linear odom acceleration ratio = 2.95x
angular odom acceleration ratio = 2.33x
Why this is not a RoboFuzz input artifact
The input commands remain within the configured velocity bounds. The fuzzing campaign observed:
max |linear.x| = 0.150 m/s
max |angular.z| = 0.800 rad/s
These are below the runtime limits:
linear.x.max_velocity = 0.46 m/s
angular.z.max_velocity = 1.9 rad/s
The error is therefore not caused by out-of-range user command velocity.
Why this is unlikely to be only an oracle artifact
The executable oracle computes acceleration from /odom.twist.twist samples using odometry header timestamps when available. It ignores invalid or very large time deltas and reports a fatal acceleration bug only when:
- the ratio is very strong, or
- the acceleration stays over the tolerance for at least two adjacent intervals.
The latest 1000-round report also found that error rounds had substantial observations:
minimum /odom sample count in error rounds: 703
minimum /diffdrive_controller/cmd_vel sample count in error rounds: 446
So the finding is not explained by missing topics or an empty rosbag. Timestamp jitter remains a residual risk for borderline cases, but the representative cases above exceed the configured limit by 1.30x to 2.12x and are supported by sustained odometry evidence.
Code-Level Analysis
This issue is intentionally separated from the direct command-path acceleration issue. For the direct command-path bug, /diffdrive_controller/cmd_vel itself shows a strong acceleration spike. Here, the observable symptom is centered on /odom.twist.twist, so the likely root cause may be later in the simulation/control pipeline:
safe /cmd_vel
-> ROS-GZ / Gazebo model command path
-> wheel simulation or controller output
-> odometry integration / publication
-> /odom.twist.twist acceleration exceeds configured limits
Possible code areas to investigate:
- Gazebo model command handling for the Create3 base
irobot_create_gz_bringup / irobot_create_gz_nodes simulation-side motion path
- Create3 diffdrive odometry generation when
open_loop: false
- wheel velocity integration and
/odom publication
The root cause may still share part of the same pipeline as the command-path issue, but these odom-only cases should be tested independently because fixing the published limited-command topic may not fully fix odometry dynamics.
Suggested Fix / Next Step
Add an integration test that publishes velocity-safe /cmd_vel sequences and asserts that /odom.twist.twist does not exceed the configured acceleration envelope:
|d(odom.linear.x)/dt| <= linear.x.max_acceleration
|d(odom.angular.z)/dt| <= angular.z.max_acceleration
The test should record both /diffdrive_controller/cmd_vel and /wheel_vels so the failure can be localized to:
- command limiting,
- wheel dynamics,
- odometry calculation,
- or timestamp/publication behavior.
If /diffdrive_controller/cmd_vel is within limits but /odom still violates the envelope, the bug is downstream of command limiting and should be fixed in the wheel/physics/odometry path.
Description
TurtleBot4 Jazzy simulation can publish
/odom.twist.twistvelocity samples whose adjacent-sample acceleration exceeds the configured Create3 diffdrive acceleration limits, even when the recorded/diffdrive_controller/cmd_velevidence is not strong enough to prove that the internal command topic itself is the direct cause.This is distinct from the command-path issue where
/diffdrive_controller/cmd_velvisibly exceeds the configured acceleration envelope. In this class, the externally published/cmd_velis still safe and the odometry stream still violates the acceleration envelope, but the available command-path observation does not by itself isolate the bug to the limited-command topic. That points to a separate possible root location in the Gazebo physics, wheel simulation, odometry integration, or controller output path.Impact: Consumers of
/odommay observe motion dynamics that violate the Create3/TurtleBot4 controller's declared acceleration limits. Navigation, safety monitors, and downstream estimators can make incorrect assumptions if odometry acceleration is allowed to exceed the configured motion envelope under safe commands.Environment
standardros-jazzy-turtlebot4-simulatorros-jazzy-irobot-create-nodesros_gz_bridgeros_gz_simsrc_jazzy/launch/turtlebot4_fuzz_spawn.launch.pyturtlebot4_jazzytb4_headless_p0_p1_1000andtb4_headless_semantic3_1000Declared Limits
The Create3 diffdrive controller configuration declares:
The same config publishes odometry and wheel data:
Therefore
/odom.twist.twistshould not persistently show dynamics outside the configured acceleration envelope under safe commands.Steps to Reproduce
/cmd_vel/diffdrive_controller/cmd_vel/odom/wheel_vels/clockgeometry_msgs/msg/TwistStampedsequences.Representative linear odom-only repro from frame
1782630920.9406638:Representative angular odom-only repro from frame
1782633493.955823:Representative combined odom-only repro from frame
1782643396.2443988:All inputs are inside the velocity envelope:
|linear.x| <= 0.150 m/s, belowlinear.x.max_velocity = 0.46 m/s|angular.z| <= 0.800 rad/s, belowangular.z.max_velocity = 1.9 rad/sExpected Behavior
The odometry velocity stream should remain consistent with the configured acceleration envelope:
Minor numerical noise or one-sample timing jitter should not create sustained acceleration-limit violations.
Actual Behavior
The odometry stream shows sustained acceleration-envelope violations under safe commands.
Representative frame
1782630920.9406638:Representative frame
1782633493.955823:Representative frame
1782643396.2443988:Latest 1000-round campaign (
tb4_headless_semantic3_1000) contained these odom-only classes:The previous 1000-round campaign (
tb4_headless_p0_p1_1000) contained the same class at larger volume:Across the latest run, the maximum observed odometry acceleration ratios were:
Why this is not a RoboFuzz input artifact
The input commands remain within the configured velocity bounds. The fuzzing campaign observed:
These are below the runtime limits:
The error is therefore not caused by out-of-range user command velocity.
Why this is unlikely to be only an oracle artifact
The executable oracle computes acceleration from
/odom.twist.twistsamples using odometry header timestamps when available. It ignores invalid or very large time deltas and reports a fatal acceleration bug only when:The latest 1000-round report also found that error rounds had substantial observations:
So the finding is not explained by missing topics or an empty rosbag. Timestamp jitter remains a residual risk for borderline cases, but the representative cases above exceed the configured limit by 1.30x to 2.12x and are supported by sustained odometry evidence.
Code-Level Analysis
This issue is intentionally separated from the direct command-path acceleration issue. For the direct command-path bug,
/diffdrive_controller/cmd_velitself shows a strong acceleration spike. Here, the observable symptom is centered on/odom.twist.twist, so the likely root cause may be later in the simulation/control pipeline:Possible code areas to investigate:
irobot_create_gz_bringup/irobot_create_gz_nodessimulation-side motion pathopen_loop: false/odompublicationThe root cause may still share part of the same pipeline as the command-path issue, but these odom-only cases should be tested independently because fixing the published limited-command topic may not fully fix odometry dynamics.
Suggested Fix / Next Step
Add an integration test that publishes velocity-safe
/cmd_velsequences and asserts that/odom.twist.twistdoes not exceed the configured acceleration envelope:The test should record both
/diffdrive_controller/cmd_veland/wheel_velsso the failure can be localized to:If
/diffdrive_controller/cmd_velis within limits but/odomstill violates the envelope, the bug is downstream of command limiting and should be fixed in the wheel/physics/odometry path.