- clone leg_tracker repo into your indigo catkin source directory
- install SciPy:
- $ sudo apt-get install python-scipy
- install pykalman (http://pykalman.github.io/#installation or https://pypi.python.org/pypi/pykalman):
- $ sudo pip install pykalman
- install munkres for Python:
- $ sudo pip install munkres
- $ cd [your catkin_workspace]
- $ catkin_make
- $ roslaunch leg_tracker joint_leg_tracker.launch
- try $ roslaunch leg_tracker demo_stationary_simple_environment.launch to see a demo of it working on a stationary robot.
- there are a bunch more demo launch files in the /launch directory.
- video: youtu.be/F2Qx3O5AyBs, which also includes a brief explaination of the method.
- you can change the subscribed scan topic by changing the parameter "scan_topic" in the launch file.
- to get the transforms. You should specify the fixed frame by the parameter "fixed_frame" in the launch file.
- the positions and velocities of the tracked people as a PersonArray message (see: leg_tracker/msg/PersonArray.msg for the message specification).
- markers for the tracked people, other tracked objects and the centroids of the detected clusters.
- right now, it's only been tuned for 7.5, 10 or 15Hz laser scanners. If you're using something faster than this, I would recommend downsampling to one of these frequencies.
- frame_id for /people_tracked messages. Default: fixed_frame.
- If the program is running slow because there are a lot of objects to be tracked, you can set this so it only tracks the "max_detected_clusters" closest objects. Default: -1 (i.e., unlimited).
- where to find the configuration file for the OpenCV random forest which has been trained to determine the probability of a scan cluster being a human leg based on its shape.
- Confidence threshold in leg shape to publish detect clusters. We found be results publishing and tracking all clusters, regardless of confidence in leg shape. Default: -1 (i.e., no threshold).
- Euclidian distance for clustering of laser scan points. Any two laser scan points which are closer than this distance will be clustered together. If you change this, you might want to re-train the leg detector. Default: 0.13 (m).
- Minimum scan points for a cluster to be valid. If a cluster has less than this, then we assume it's noise and delete it. Default: 3.
- Maximum distance from laser scanner to consider detected clusters. Farther is better but decreases run speed. Default: 10.0 (m).
- Maximum separation of legs. Legs further apart than this distance will not be matched. Default: 0.8 (m).
- How high the confidence needs to be of the current track's leg shape to initiate and maintain a person track. Higher values will yield lower false positive people tracks and lower values higher false negatives. Will likely need re-tuning if you retrain the leg detector. Default: 0.1.
- If people who weren't seen in the previous scan should be published to the /people_tracked topic. Default: True.
- If you should use the scan headers to do tfs or just use the latest transform available. If you're trying to do repeatable tests on recorded bags than it might be useful to use the scan headers. Default: False (i.e., use latest tf available).
- Previously used only for debugging. Default: False.
- How far a candidate leg pair must travel to initiate a person track. Default: 0.5 (m).
- A threshold to determine whether a track should be considered in free space or occupied space. Default: 0.06.
- Confidence percentile for matching of clusters to tracks. Larger confidence percentile generates larger gates for the tracks to match to new clusters. You should be able to view the size of the gates in Rviz as circular visualization markers. Default: 0.9.
- Maximum standard deviation of covariance of a track before it is deleted: Default: 0.9.
Compatible laser scanners
- right now it's trained for laser scanners of 0.33 degree resolution. Different resolutions should still be runnable but would probably require retraining (see below) to get optimal performance.
Retraining the leg detector
- gather positive examples by setting the scanner up in a populated area where you specify a bounding box (or alternatively, an arc), within which only peoples' legs will appear.
- record scan data in a rosbag.
- run extract_positive_training_clusters.launch on the recorded data to have it automatically annotate where the legs are in the scans. It will put a marker on any clusters that fall within the specified bounding box. You can check if the right clusters have been annotated by playing back the generated rosbag with the "--pause" option and stepping through it and visually checking in Rviz where the markers lie in the scan.
- gather negative examples by moving the scanner on a moble platform around empty rooms.
- run train_leg_detector and include the positive and negative examples as command line arguments (see the train_leg_detector.launch for an example).
- a .yaml file will be output with the name of the "save_file" parameter in the train_leg_detector launch file.
- set the launch file for the joint_leg_tracker to load the .yaml file you produced.
- when running the joint_leg_tracker with your new detector, you will likely need to retune the "confidence_threshold_to_maintain_track" parameter so you get the desired tradeoff between false positive/false negative person tracks.
Under the hood
Files for running
- src/laser_processor.cpp - scan processing stuff. E.g., splitting scan into clusters based on euclidian distance.
- src/cluster_features.cpp - calculates geometric features of scan clusters. Used by detect_leg_clusters.
- src/detect_leg_clusters.cpp - detects leg clusters in the scan and publishes them to /detected_leg_clusters.
- scripts/joint_leg_tracker.py - uses detect_leg_clusters and a global nearest neighbour tracking method to track people. They're published as markers to rviz and to a people_tracked topic.
- scripts/individual_leg_tracker.py - alternative to joint_leg_tracker. I found better performance with the joint_leg_tracker.
** Files for retraining the detector **
- src/extract_positive_training_clusters.cpp - extracts positive example clusters from scans in a rosbag. They're saved to another rosbag to be used for training.
- src/train_leg_detector.cpp - train the random forest classifier using the positive example clusters and negative scans examples.
- I found using this version of munkres, which is based on numpy, sped up the data association matching a little bit: https://github.com/ben-eysenbach/munkres
We used some code from the leg_detector package: http://wiki.ros.org/leg_detector. It does fundamentally the same task, but we found this version was more capable of tracking people longer, not mismatching people and producing less false positives in cases where a grid occupancy map is not provided a priori. See the reference paper and the leg_tracker_benchmarks repo for more details.
- port tracker to C++ to improve speed
- use BFL's kalman filter in place of pykalman so users aren't required to install the external dependancy
- use a C++ version of munkres in place of python's munkres so users aren't required to install the external dependancy
- integrate a priori occupancy grid maps or SLAM gmapping maps to speed up detection and reduce false positives
A. Leigh, J. Pineau, N. Olmedo and H. Zhang, Person Tracking and Following with 2D Laser Scanners, International Conference on Robotics and Automation (ICRA), Seattle, Washington, USA, 2015.