THE canonical_scan_matcher PACKAGE IS DISCONTINUED

the package has been renamed to laser_scan_matcher and has been updated with additional features.

The information below be preserved for a while while people switch.

canonical_scan_matcher.png

Details

The canonical_scan_matcher package is a wrapper around Andrea Censi's Canonical Scan Matcher [1] implementation. The package allows to scan match between consecutive sensor_msgs/LaserScan messages, and publish the estimated position of the laser as a geometry_msgs/Pose2D or a tf transform.

The package is intended to be used without any odometry estimation provided by other sensors. Thus, it can serve as a stand-alone odometry estimator.

An estimation for theta can optionally be provided to improve accuracy, in the form of a sensor_msgs/Imu. This message would typically be published by an IMU or other angular rate sensor.

Alternatively, an estimation for x, y, and theta can optionally be provided to improve accuracy, in the form of a tf transform. This transform would typically be published by an odometry system. This has not yet been tested.

Example

You can run the canonical_scan_matcher on a pre-recorded bag file that comes with the package. First, make sure you have the scan_tools stack downloaded and installed by following the instructions here.

Next, make sure you have the necessary tools installed:

   1 rosmake rviz rosbag tf

Finally, run the demo:

   1 roslaunch canonical_scan_matcher demo.launch

You should see a result similar to the video below. The video shows CSM tracking the position of a Hokuyo laser as it is being carried freely around a room. The pose is determined entirely by the scan matcher - no additional odometry is provided.

Nodes

csm_node

The csm_node takes in sensor_msgs/LaserScan messages, performs scan registration, and outputs an estimate for the displacement of the robot.

Subscribed Topics

scan (sensor_msgs/LaserScan)
  • Scans from a laser range-finder
imu (sensor_msgs/Imu)
  • Imu messages, used for theta estimation. Only used if odometry_type is set to imu.

Published Topics

pose2D (geometry_msgs/Pose2D)
  • The pose of the base frame, in some fixed (world) frame.

Parameters

~world_frame (string, default: "world")
  • the fixed frame
~base_frame (string, default: "base_link")
  • the base frame of the robot
~publish_tf (bool, default: true)
  • whether to publish scan matcher's estimation for the position of the base frame in the world frame as a transform. Disable this if some other node is already publishing an odometric estimation.
~publish_pose (bool, default: true)
  • whether to publish scan matcher's estimation for the position of the base frame in the world frame as a geometry_msgs/Pose2D
~odometry_type (string, default: "none")
  • If "none", the scan matcher will not use any estimate for the displacement between scans. If "imu", the matcher will use as an estimate the yaw value of sensor_msgs/Imu messages published on a topic called "imu". If "tf", the matcher will use as an estimate the x, y, and yaw value of a tf transform between the world and base frames.
~max_angular_correction_deg (double, default: 45.0)
  • Maximum angular displacement between scans, in degrees
~max_linear_correction (double, default: 0.50)
  • Maximum translation between scans (m)
~max_iterations (int, default: 10)
  • Maximum ICP cycle iterations
~epsilon_xy (double, default: 0.001)
  • A threshold for stopping (m)
~epsilon_theta (double, default: 0.00872)
  • A threshold for stopping (rad)
~max_correspondence_dist (double, default: 0.5)
  • Maximum distance for a correspondence to be valid
~sigma (double, default: 0.010)
  • Noise in the scan (m) (Not sure if changing this has any effect in the current implementation)
~use_corr_tricks (int, default: 1)
  • If 1, use smart tricks for finding correspondences (see paper).
~restart (int, default: 0)
  • Restart: If 1, restart if error is over threshold
~restart_threshold_mean_error (double, default: 0.01)
  • Restart: Threshold for restarting
~restart_dt (double, default: 1.0)
  • Restart: displacement for restarting. (m)
~restart_dtheta (double, default: 0.1)
  • Restart: displacement for restarting. (rad)
~clustering_threshold (double, default: 0.25)
  • Max distance for staying in the same clustering
~orientation_neighbourhood (int, default: 10)
  • Number of neighbour rays used to estimate the orientation
~use_point_to_line_distance (int, default: 1)
  • If 0, it's vanilla ICP
~do_alpha_test (int, default: 0)
  • If 1, discard correspondences based on the angles
~do_alpha_test_thresholdDeg (double, default: 20.0)
  • Discard correspondences based on the angles - threshold angle, in degrees
~outliers_maxPerc (double, default: 0.90)
  • Percentage of correspondences to consider: if 0.90, always discard the top 10% of correspondences with more error
~outliers_adaptive_order (double) (, default: 0.7)
  • Parameters describing a simple adaptive algorithm for discarding. 1) Order the errors. 2) Choose the percentile according to outliers_adaptive_order (if it is 0.7, get the 70% percentile). 3) Define an adaptive threshold multiplying outliers_adaptive_mult with the value of the error at the chosen percentile. 4) Discard correspondences over the threshold. This is useful to be conservative; yet remove the biggest errors.
~outliers_adaptive_mul (double, default: 2.0)
  • Parameters describing a simple adaptive algorithm for discarding. 1) Order the errors. 2) Choose the percentile according to outliers_adaptive_order (if it is 0.7, get the 70% percentile). 3) Define an adaptive threshold multiplying outliers_adaptive_mult with the value of the error at the chosen percentile. 4) Discard correspondences over the threshold. This is useful to be conservative; yet remove the biggest errors.
~do_visibility_test (int, default: 0)
  • If you already have a guess of the solution, you can compute the polar angle of the points of one scan in the new position. If the polar angle is not a monotone function of the readings index, it means that the surface is not visible in the next position. If it is not visible, then we don't use it for matching.
~outliers_remove_doubles (int, default: 1)
  • If 1, no two points in laser_sens can have the same correspondence
~do_compute_covariance (int, default: 0) ~debug_verify_trick (int, default: 0)
  • If 1, checks that find_correspondences_tricks gives the right answer
~use_ml_weights (int, default: 0)
  • If 1, the field 'true_alpha' (or 'alpha') in the first scan is used to compute the incidence beta, and the factor (1/cos^2(beta)) used to weight the correspondence. (Changing this has no effect in the current implementation)
~use_sigma_weights (int, default: 0)
  • If 1, the field 'readings_sigma' in the second scan is used to weight the correspondence by 1/sigma^2 (Not sure if changing this has any effect in the current implementation)

Required tf Transforms

base_linklaser
  • the pose of the laser in the base frame. Only needed when use_odometry is enabled.

Provided tf Transforms

worldbase_link
  • the pose of the robot base in the world frame. Only provided when publish_tf is enabled.

References

[1] A. Censi, "An ICP variant using a point-to-line metric" Proceedings of the IEEE International Conference on Robotics and Automation (ICRA), 2008

Bug Reports & Feature Requests

We appreciate the time and effort spent submitting bug reports.

Please use our Trac to report bugs or request features.

Wiki: canonical_scan_matcher (last edited 2011-06-18 21:33:28 by IvanDryanovski)