ERASOR: cleaning dynamic objects out of accumulated LiDAR maps
Official page of ERASOR (Egocentric Ratio of pSeudo Occupancy-based Dynamic Object Removal), which is accepted @ RA-L'21 with ICRA'21
At a glance
- What is it?
- ERASOR is the research implementation of a RA-L paper with an ICRA option that removes moving objects from a LiDAR map built by naive accumulation, using an egocentric pseudo-occupancy ratio rather than a learned classifier. It suits a robotics researcher reproducing that method on SemanticKITTI, and the project itself points new work at its ROS-free successor.
- Who is it for?
- Adopt ERASOR when you are reproducing the RA-L 2021 result on SemanticKITTI or need a ROS Melodic era pipeline for removing moving objects from naively accumulated LiDAR maps, because the shipped rosbags, ground truth point clouds and baseline outputs let you check the method against the published numbers.
- Can I use it commercially?
- Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
- Is it still maintained?
- Yes. The repository last received commits 154 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 20, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What the method is actually solving
ERASOR stands for Egocentric Ratio of Pseudo Occupancy-based Dynamic Object Removal, and the official page describes it as the paper of that full name, accepted by RA-L with an ICRA'21 option. A video and a preprint on arXiv are linked from the README.
The problem is a specific one in LiDAR mapping. When a robot drives around accumulating scans into a map, everything it passes gets baked in: parked cars that drove away, pedestrians, cyclists, other vehicles. The result is a static map contaminated with ghosts of moving objects, which breaks any downstream use that assumes the map is a picture of the environment.
The approach is not a learned detector. The name gives the mechanism away, an egocentric ratio of pseudo occupancy, and the paper's own framing is that it uses these occupancy cues rather than a trained classifier. That matters for adoption: the method has no model to train and no dataset beyond the one you are mapping, which is very different from a deep learning detector that needs labelled data and a GPU at inference time.
The repository is a research artefact rather than a product. The primary language is recorded as Python, which refers to the metric calculation scripts, and the core is a C++ ROS package, since the top level contains `CMakeLists.txt`, `package.xml`, `launch/`, `src/`, `include/`, `msg/` and `rviz/` directories. The licence is GPL-3.0 with a `Licence` file, the last push was on 2026-05-22, and the repository is not archived.
The repository ships the baselines and the evaluation code too
The README lists what is provided, and the list is broader than the method itself. It provides the source code of ERASOR, all outputs of the state of the arts, the visualization, and the calculation code of the Preservation Rate and Rejection Rate metrics.
That last item is what makes the repository useful for comparison rather than only for demonstration. The Preservation Rate and Rejection Rate are the two numbers the paper reports, and having the calculation code and the baseline outputs in the same tree means you can recompute the published table rather than trust a number in a PDF. The Visualization of All the State-of-the-arts section goes further, offering the outputs of competing methods so a qualitative comparison does not require re-running anyone else's code.
The contributors are named in the README, with a contact address for Hyungtae Lim at KAIST and the advisor Hyun Myung, and the top level also contains a `scripts/` directory whose `semantickitti2bag/` subdirectory is where the raw SemanticKITTI data is converted into the rosbag form the code consumes.
That conversion script is a substantial part of the practical work. The May 2026 news entry records that the per-sequence KITTI configs were re-tuned against Table II of the paper, that the main README and the `scripts/semantickitti2bag/README.md` were rewritten, and that an ERASOR in the Wild section was expanded with coordinate-frame cautions and a non-KITTI pitfall checklist. A reader planning to apply this to their own robot is pointed at that section and at `src/offline_map_updater/main_in_your_env.cpp` with the `launch/run_erasor_in_your_env_vel16.launch` file, added in October 2021 as an example of running the method in an environment that is not the test setup.
Building it: catkin, ROS Melodic and a Python 2.7 metric script
The test environment is stated plainly: the code is tested successfully at Linux 18.04 LTS and ROS Melodic. That is a decade-old combination, and it is the single biggest practical constraint on adopting this repository as it stands.
The build is a standard catkin workspace. The README asks you to install ROS, and also jsk-visualization, which is required to visualize the Scan Ratio Test status. The jsk packages come from apt:
sudo apt-get install ros-melodic-jsk-recognition
sudo apt-get install ros-melodic-jsk-common-msgs
sudo apt-get install ros-melodic-jsk-rviz-pluginsThen the package itself is cloned and built with catkin tools:
mkdir -p ~/catkin_ws/src
cd ~/catkin_ws/src
git clone https://github.com/LimHyungTae/ERASOR.git
cd .. && catkin build erasorThe Python side is separate and older. The metric calculation for the Preservation Rate and Rejection Rate is implemented by python2.7, and it needs pypcd, tqdm, scikit-learn and tabulate:
pip install pypcd
pip install tqdm
pip install scikit-learn
pip install tabulateSo the repository has two toolchains in it, a ROS Melodic catkin package for the method and a Python 2.7 script for the evaluation. On a modern distribution neither installs without work, which is the practical reason the project points at its successor.
The prepared rosbags assume SuMa poses, and that detail matters
Before you can run anything you need data, and the README gives you preprocessed KITTI data encoded into rosbag, with the note that the downloading process might take five minutes or so and that all the rosbags require total 2.3G of storage space. Five files are listed for the download, covering sequences 00, 01, 02, 05 and 07.
The format details are specific enough to be useful. The rosbag consists of `node`, referring to `msg/node.msg`, and each label of the point is assigned in `intensity` for the sake of convenience. The dynamic classes are listed with their label codes, from 252 for moving-car through 259 for moving-other-vehicle, and the README points at `std::vector<int> DYNAMIC_CLASSES` in the code.
The trap is the pose assumption, and the README flags it in bold. The rosbags assume that the per-frame poses are estimated by SuMa, and it cites the paper's own section III.A, which states that maps are constructed at the regular intervals with the poses provided by SuMa, which contains inherent uncertainty. If you regenerate any bag from raw SemanticKITTI data via `scripts/semantickitti2bag/`, you must copy `sequences/<seq>/poses_suma_optim.txt` to `sequences/<seq>/poses.txt` first so that `pykitti.odometry.load_poses()` picks up the SuMa poses. Otherwise the resulting map will not align with the shipped ground-truth PCDs.
That is a good example of the kind of detail that is invisible in a paper and decisive in practice. If you skip it, the map still builds, the outputs still appear, and the numbers are simply wrong.
Running the two steps: naive map, then removal
The walkthrough uses sequence 05 of the KITTI dataset as the example, and it is a two step process with a distinct role for each step.
Step one builds the naive map. You set `target_rosbag` in `launch/mapgen.launch` to the name of the target rosbag and `save_path` to where the naively accumulated map is saved, then launch and play the bag:
roscore # (Optional)
roslaunch erasor mapgen.launch
rosbag play 05_2350_to_2670_w_interval_2_node.bagTwo maps are auto-saved at the save path. The dense map is used for evaluation to fill in the corresponding labels, and the voxelized map is the input of step two as the naively accumulated map.
Step two runs ERASOR itself. You set `initial_map_path` in `config/seq_05.yaml` to the naively accumulated map and `save_path` to where the filtered static map goes, then run:
roscore # (Optional)
roslaunch erasor run_erasor.launch target_seq:="05"
rosbag play 05_2350_to_2670_w_interval_2_node.bagThere is also a performance note: as of 22.03.01 the submap module is employed to speed up when extracting the map VOI, controlled by rosparams in `run_erasor.launch` for `is_large_scale` and `submap_size`, with the guidance that the appropriate `submap_size` is greater than two times the maximum range.
Finally the static map is written out as a point cloud file, with 0.2 denoting the voxelization size:
rostopic pub /saveflag std_msgs/Float32 "data: 0.2"and the result lands under the save path as `05_result.pcd`.
Where ERASOR is the wrong choice, and the successor to use instead
The project answers the wrong-tool question itself, at the very top of its news section, and it is worth taking at face value. ERASOR2 is now available, at the `url-kaist/ERASOR2` repository, and it is described as a ROS-free, pure-CMake C++ rewrite with a Python evaluator and improved benchmarks. The README says that if you are starting a new project, it recommends ERASOR2.
That is an unusual and welcome admission, and it changes how you should read everything else in the repository. This is the reference implementation of a 2021 paper, kept for reproducibility, with a maintained successor doing the same job on modern toolchains.
The concrete limits of this repository follow from that. The build needs ROS Melodic on Linux 18.04, and ROS Melodic is long past its support window, so the environment has to be an archived one, a container built from an old base image, or a machine you have specifically provisioned. The metric code needs Python 2.7, which is not available in most current distributions. The prepared data assumes SuMa poses, which constrains what you can regenerate and compare. And the method is tied to a specific test environment, with the README's own list of coordinate-frame cautions for applying it elsewhere.
The alternative worth naming is ERASOR2, and the difference in approach is the removal of the ROS dependency and the move to pure CMake and a C++ rewrite with a Python evaluator. The method is the same family of idea, an egocentric pseudo-occupancy ratio for detecting what moved, but it is packaged so that it builds on a current system.
For a reader who simply wants the idea, the paper and the preprint are the artefacts to read, and the code here is the way to check the numbers. For a reader who wants to run it, ERASOR2 is the answer, and the time spent forcing ROS Melodic into existence buys nothing.
Maintenance state and the licence
The last push was on 2026-05-22, and the recent releases list is empty, with the README noting that the repository has no GitHub releases. There is no version tag to pin and no package to install, so the repository is used as a source tree and a data source rather than as a dependency.
The news entries show what maintenance means for this project. The May 2026 entry describes a substantive pass: per-sequence KITTI configs re-tuned against Table II of the paper, a rewritten main README, a rewritten `scripts/semantickitti2bag/README.md`, and an expanded section on running the method outside the test setup. The October 2021 entry added the example for running in your own environment.
So this is a repository that gets periodic correctness passes rather than frequent releases, which suits a paper artefact whose inputs are fixed datasets and whose outputs are fixed tables. It does mean there is no upstream changelog to read before upgrading, only the commit history and the news section.
The licence is GPL-3.0, with a `Licence` file at the top level of the tree. For a research implementation that people build on top of, GPL is the expected and useful choice, since derived work stays open. If you intend to fold the method into a closed commercial product, that is the point to read the terms carefully, and this is a description of the published licence rather than legal advice.
The repository also carries the usual research overhead: `config/` with the per-sequence YAML files, `launch/` with the launch files, `rviz/` for the visualisation setup, `img/` with the figures, and `msg/` with the message definition that the rosbag format depends on. There is no CI configuration visible at the top level and no packaging for pip or conda, which is consistent with a ROS package that is built with catkin and used in place.
Editorial conclusion
Adopt ERASOR when you are reproducing the RA-L 2021 result on SemanticKITTI or need a ROS Melodic era pipeline for removing moving objects from naively accumulated LiDAR maps, because the shipped rosbags, ground truth point clouds and baseline outputs let you check the method against the published numbers. Do not start a new project on it, because the README says the successor ERASOR2 is available, a ROS-free pure-CMake C++ rewrite with a Python evaluator, and recommends it for new work. Before you build, confirm you can run ROS Melodic on Linux 18.04 as the test environment, note that the metric code needs Python 2.7 with pypcd, tqdm, scikit-learn and tabulate, and follow the SuMa pose instruction, because the prepared rosbags assume SuMa poses and regenerating them without copying `poses_suma_optim.txt` to `poses.txt` will produce a map that does not align with the shipped ground truth.
Frequently asked questions
What is ERASOR and what problem does it solve?
ERASOR is the official implementation of a RA-L paper with an ICRA'21 option on Egocentric Ratio of Pseudo Occupancy-based Dynamic Object Removal for static 3D point cloud map building. It removes moving objects that get baked into a LiDAR map built by naive accumulation, using an egocentric pseudo-occupancy ratio rather than a learned classifier.
What environment does ERASOR need?
The code is tested successfully at Linux 18.04 LTS and ROS Melodic, built with catkin tools. The metric calculation for the Preservation Rate and Rejection Rate is implemented in Python 2.7 and needs pypcd, tqdm, scikit-learn and tabulate, and jsk-visualization is required to visualise the Scan Ratio Test status.
Do I need to download the KITTI rosbags to try ERASOR?
The prepared data is preprocessed KITTI encoded into rosbag, and the README says the download may take five minutes or so and that all the rosbags require total 2.3G of storage space. The rosbag consists of `node` as described in `msg/node.msg`, and each point label is assigned in `intensity`.
What should I use for a new ERASOR-style project?
The README itself points to the successor, ERASOR2 at the `url-kaist/ERASOR2` repository, described as a ROS-free, pure-CMake C++ rewrite with a Python evaluator and improved benchmarks, and it says that if you are starting a new project it recommends ERASOR2.
What is the SuMa pose issue when regenerating the ERASOR rosbags?
The shipped rosbags assume the per-frame poses are estimated by SuMa. If you regenerate a bag from raw SemanticKITTI data via `scripts/semantickitti2bag/`, you must copy `sequences/<seq>/poses_suma_optim.txt` to `sequences/<seq>/poses.txt` first so that `pykitti.odometry.load_poses()` picks up the SuMa poses, otherwise the resulting map will not align with the shipped ground-truth point clouds.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/limhyungtae-erasor)Was this useful?