feat(perception): dynamic obstacle velocity estimator (Issue #326) #336
Loading…
x
Reference in New Issue
Block a user
No description provided.
Delete Branch "sl-perception/issue-326-obstacle-velocity"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Closes #326
ObstacleVelocity.msg/ObstacleVelocityArray.msginsaltybot_scene_msgs— carries stableobstacle_id, Kalman-filteredcentroid+velocityvector,speed_mps, clusterwidth_m/depth_m/point_count, trackconfidence(0–1), andis_staticflag_obstacle_velocity.py— pure-Python tracker (no ROS2 deps):KalmanTrack— constant-velocity 2-D Kalman filter: state[x, y, vx, vy], white-noise-acceleration process noise,predict(dt)/update(centroid), coasting → alive lifecycle,confidence = min(1, age/n_init)associate()— greedy nearest-centroid matching O(N·M), strict<thresholdObstacleTracker— predict-all → associate → update-matched / spawn-new → prune-dead cycleobstacle_velocity_node.py— subscribes/scan(BEST_EFFORT); reuses_lidar_clustering.scan_to_cartesian+cluster_points; publishesObstacleVelocityArrayon/saltybot/obstacle_velocitieseach scanAlgorithm
Parameters
distance_threshold_m0.20min_points3range_min_m/range_max_m0.05/12.0max_association_dist_m0.50max_coasting_frames5n_init_frames3q_pos/q_vel0.05/0.50r_pos0.10static_speed_threshold0.10Test plan
test/test_obstacle_velocity.py— 48 tests, 0 failures (pure Python, no ROS2)KalmanTrackinit: position, velocity, confidence, alive, coasting, ageKalmanTrackpredict: dt=0 no change, dt>0 zero-vel no change, negative clamped, coasting inc, alive boundaryKalmanTrackupdate: resets coasting, increments age, shifts position, reduces covariance, confidence growth/cap, metadata storedassociate: empty cases, single match, above-threshold reject, 2×2 diagonal, M>N, N>M, nearest-wins, strict-less-than boundaryObstacleTracker: empty input, single cluster, ID sequence, same-position continuity, confidence growth, coast→die, deletion→new ID, two clusters, monotonic IDs, velocity direction, metadata, far cluster, empty-to-single-and-back, speed estimate🤖 Generated with Claude Code
Adds ObstacleVelocity/ObstacleVelocityArray msgs and an ObstacleVelocityNode that clusters /scan points, tracks each centroid with a constant-velocity Kalman filter, and publishes velocity vectors on /saltybot/obstacle_velocities. New messages (saltybot_scene_msgs): msg/ObstacleVelocity.msg — obstacle_id, centroid, velocity, speed_mps, width_m, depth_m, point_count, confidence, is_static msg/ObstacleVelocityArray.msg — array wrapper with header New files (saltybot_bringup): saltybot_bringup/_obstacle_velocity.py — pure helpers (no ROS2 deps) KalmanTrack constant-velocity 2-D KF: predict(dt) / update(centroid) coasting counter → alive flag; confidence = age/n_init associate() greedy nearest-centroid matching (O(N·M), strict <) ObstacleTracker predict-all → associate → update/spawn → prune cycle saltybot_bringup/obstacle_velocity_node.py Subscribes /scan (BEST_EFFORT); reuses _lidar_clustering helpers; publishes ObstacleVelocityArray on /saltybot/obstacle_velocities Parameters: distance_threshold_m=0.20, min_points=3, range 0.05–12m, max_association_dist_m=0.50, max_coasting_frames=5, n_init_frames=3, q_pos=0.05, q_vel=0.50, r_pos=0.10, static_speed_threshold=0.10 test/test_obstacle_velocity.py — 48 tests, all passing Modified: saltybot_scene_msgs/CMakeLists.txt — register new msgs saltybot_bringup/setup.py — add obstacle_velocity console_script Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>