lidar_obstacle_detector

SS47816MIT活跃维护

面向 ROS 1/2 的实时 3D 激光雷达障碍物检测工具,集地面分割、聚类、跟踪与轨迹预测于一体,单核 CPU 约 10ms 处理一帧,可选 TensorRT 加速的 CenterPoint。

Real-time 3D LiDAR obstacle detection, tracking & trajectory prediction for ROS 1 / ROS 2: ground segmentation, clustering, 2.5D occupancy, optional GPU CenterPoint (TensorRT). ~10 ms/scan on one CPU core.

2.0.0发布于 2026-10-23 14:00 UTC419star67fork同步于 2026-11-10 18:00 UTC

怎么上手

由 README 提炼,执行前请确认
git clone https://github.com/SS47816/lidar_obstacle_detector.git && cd .. && rosdep install --from-paths src --ignore-src -r -y && colcon build --cmake-args -DCMAKE_BUILD_TYPE=Release
硬件要求按 README 说明

CPU 模式无需 GPU,单核约 10 ms/帧;GPU 模式需 NVIDIA Ampere 或更新架构(含 Jetson Orin)、CUDA 11.4–13、TensorRT ≥ 10,README 未给出显存要求。

需要 CUDA
下载:源码 zip·GitHub Releases(安装包)本站不镜像安装包

项目说明

由 README 自动翻译提炼

ROS 1/2 实时 3D 激光雷达感知节点,单核 CPU 就能检测、跟踪并预测障碍物

面向 ROS 1/2 的实时 3D 激光雷达障碍物检测工具,集地面分割、聚类、跟踪与轨迹预测于一体,单核 CPU 约 10ms 处理一帧,可选 TensorRT 加速的 CenterPoint。

核心能力

  • 用 Patchwork++ 加高程图做地面分割
  • 用 Kalman 滤波加 GIoU 关联跟踪目标并输出速度
  • 未识别物体转成 2.5D 柱体,跨帧融合抑制闪烁
  • 可选 TensorRT CenterPoint 融合出类别与精确框
  • 输出 vision_msgs、Autoware、nav2 占据栅格等话题

容易踩的坑

GPU 模式需加 -DLOD_WITH_TENSORRT=ON 重新编译,否则 learning/fused 会被拒绝;首次运行要花约一分钟构建 TensorRT 引擎并缓存到 ~/.cache;用 GPU 模式时须把 sensor_height 设成实际雷达离地高度以匹配 nuScenes 安装高度;Autoware 话题只在编译时找到 autoware_perception_msgs 才发布。

内容由模型根据 README 生成,可能不完整或不准确,以官方文档为准。看原文 README

最近发版

1 个版本2.0.0
  1. 2.0.02.0.0: detect, track and predict every obstacle最新正式版2026-10-23 · 2026-10-23 14:00 UTC

    lidar_obstacle_detector 2.0.0 is a ground-up rewrite: real-time 3D lidar perception for ROS 1 and ROS 2 that detects, tracks and predicts every obstacle, model-free on a CPU or fused with a GPU detector.

    demo

    Highlights

    • Three detector modes:
      • clustering: CPU, about 10 ms per 95k-point scan on one core.
      • learning: NVIDIA CUDA-CenterPoint via TensorRT, with multi-sweep input.
      • fused: recognised objects become tracked boxes, and everything else becomes 2.5D pillars, so nothing is dropped.
    • Tracking and prediction: Kalman filter with GIoU Hungarian association, heading from motion, 3 s constant-turn-rate paths, and Autoware PredictedObjects.
    • Occupancy: 2.5D pillars fused over time (flicker 37% → 13%), a nav2-ready occupancy grid with ray-cast free space, and 3D voxels.
    • Ground: Patchwork++ with elevation-map refinement. Only 5% of object points are lost on hilly roads, down from 26%.
    • Accuracy on Argoverse 2:
      • recall@1m 0.66 (CPU) / 0.91 (GPU)
      • coverage 99%
      • IDF1* 0.73 / 0.86
    • Accuracy on nuScenes val: recall@1m 0.98 with the GPU detector.
    • Integrations: ROS 1 Noetic and ROS 2 Humble / Jazzy, vision_msgs, Autoware, jsk, RViz class models, and a Foxglove layout.
    • Reproducible: public benchmark tooling, unit tests, CI, and pixi environments that need no system ROS.

    Assets

    • lidar_obstacle_detector_demo.mp4: the full-resolution demo video.
    • lidar_obstacle_detector_demo.mcap + foxglove_layout.json: open them in app.foxglove.dev. The recording is the ROS 2 node in clustering mode on an Argoverse 2 drive.

    See the README, benchmarks and CHANGELOG. The previous ROS 1-only release stays available at the v1-ros1-legacy tag.

    Demo data: Argoverse 2 (CC BY-NC-SA 4.0).

用户点评

登录用户的真实使用记录,可按版本和硬件筛选
共 0 条

    还没有人点评。第一个说出真实体验的人最有价值。

    README 原文

    未翻译

    Why lidar_obstacle_detector?

    • Fast. 10.4 ms per 95k-point scan on one CPU core (Argoverse 2), 3.4 ms on nuScenes. That includes ground segmentation, clustering, tracking and occupancy.
    • Nothing is dropped. Recognised objects become tracked boxes. Everything else (walls, poles, debris, an overturned bin) becomes 2.5D pillars: on Argoverse 2, 99% of labelled objects are covered by a box or by pillars.
    • Stable. Pillars are fused over time, which cuts their scan-to-scan flicker from 37% to 13%. Boxes keep their shape and heading along a track.
    • Tracks with velocity and a future. A Kalman filter with GIoU association tracks every object. Moving objects take their heading from their motion and get a 3 s predicted path (constant turn rate and velocity).
    • Optional GPU detector. NVIDIA CUDA-CenterPoint (TensorRT) with multi-sweep input adds class labels and precise boxes:
      • recall@1m 0.91 on Argoverse 2 and 0.98 on nuScenes val
      • IDF1* 0.86 / 0.88
      • 25.5 ms per scan in fused mode on an RTX 3090 Ti
    • Robust ground segmentation. Patchwork++ plus an elevation-map refinement. Only 5% of object points are lost to the ground on hilly Pittsburgh streets.
    • Drop-in for your stack. ROS 1 and ROS 2 nodes, live-tunable parameters, and outputs for vision_msgs, Autoware (DetectedObjects, PredictedObjects), jsk, nav2 occupancy grids, RViz and Foxglove.
    • Reproducible. A public benchmark on Argoverse 2 and nuScenes, unit tests, CI on Noetic, Humble and Jazzy, and a one-command pixi setup with no system ROS needed.

    Quick start

    # ROS 2 (Humble / Jazzy), in your workspace's src/
    git clone https://github.com/SS47816/lidar_obstacle_detector.git && cd ..
    rosdep install --from-paths src --ignore-src -r -y && colcon build --cmake-args -DCMAKE_BUILD_TYPE=Release
    source install/setup.bash
    ros2 launch lidar_obstacle_detector obstacle_detector.launch.py points:=/your/points tracking_frame:=odom rviz:=true
    

    No ROS installed? pixi run -e jazzy build builds everything, ROS 2 Jazzy included, inside the repository folder (see Installation).

    Detector modes

    Two detectors, three ways to combine them (detector_method):

    ModeObjects (tracked boxes)Everything elseNeeds
    clustering (default)every obstacle, class unknownalso reported as 2.5D pillarsCPU
    learning10 nuScenes classes: car, truck, bus, trailer, construction vehicle, pedestrian, bicycle, motorcycle, barrier, traffic conenot reportedNVIDIA GPU
    fusedthe 10 classes, each absorbing the clusters that belong to it2.5D pillars, untrackedNVIDIA GPU

    [!WARNING] learning only reports what the network was trained on. A fallen tree, a wheelchair or a shopping trolley is invisible to it. Use fused on a robot that has to stop for them.

    fused follows the output model used by production AV stacks: what the network recognises is tracked and predicted as an object, and what it doesn't is still there as occupied space.

    Argoverse 2, 15 val logsRecall@1mCoverageIDF1*ID switchesMoving heading err.Runtime
    clustering (fast, CPU)0.6699.5%0.731,72514°10.4 ms
    learning (CenterPoint, 10 sweeps)0.9194.7%0.861,0242.4°23.7 ms
    fused0.9199.0%0.861,0342.4°25.5 ms

    Coverage is the share of labelled objects that are reported, either as a box or by pillars in their footprint. Recall@1m counts boxes only.

    Outputs

    ROS 2 topicTypeContent
    ~/detectionsvision_msgs/Detection3DArrayboxes, class, score; id is the track id
    ~/objectsautoware_perception_msgs/DetectedObjectsboxes with velocity and heading availability
    ~/predicted_objectsautoware_perception_msgs/PredictedObjectstracked objects with their 3 s predicted path
    ~/pillarssensor_msgs/PointCloud22.5D pillars: x, y, z (top), z_min (ground), observed
    ~/occupancynav_msgs/OccupancyGridfree / occupied / unknown (ray-cast), for nav2 or costmaps
    ~/occupancy_voxelssensor_msgs/PointCloud2occupied 3D voxels
    ~/markersvisualization_msgs/MarkerArrayclass models, boxes, ids, velocities, predicted paths, pillars
    ~/cloud_ground, ~/cloud_obstaclessensor_msgs/PointCloud2segmented input

    Autoware topics are published when autoware_perception_msgs is found at build time. Clouds, pillars and occupancy are only converted into messages when something subscribes. On ROS 1 the node publishes the same content as jsk boxes, autoware_msgs/DetectedObjectArray, markers, pillars and occupancy (see ROS 1).

    Try it in Foxglove

    config/foxglove_layout.json is a ready-made Foxglove layout: 3D view with models, pillars and paths, the camera, and the detections. Download the demo recording lidar_obstacle_detector_demo.mcap from the latest release (the ROS 2 node in clustering mode on an Argoverse 2 drive), open it in app.foxglove.dev (no install needed) and import the layout. To record your own, run the node with mesh_uri:=https://raw.githubusercontent.com/SS47816/lidar_obstacle_detector/main/meshes/ so the models load in the browser.

    Pipeline

    flowchart LR
      A[PointCloud2] --> B["Preprocess<br/>ROI · ego removal · voxel grid"]
      B --> C["Ground<br/>Patchwork++ + elevation-map refinement"]
      C --> D["Clustering<br/>height-aware BEV grid | adaptive Euclidean"]
      A --> N["CenterPoint (GPU, optional)<br/>10 ego-compensated sweeps"]
      D --> M{"detector_method"}
      N --> M
      M --> E["Objects<br/>L-shape boxes | learned boxes"]
      M --> P["2.5D pillars<br/>fused over time"]
      E --> F["Tracking + prediction<br/>Kalman · Hungarian (GIoU) · CTRV paths"]
      F --> G["vision_msgs · Autoware · jsk · markers"]
      P --> O["pillars · occupancy grid · voxels"]
    
    PresetGroundClusteringBoxesUse it for
    fast (default)Patchwork++BEV gridL-shapemost robots and vehicles
    accuratePatchwork++adaptive EuclideanL-shapehighest clustering recall, 2–3× the compute
    legacyRANSACEuclideanaxis-alignedthe classic pipeline; no pillars or occupancy

    Benchmark

    Class-agnostic results on 15 Argoverse 2 validation logs (2 × 32-beam lidar, 10 Hz, 2,350 scans) and the 10 nuScenes-mini scenes (32-beam, 20 Hz). The ROI is ±40 m. Objects are vehicles, pedestrians and cyclists with at least 5 lidar points. CPU timings are on one core of an i9-12900K; GPU rows add an RTX 3090 Ti. "*" metrics ignore predictions far from any labelled object, because walls, poles and vegetation are correctly reported but not labelled.

    DatasetModeRecall@1m[email protected]CoverageUnder-segIDF1*ID switchesObj. pts lost to groundRuntime [ms]
    Argoverse 2legacy (classic)0.530.4272.7%28%0.514,65326%30.5
    Argoverse 2fast0.660.6299.5%10%0.731,7255%10.4
    Argoverse 2accurate0.700.6399.5%9%0.711,7495%32.2
    Argoverse 2learning (GPU)0.910.9194.7%2%0.861,0245%23.7
    Argoverse 2fused (GPU)0.910.9199.0%2%0.861,0345%25.5
    nuScenes minilegacy (classic)0.380.3158.1%9%0.574255%6.7
    nuScenes minifast0.420.3698.3%11%0.583636%3.4
    nuScenes miniaccurate0.410.3498.3%8%0.573906%6.8
    nuScenes valfast0.380.3299.1%17%0.551355%3.5
    nuScenes vallearning (GPU)0.980.9699.0%1%0.88775%14.9
    nuScenes valfused (GPU)0.980.9699.8%1%0.88825%16.0

    CenterPoint was trained on nuScenes, so on nuScenes it is scored on the two mini val scenes only. On Argoverse 2, a lidar setup and city it has never seen, it is still far ahead of clustering. Multi-sweep input and every other component are ablated in docs/benchmarks.md, which also explains each metric.

    Installation

    ROS 2 (Humble, Jazzy)

    cd ~/ros2_ws/src
    git clone https://github.com/SS47816/lidar_obstacle_detector.git
    cd ..
    rosdep install --from-paths src --ignore-src -r -y
    colcon build --packages-select lidar_obstacle_detector --cmake-args -DCMAKE_BUILD_TYPE=Release
    source install/setup.bash
    

    ROS 1 (Noetic)

    cd ~/catkin_ws/src
    git clone https://github.com/SS47816/lidar_obstacle_detector.git
    cd ..
    rosdep install --from-paths src --ignore-src -r -y
    catkin_make -DCMAKE_BUILD_TYPE=Release   # or: catkin build
    source devel/setup.bash
    

    Without a system ROS install (pixi)

    pixi installs ROS from RoboStack into the repository folder. It needs no root access and works on any Linux distribution:

    pixi run -e jazzy build      # ROS 2 Jazzy (colcon), then: pixi shell -e jazzy
    pixi run -e noetic build     # ROS 1 Noetic (catkin build)
    pixi run -e core test        # the ROS-agnostic library + unit tests
    pixi run -e gpu gpu-test     # with CUDA-CenterPoint (NVIDIA driver >= 570)
    

    GPU detector (optional)

    You need an NVIDIA GPU (Ampere or newer, or Jetson Orin), CUDA 11.4–13, TensorRT ≥ 10 and protobuf. Then:

    colcon build --packages-select lidar_obstacle_detector --cmake-args -DLOD_WITH_TENSORRT=ON
    

    CMake downloads NVIDIA's prebuilt sparse-convolution library and the ONNX models, and checks their SHA-256. The first run builds a TensorRT engine for your GPU (about a minute) and caches it in ~/.cache/lidar_obstacle_detector. Set detector_method: fused, and set sensor_height to your lidar's height above the ground: the network expects nuScenes' mounting height, and the input is shifted to match. Multi-sweep input needs tracking_frame (e.g. odom). Without a TensorRT build, the GPU modes are rejected with an error and the node keeps running.

    Usage

    ROS 2

    ros2 launch lidar_obstacle_detector obstacle_detector.launch.py points:=/velodyne_points
    # options: preset:=fast|accurate|legacy  tracking_frame:=odom  target_frame:=base_link  rviz:=true
    

    Every parameter can be changed while the node runs, with rqt_reconfigure or ros2 param set /obstacle_detector cluster_threshold 0.5. The defaults are in config/obstacle_detector.yaml.

    ROS 1

    roslaunch lidar_obstacle_detector mai_city.launch
    

    Topics are set with the parameters lidar_points_topic, cloud_ground_topic, cloud_clusters_topic, jsk_bboxes_topic, autoware_objects_topic, markers_topic, occupancy_topic, occupancy_voxels_topic and pillars_topic. Boxes are published in bbox_target_frame. Every algorithm parameter is exposed through dynamic_reconfigure.

    Demo with the MAI City dataset

    1. Download the bags from the MAI City dataset.
    2. Play them:
      • ROS 1: roslaunch lidar_obstacle_detector mai_city.launch, then rosbag play 00.bag.
      • ROS 2: convert the bag first with pip install rosbags && rosbags-convert --src 00.bag --dst 00, then run ros2 launch lidar_obstacle_detector mai_city.launch.py and ros2 bag play 00 --clock.

    You can also replay Argoverse 2 or nuScenes sequences into ROS 2 with tools/python/lod_bench/replay_ros2.py (see Reproducing the benchmark).

    C++ library (no ROS)

    #include <lidar_obstacle_detector/obstacle_detector.hpp>
    using namespace lidar_obstacle_detector;
    
    PipelineConfig cfg = PipelineConfig::preset("fast");
    setParameter(&cfg, "detector_method", "fused");  // needs a TensorRT build
    ObstacleDetector<pcl::PointXYZI> detector(cfg);
    
    auto result = detector.process(cloud, stamp_seconds, odom_T_lidar);
    for (const Box &b : result.boxes) {
      // b.id, b.label, b.score, b.center, b.size, b.yaw, b.velocity, b.predicted_path
    }
    // result.pillars (2.5D), result.occupancy (2D grid), result.occupied_voxels
    

    ObstacleDetector::setLearnedDetector() plugs in your own network (any LearnedDetector that returns labelled boxes). Fusion, tracking, prediction and the ROS outputs then work unchanged.

    Parameters

    Every parameter has the same name in ROS 1, ROS 2 and the benchmark CLI. The full list, with ranges, is in core/src/config.cpp. The ones you are most likely to change:

    ParameterDefaultMeaning
    detector_methodclusteringclustering, learning or fused (see Detector modes)
    tracking_frame""fixed frame (e.g. odom). Velocities are then absolute, and multi-sweep input and pillar fusion turn on
    sensor_height1.73lidar height above the ground [m]
    roi_{min,max}_{x,y,z}-30/70, ±30, -2.5/1region of interest in the lidar frame (x forward, z up)
    ego_{min,max}_{x,y,z}box around your vehicle; its points are removed
    cluster_threshold0.6max gap between points of one object [m]
    cluster_min_size10minimum points per obstacle
    pillar_memory2.0how long pillars are remembered when occluded [s] (0 = this scan only)
    prediction_horizon3.0length of predicted paths [s] (0 = off)
    occupancy_min_height, occupancy_max_height0.2, 2.5height band above the local ground that counts as occupied [m]

    Tuning for your lidar. With sparse sensors (32 beams or fewer, e.g. nuScenes), use cluster_min_size: 5 and cluster_range_gain: 0.04 to keep small and distant objects. On nuScenes this raises recall@1m from 0.42 to 0.55 (fast) and from 0.41 to 0.57 (accurate). With dense 64- or 128-beam sensors, keep the defaults. For many long trucks in clustering mode, try cluster_track_guided: true: it cuts split trucks by a quarter, at a small cost in recall (see docs/benchmarks.md).

    Reproducing the benchmark

    pixi run -e core build
    # Argoverse 2 (no account needed) and nuScenes (free account) -> common format
    pixi run -e core python -I tools/python/lod_bench/prepare_av2.py --root ~/datasets/av2/sensor/val --out ~/datasets/lod_bench/av2
    pixi run -e core python -I tools/python/lod_bench/prepare_nuscenes.py --root ~/datasets/nuscenes --out ~/datasets/lod_bench/nuscenes
    # run + evaluate a preset (--set key=value to change parameters)
    pixi run -e core python -I tools/python/lod_bench/run.py --data ~/datasets/lod_bench/av2 --runs ~/datasets/lod_bench/runs --name fast --preset fast
    

    The demo videos are rendered with tools/python/lod_bench/render_showcase.py (map, camera and models) and render_demo.py (chase camera, bird's-eye comparison).

    Roadmap

    • ROS 2 support, multi-object tracking with velocities, L-shape boxes, Patchwork++
    • Occupancy grid and 2.5D pillars fused over time
    • NVIDIA CUDA-CenterPoint with multi-sweep input, and fused mode
    • Trajectory prediction (CTRV) with Autoware PredictedObjects
    • Map-aware prediction (lane following)
    • NVIDIA CUDA-PointPillars as a second learned backend
    • Release on the ROS buildfarm (apt install ros-<distro>-lidar-obstacle-detector)
    • Python bindings
    • Motion undistortion of rotating lidar scans

    The previous ROS 1-only release is still available at the v1-ros1-legacy tag. See the changelog for everything in 2.0.

    Contributing

    Issues, discussions and pull requests are welcome; see CONTRIBUTING.md. If lidar_obstacle_detector is useful to you, a ⭐ helps others find it.

    Citation

    If you use this package, please cite it (see CITATION.cff). Please also cite Patchwork++ (Lee et al., IROS 2022), L-shape fitting (Zhang et al., IV 2017) and, for the GPU modes, CenterPoint (Yin et al., CVPR 2021).

    License

    MIT, see LICENSE. Vendored code: Patchwork++ (third_party/patchworkpp, BSD-2-Clause) and NVIDIA CUDA-CenterPoint (third_party/cuda_centerpoint, MIT).