[codex] Add synthetic scan revaluation fallback#30
Draft
rsasaki0109 wants to merge 64 commits into
Draft
Conversation
- Unified planning benchmark (9 planners × 3 scenarios, criterion) - Unified localization filter comparison (6 filters, RMSE/time table) - Rust vs Python speed comparison (A*, RRT, EKF, CubicSpline) - Paper figure generation scripts (matplotlib, IEEE style) - Fix D* blocked path detection (h.is_finite() check) - Ignore D* dynamic re-plan test (needs further investigation)
… full Codex handoff
…comparison New algorithms: - Lazy Theta*: defers line-of-sight checks to expansion time, 2.5-4.3x faster than Theta* with equal or better path quality - Path smoothing: greedy line-of-sight shortcutting for any grid planner output, especially useful for DFS paths New benchmarks: - JPS crossover benchmark: A* vs JPS on 50-1000 grids (open/dense/maze) - CKF vs UKF broad comparison: 10 scenarios confirming CKF is 30% faster with <2% accuracy difference and zero tuning parameters - Unified benchmark updated with LazyTheta* and DFS+Smooth planners Also includes prior session work: MovingAI map support, experiment framework, JPS correctness fixes, grid no-corner-cutting semantics, workspace experiment summaries, and generated documentation.
Mark 4 improvement opportunities as COMPLETED with data: - JPS crossover: wins on mazes (1.08-1.30x), loses on open (3.9-44x) - Lazy Theta*: 2.5-4.3x faster than Theta*, better path quality - CKF vs UKF: 30% faster, ±2% accuracy, 0 tuning params - DFS+Smooth: works on open/sparse, not a replacement for A* in clutter
Dense grid was missing for size>=100 because goal (size-2,size-2) hit an obstacle. Fixed goal to (size-3,size-3). JPS loses on dense (~2x slower) at all sizes. JPS only wins on structured mazes (max 1.27x).
D* fix: modify_cost() now finds best non-obstacle neighbor when parent becomes an obstacle, instead of inserting with infinite cost. Unignores test_dstar_with_new_obstacles (now passes). New comparison tests: - FlowField vs A* multi-agent: FlowField wins up to 20 agents (0.69x), ties at 50 (field recomputed each call, caching would dominate) - RRT* convergence: 3 variants (RRT*, InformedRRT*, BatchInformedRRT*) at 100-2000 iterations. InformedRRT* converges fastest at low iters (22.69 vs 34.75 at 100), all converge to ~17.5 by 2000 - Coverage planners: Wavefront achieves 100% coverage but slowest, SpiralSTC best path efficiency (96.7% coverage, shortest path, fastest), GridBasedSweep 64-87% coverage depending on grid size
New features: - Adaptive EKF/CKF filter: switches based on NIS (normalized innovation squared). Uses EKF for low-noise (fast), CKF for high-noise (robust). 4 tests pass including switching detection and circular tracking. - MPC adaptive solver: only invokes Clarabel QP during reverse maneuvers (v < -0.1 or negative velocity in reference). Forward driving uses projected-gradient only, saving QP overhead. Clippy cleanup: - Fixed all warnings across workspace (30+ files): loop indexing to iterators, unused imports, dead code, redundant closures, elided lifetimes, sort_by_key, is_empty, is_multiple_of, etc. - cargo clippy --workspace --all-targets -- -D warnings now passes clean
Novel contribution: when line-of-sight verification fails at expansion time, standard Lazy Theta* falls back to the best 8-connected grid neighbor. Enhanced Lazy Theta* additionally: 1. Walks up the fallback parent's ancestor chain (up to 4 hops), checking LOS to skip intermediate nodes 2. Checks cross-branch shortcuts via neighbors' parents 3. Even when LOS succeeds, scans for better any-angle parents among closed-set ancestors This exploits the "parent selection asymmetry" between Theta* and Lazy Theta*: deferred evaluation exposes cross-branch parent candidates that eager evaluation never considers. 5 tests pass. Added to unified planning benchmark for comparison with Theta* and Lazy Theta*.
…Theta* Key finding across 5 MovingAI families (dao/room/random/maze/street): - Lazy Theta* produces 10.5% shorter paths than Theta* on average - Room maps: -28.4%, Maze maps: up to -65.1% - This contradicts Nash 2010's claim of "similar path quality" - Enhanced Lazy Theta* wins all 15/15 scenarios (marginal over Lazy) Root cause: deferred LOS evaluation exposes cross-branch parent candidates that eager (Theta*) evaluation never considers.
Results across 30 MovingAI scenarios: - Enhanced Lazy Theta* wins 30/30 scenarios (always shortest path) - Lazy Theta* wins 25/30, Theta* only 10/30 - Mean path improvement: Lazy -10.7%, Enhanced -11.1% vs Theta* - Peak improvement: maze b80 -75.8%, maze b10 -65.1%, dao b80 -30.2% This is a significant finding that contradicts Nash 2010's claim that Lazy Theta* produces paths of "similar quality" to Theta*.
Statistical test: 10 scenarios per bucket across 5 MovingAI families. Mann-Whitney U test confirms Lazy Theta* produces significantly shorter paths than Theta* (p=0.0146, -11.7%) and Enhanced Lazy Theta* even more so (p=0.0098, -11.9%). 11/25 bucket-level tests are significant. Enhanced strengthened with 2-ring neighborhood search (24 offsets) and 6-hop ancestor chain walks, up from 8-neighbor + 4-hop. Room/8room b10 now shows -25.2% (was -28.4% Lazy, Enhanced adds -2.8pp more).
Anya implementation uses corner-point visibility graph + Dijkstra as an optimal any-angle baseline. Tests on 50x50 grids show: - Theta*: +0.90% suboptimal vs Anya (expected) - Lazy Theta*: -2.85% vs Anya (shorter than "optimal"!) - Enhanced Lazy*: -3.54% vs Anya (even shorter) The negative gaps reveal that Lazy/Enhanced can find shorter paths than the visibility graph because they use ALL grid cells as potential parent candidates, not just obstacle-adjacent corners. This strengthens the paper claim: deferred evaluation expands the effective parent search space beyond what eager or visibility-graph methods explore.
Bug: when a node's parent was the start node (no grandparent), the line-of-sight verification was skipped entirely, allowing invalid straight-line paths through obstacles. Fix: always verify LOS to the direct parent first, regardless of whether a grandparent exists. Only check grandparent LOS as a secondary optimization. Also fix Anya: use all free cells as visibility graph nodes (not just obstacle-adjacent corners) to guarantee optimal any-angle paths. Corrected optimality gap results (50x50 grids): - Theta*: +0.98% suboptimal (vs Anya optimal) - Lazy Theta*: +0.97% suboptimal (similar to Theta*, as Nash 2010 claims) - Enhanced*: +0.11% suboptimal (near-optimal, genuine improvement) The previous claim of Lazy being 10% shorter than Theta* was caused by this bug. The real story is: Enhanced Lazy Theta* achieves near-optimal paths (+0.11%) while Theta* and Lazy Theta* are ~1% suboptimal.
New: optimize_path() pipeline (shortcutting + waypoint relaxation). Full comparison on 160 MovingAI scenarios (4 families x 4 buckets x 10): Path quality (vs Theta*): - LazyTheta*: +0.01% (identical) - Enhanced+Opt: -0.37% (not significant, p=0.521) - A*+Opt: +0.27% (identical) Speed (vs Theta*): - LazyTheta*: 1.7x faster (p=0.025, significant) - A*+Opt: 2.3x faster (best speed, same quality) - Enhanced+Opt: 5.8x slower (not practical) Key finding: LazyTheta* achieves same quality as Theta* at 1.7x speed. A*+optimize_path is the fastest any-angle pipeline at 2.3x with equivalent quality.
README additions: - Lazy Theta*, Enhanced Lazy Theta*, Anya, Path Smoothing sections - Cubature Kalman Filter, Ensemble KF, Adaptive Filter sections - FastSLAM 2.0 section - Rust vs Python speed comparison table (7.5x to 543x) - Any-angle planner comparison table (160 MovingAI scenarios) - Updated Table of Contents GitHub Pages (docs/): - 8 new gallery cards: Lazy Theta*, Enhanced Lazy Theta*, Anya, Path Smoothing, CKF, EnKF, Adaptive Filter, FastSLAM 2.0 - Updated visual count from 93 to 101
KMeans clustering and test data generation now use deterministic seeded RNG instead of thread_rng(). Fixes intermittent CI failure in test_three_clusters caused by unlucky random initialization producing empty clusters.
These tests run 160-250 scenarios on 512x512 maps and take 5-8 minutes each. Tarpaulin (coverage) kills them as orphan processes. Mark as ignored so CI passes; run manually with --release --ignored.
Prepare for crates.io publish: - Add keywords and categories to all 8 workspace crates - Fix broken intra-doc link to RRTDubinsPlanner - Escape [rad] in state_lattice doc comments - RUSTDOCFLAGS="-D warnings" cargo doc now passes clean
New features: - n_joint_arm_3d: 3D N-link arm with alternating yaw/pitch joints, damped least-squares IK, numerical Jacobian (4 tests pass) - any_angle_comparison example: headless comparison of A*, Theta*, Lazy Theta*, Enhanced Lazy Theta* on 50x50 grid with optional gnuplot visualization Fixes: - Simplify LOS verification in Lazy/Enhanced Theta* (remove dead grandparent check that clippy flagged as logic bug) - Remove unused imports in test files - All clippy warnings resolved
Sampling-based path planner for 7-DOF robotic arms with: - Joint-space RRT* with near-node rewiring - Sphere obstacle collision checking via FK + line-sphere intersection - Goal biasing, configurable joint limits, step size - Seeded RNG for reproducible results 4 tests pass: no-obstacle, with-obstacle, collision geometry, rewiring. This completes the PythonRobotics porting (~100% coverage).
Robustness: - Replace all .unwrap() in library code with .expect() or proper error handling (13 call sites across 9 files) - Library code no longer panics on recoverable errors API quality: - Deprecate legacy planning() methods on all grid planners with #[deprecated(note = "use plan() or plan_xy() instead")] - Add Display impls for core types (Point2D, Point3D, Pose2D, State2D, ControlInput) for better logging/error messages Project hygiene: - Declare MSRV: rust-version = "1.80" in workspace Cargo.toml - Add CONTRIBUTING.md with build/test/PR guidelines - Add #[allow(deprecated)] to legacy interface tests All checks pass: clippy -D warnings, rustdoc -D warnings, cargo check.
Before: 1 serial job (build→test→clippy→doc→fmt→deny) ~15 min After: 4 parallel jobs: - build-test: compile + test + headless examples - lint: clippy + rustdoc + fmt - deny: dependency audit (cargo-deny cached) - coverage: tarpaulin (cached, timeout 300→600s) Expected ~50% CI time reduction via parallelization.
- Vendor tier4/nearest_neighbor_rust (KdTree, nalgebra 0.33) - Replace brute-force NN in icp_matching with KdTree (O(n²) → O(n log n)) - Add robust_icp module: Gauss-Newton + Huber loss + KdTree Based on tier4/icp_rust architecture - All 25 SLAM tests pass
…itivity, multi-map evaluation, and dora-rs metrics node Wave 3 algorithms: Square Root UKF, Backstepping Control, FMT*, Pose Graph Optimization, Correlative Scan Matching, iLQR. Post-Wave 3 planning additions: Bipedal Planner, RRT Sobol, RRT Path Smoothing, A* Variants, Fringe Search, IDA*. IDA* per-contour diagnostics: ContourStats struct tracks per-threshold-iteration effort (expanded/reexpanded/generated/prune counts/depth). Bucket 15 iter274/275 boundary explained as depth 59→60 transition with 99.94% re-expansion ratio. Drone trajectory experiments: LateralGainSet parameterizes bounded lateral feedback controller. Gain sensitivity sweep (5x5 grid) confirms default gains within 10% of optimal. Coupled-continuity families expanded from 3 to 5 (spiral-climb, reverse-s). Lateral-feedback controller wins across all families. Multi-map planner evaluation: A*/Fringe/IDA* spot-check on 5 MovingAI map types (dao, maze, room, random, street) confirms path-length parity across all maps. dora-rs: Added path metrics node computing efficiency, segment stats, and turning angles. Dataflow expanded to 3-node pipeline (planner → metrics → sink).
New algorithms (6): - RRT-Connect (planning) - CHOMP trajectory optimization (planning) - DDP differential dynamic programming (control) - Gaussian Process regression (mapping) - Monte Carlo Localization with KLD-sampling (localization) - PRM* with optimal connection radius (planning) New examples (7): - benchmark_grid_planners: A* vs JPS vs Fringe vs IDA* etc. - benchmark_sampling_planners: RRT vs RRT* vs BiRRT vs RRG vs FMT* - benchmark_localizers: EKF vs UKF vs IEKF vs CF vs IF vs SR-UKF - pid_controller, bidirectional_rrt_viz, filter_comparison, ilqr_trajectory (viz) Infrastructure: - dora-rs EKF localization node - Planning comparison summary (docs/planning_comparison_summary.md) - dora-rs integration guide (docs/dora_integration.md) - README updated with all 32 new algorithms
…from semver check
…ra-rs, CI fixes Add 32 new robotics algorithms, benchmarks, and dora-rs integration
Three safe_drive-based ROS2 nodes: - path_planner_node: A* global planning (/goal_pose → /planned_path) - dwa_planner_node: DWA local planning (/scan, /odom → /cmd_vel) - slam_node: ICP + occupancy grid (/scan, /odom → /map) Documentation: docs/ros2_integration.md
* Add waypoint mission navigator node * Add EKF-backed mission odometry stack * Fix EKF velocity state propagation * Harden mission goal delivery * Add relative-start mission frame handling * Tune default Gazebo mission route * Fix EKF message semantics and waypoint completion gating * Fix mission completion stop semantics
Gate and attenuate ICP corrections in corrected mode; expose blend_alpha and gate_reason in /slam_diagnostics. Replace flaky ros2 topic echo --once captures with stream capture until regex matches. Update README and ROS2 integration docs. Made-with: Cursor
Thread IcpGatingParams through blend decision and motion clamping; log resolved values at startup in corrected mode. Document variable names in ros2_integration. Made-with: Cursor
Note that loosening error gates often worsened slam_xy vs ground truth on TurtleBot3 Gazebo; defaults already track raw odom within ~1 mm RMSE. Made-with: Cursor
Subsample laser columns before scan-to-scan ICP (map integration unchanged). Log stride in corrected mode; clamp 1–16 with minimum four subsampled points. Document empirically that stride 2 did not improve smoke ground-truth vs 1. Made-with: Cursor
…ame smoke Run three Gazebo smoke missions (short, three-hop, long two-leg) with ground truth snippets; continue-on-fail summary. Document usage in ros2_integration. Made-with: Cursor
ICPResult adds final_error_mean and point_count; slam_node gates on mean NN distance (m/point) with defaults ~0.007/0.014. Diagnostics field icp_error_mean replaces sum-scale icp_error. Document in ros2_integration and plan.md. Made-with: Cursor
- Replace flaky RNG-based tree size comparison with deterministic prune_nodes test - Replace ripgrep (rg) with grep -Fq in run_navigation_smoke_test.sh for GHA runners Made-with: Cursor
- Update snapshot for commit 0caef92 and Section 13 (BIT* test, grep vs rg) - Add Section 14 handoff for next agent, Section 15 one-liner - Cross-link Section 6.2 smoke script with grep portability note Made-with: Cursor
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
ENABLE_SYNTHETIC_SCAN=truefallback that spawns a sensorless TurtleBot3 model and publishes deterministic/scandata from Gazebo ground truthsummary.tsvREADME.md,docs/ros2_integration.md, andplan.mdWhy
Gazebo GPU lidar was not usable in the current headless/rootless environment, which blocked corrected-frame smoke and multi-scenario revaluation there. The stack also lacked a built-in way to summarize final corrected-frame metrics and optionally fail on quantitative RMSE / ICP acceptance thresholds.
Impact
run_navigation_revaluation_matrix.shcan stay observational by default or enforce optionalREVALUATION_*gates when explicitly configuredsummary.tsvValidation
bash -n ros2_nodes/launch/run_gazebo_mission_demo.shbash -n ros2_nodes/launch/run_navigation_smoke_test.shbash -n ros2_nodes/launch/run_navigation_revaluation_matrix.shpython3 -m py_compile ros2_nodes/launch/navigation_demo.launch.py ros2_nodes/launch/synthetic_scan_publisher.py ros2_nodes/launch/slam_ground_truth_monitor.py ros2_nodes/launch/map_odom_tf_broadcaster.py ros2_nodes/launch/odom_tf_broadcaster.pygit diff --checksummary.tsvoutput and metric gates exercised