Skip to content

fix(cmd_vel): add hysteresis to deadzone snap and trajectory gates#181

Draft
xiaolefang-dm wants to merge 3 commits into
mainfrom
fix/cmdvel-deadzone-hysteresis
Draft

fix(cmd_vel): add hysteresis to deadzone snap and trajectory gates#181
xiaolefang-dm wants to merge 3 commits into
mainfrom
fix/cmdvel-deadzone-hysteresis

Conversation

@xiaolefang-dm

@xiaolefang-dm xiaolefang-dm commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Summary

Add hysteresis (dual enter/exit thresholds) to three bang-bang-prone gates in the velocity pipeline:

1. Linear/angular deadzone snap (cmd_vel_control.py)

  • Before: Single min_effective_*_speed threshold — when planner target hovered near the boundary, cmd_vel snapped between 0 and min every cycle.
  • After: Engage motion at min_effective_*_speed; once engaged, stay engaged until target drops below a lower *_engage_threshold (0.04). Eliminates bang-bang on noisy targets.

2. Forward/reverse trajectory gate (planning_node.py)

  • Before: Single enter_threshold = 0.30 — gate flipped every cycle when front clearance hovered at the boundary.
  • After: Enter reverse mode at 0.30, require 0.40 clearance to exit. Hysteresis state stored in self._reverse_mode.

3. Rotate-first heading gate (cmd_vel_control.py)

  • Before: Single 0.45 rad threshold — flip-flopped between drive+turn and rotate-only when heading jittered near boundary.
  • After: Engage at rotate_first_enter_threshold = 0.45 rad (~26°), stay engaged until heading error drops below rotate_first_exit_threshold = 15°.

All hysteresis states are reset on pause, nav deactivation, and reverse command for clean transitions.

Changed files

  • tinynav/core/planning_node.py — +12 -1
  • tinynav/platforms/cmd_vel_control.py — +57 -10

Testing

  • Test on hardware with obstacle-rich scenarios
  • Verify no bang-bang at trajectory boundaries
  • Confirm smooth pause/resume transitions

xiaolefang added 3 commits July 2, 2026 15:31
The min_effective_linear/angular_speed snap-to-min-or-zero logic had a
single threshold, so a planner target hovering near min_effective_*
caused the executed command to bang-bang between 0 and min. Add
engage/release hysteresis (reusing the previously-unused
linear_engage_threshold, plus a new angular_engage_threshold) so once
moving, the robot stays engaged until the target genuinely drops below
the lower threshold.
front_clearance <= 0.30m flipped the reverse-vs-forward trajectory
pool with a single threshold, causing the gate to oscillate every
cycle when the robot idled right at the boundary. Add a wider exit
threshold (0.40m) so once reverse mode engages, it only releases once
clearance genuinely improves.
The rotate-first gate (forward motion blocked, in-place turn only)
used a single 0.45 rad heading-error threshold, so it flip-flopped
every cycle when the planner's selected heading jittered near the
boundary (common near obstacles). Add a lower exit threshold (15 deg)
so once rotate-only mode engages, forward motion only resumes once
heading error genuinely drops.
@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown
cloc github.com/AlDanial/cloc v 2.04 T=0.18 s (238.6 files/s, 38169.6 lines/s)
Language files blank comment code
Python 13 672 330 3804
Markdown 4 155 6 426
C++ 4 60 38 409
Bourne Shell 15 41 9 272
Dockerfile 1 31 32 204
JSON 2 8 0 58
TOML 1 4 0 58
make 1 18 15 49
CMake 1 4 0 17
-------- -------- -------- -------- --------
SUM: 42 993 430 5297

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.

1 participant