How to run:
git clone https://github.com/cornellev/ml_laneseg.git
PIXI INSTRUCTIONS: (all from the mllaneseg folder itself) pixi install pixi run build pixi run run-node pixi run start-foxglove
DOCKER INSTRUCTIONS: docker build -t lane_segr_final -f Dockerfile_cuda.jetson .
docker run -it --rm
--runtime nvidia
--privileged
--network host
-v /dev:/dev
-v $(pwd):/ros2_ws
-v ~/zed_models:/usr/local/zed/resources
lane_segr_final bash
colcon build --packages-select zed_ml_inference --symlink-install source install/setup.bash
ros2 run zed_ml_inference lane_segmentation_node3dlanes
FOR TESTING THE MODEL: go to src/zed_ml_inference/zed_ml_inference change code for the picture that you want to test on jsut lfd roadseg byt iself: python3 test_model.py
for the upgraded version with multilane + intersection capabilities: python3 test_model_multilane.py
| Topic | Type | Notes |
|---|---|---|
lane/camera_raw |
sensor_msgs/Image |
raw ZED left image |
lane/overlay |
sensor_msgs/Image |
colour overlay + HUD |
lane/points/lanes |
sensor_msgs/PointCloud2 |
x,y,z,crossable,point_type,lane_id |
lane/costmap |
nav_msgs/OccupancyGrid |
planner-ready, lane rule applied |
lane/costmap/lane_layer |
nav_msgs/OccupancyGrid |
markings only, rule NOT applied |
lane/costmap/lanes_as_obstacles |
std_msgs/Bool |
current toggle state (latched) |
lane/costmap/set_lanes_as_obstacles |
std_msgs/Bool |
toggle command in |
lane/costmap values: -1 unknown, 0 free drivable surface, 100 lethal,
anything in between is a soft cost. The grid lies on the ground plane in the
camera frame; the ground height is re-estimated from the road surface every
frame, so no hand-measured camera height is needed.
lanes_as_obstacles (default true) governs crossable (dashed) markings
only. Solid lines stay lethal either way, because crossing them is illegal
rather than merely undesirable.
# permit lane changes — dashed lines drop to a soft cost
ros2 topic pub --once /lane/costmap/set_lanes_as_obstacles std_msgs/Bool '{data: false}'
# back to lane keeping
ros2 topic pub --once /lane/costmap/set_lanes_as_obstacles std_msgs/Bool '{data: true}'
# same switch as a parameter
ros2 param set /lane_segmentation_node lanes_as_obstacles falselane/costmap/lane_layer publishes the markings with the rule not applied
(-1 none, 0 crossable, 1 centreline, 100 solid) so a future lane-change
planner can make the decision itself instead of relying on the toggle.
Costmap geometry params (set at launch): costmap_resolution (0.10 m),
costmap_forward_min/max (-2/20 m), costmap_lateral_half (6 m).
Live-tunable via ros2 param set: costmap_crossable_cost (20),
costmap_inflation_radius (0 = off), costmap_inflation_cost (60),
costmap_ground_tolerance (0.40 m).
The costmap geometry and the lane toggle are unit-tested — no camera, GPU or model weights required:
pixi run test
# or directly:
pytest src/zed_ml_inference/test/test_costmap.py -vThe tests cover grid dimensions and the origin pose, free/unknown/lethal
classification, the ground-height filter (so a car or wall never becomes free
space), out-of-range points being dropped rather than wrapping to the far side
of the grid, both states of lanes_as_obstacles, the lane layer staying
independent of the toggle, inflation, cost clamping, and the column layout
shared with the lane/points/lanes PointCloud2.
The few tests that build an actual OccupancyGrid message skip themselves when
nav_msgs is not importable, so the suite also runs on a plain dev machine
with just numpy, opencv-python and pytest.