{"id":13526190,"url":"https://github.com/mikeferguson/robot_calibration","last_synced_at":"2025-04-01T06:31:24.338Z","repository":{"id":23038730,"uuid":"26391646","full_name":"mikeferguson/robot_calibration","owner":"mikeferguson","description":"Generic calibration for robots","archived":false,"fork":false,"pushed_at":"2025-03-17T12:34:39.000Z","size":650,"stargazers_count":392,"open_issues_count":6,"forks_count":118,"subscribers_count":19,"default_branch":"ros2","last_synced_at":"2025-03-17T13:42:37.351Z","etag":null,"topics":["calibration","robot","ros","ros2"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mikeferguson.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2014-11-09T09:50:01.000Z","updated_at":"2025-03-17T12:34:43.000Z","dependencies_parsed_at":"2023-11-26T02:24:01.495Z","dependency_job_id":"94af2839-0cdf-4da0-9392-e630e8272655","html_url":"https://github.com/mikeferguson/robot_calibration","commit_stats":null,"previous_names":[],"tags_count":33,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mikeferguson%2Frobot_calibration","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mikeferguson%2Frobot_calibration/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mikeferguson%2Frobot_calibration/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mikeferguson%2Frobot_calibration/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mikeferguson","download_url":"https://codeload.github.com/mikeferguson/robot_calibration/tar.gz/refs/heads/ros2","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246596922,"owners_count":20802926,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["calibration","robot","ros","ros2"],"created_at":"2024-08-01T06:01:26.218Z","updated_at":"2025-04-01T06:31:24.332Z","avatar_url":"https://github.com/mikeferguson.png","language":"C++","funding_links":[],"categories":["Uncategorized","Camera-to-Robot Pose Estimation","6.Calibration"],"sub_categories":["Uncategorized"],"readme":"# Robot Calibration\n\nThis package offers several ROS2 nodes. The primary one is called _calibrate_,\nand can be used to calibrate a number of parameters of a robot, such as:\n\n * 3D Camera intrinsics and extrinsics\n * Joint angle offsets\n * Robot frame offsets\n\nThese parameters are then inserted into an updated URDF, or updated camera\nconfiguration YAML in the case of camera intrinsics.\n\nTwo additional ROS nodes are used for mobile-base related parameter tuning:\n\n * _base_calibration_node_ - can determine scaling factors for wheel diameter,\n   track width and gyro gain by moving and rotating the robot while tracking\n   the actual movement based on the laser scanner view of a wall.\n * _magnetometer_calibration_ - can be used to do hard iron calibration\n   of a magnetometer.\n\n## The _calibrate_ node\n\nCalibration works in two steps. The first step involves the capture of data\nsamples from the robot. Each \"sample\" comprises the measured joint positions\nof the robot and two or more \"observations\". An observation is a collection\nof points that have been detected by a \"sensor\". For instance, a robot could\nuse a camera and an arm to \"detect\" the pose of corners on a checkerboard.\nIn the case of the camera sensor, the collection of points is simply the\ndetected positions of each corner of the checkerboard, relative to the pose\nof the camera reference frame. For the arm, it is assumed that the checkerboard\nis fixed relative to a virtual ``checkerboard`` frame which is fixed relative\nto the end effector of the arm. Within the virtual frame, we know the ideal\nposition of each point of the checkerboard corners since the checkerboard\nis of known size.\n\nThe second step of calibration involves optimization of the robot parameters\nto minimize the errors. Errors are defined as the difference in the pose\nof the points based on reprojection throuhg each sensor. In the case of our\ncheckerboard above, the transform between the virtual frame and the end\neffector becomes additional free parameters. By estimating these parameters\nalongside the robot parameters, we can find a set of parameters such that\nthe reprojection of the checkerboard corners through the arm is as closely\naligned with the reprojection through the camera (and any associated\nkinematic chain, for instance, a pan/tilt head).\n\nConfiguration is typically handled through two sets of YAML files: usually\ncalled ``capture.yaml`` and ``calibrate.yaml``.\n\nIf you want to manually move the robot to poses and capture each time you\nhit ENTER on the keyboard, you can run robot calibration with:\n\n```\nros2 run robot_calibration calibrate --manual --ros-args --params-file path-to-capture.yaml --params-file path-to-calibrate.yaml\n```\n\nMore commonly, you will generate a third YAML file with the capture pose\nconfiguration (as documented below in the section \"Calibration Poses\"):\n\n```\nros2 run robot_calibration calibrate path-to-calibration-poses.yaml --ros-args --params-file path-to-capture.yaml --params-file path-to-calibrate.yaml\n```\n\nThis is often wrapped into a ROS 2 launch file, which often records\na bagfile of the observations allowing to re-run just the calibration part\ninstead of needing to run capture each time. For an example, see the\nUBR-1 example in the next section.\n\n### Example Configuration\n\nAll of the parameters that can be defined in the capture and calibrate steps\nare documented below, but sometimes it is just nice to have a full example.\nThe UBR-1 robot uses this package to calibrate in ROS2. Start with\nthe ``calibrate_launch.py`` in\n[ubr1_calibration](https://github.com/mikeferguson/ubr_reloaded/tree/ros2/ubr1_calibration).\n\n### Capture Configuration\n\nThe ``capture.yaml`` file specifies the details needed for data capture:\n\n * ``chains`` - A parameter listing the names of the kinematic chains of the\n   robot which should be controlled.\n * ``features`` - A parameter listing the names of the various \"feature finders\"\n   that will be making our observations at each sample pose.\n\nEach of these chains and features is then defined by a parameter block of the\nsame name, for example:\n\n```yaml\nrobot_calibration:\n  ros_parameters:\n    # List of chains\n    chains:\n    - arm\n    # List of features\n    features:\n    - checkerboard_finder\n    # Parameter block to define the arm chain\n    arm:\n      topic: /arm_controller/follow_joint_trajectory\n      joints:\n      - first_joint\n      - second_joint\n    # Parameter block to define the feature finder:\n    checkerboard_finder:\n      type: robot_calibration::CheckerboardFinder\n      topic: /head_camera/depth_registered/points\n      camera_sensor_name: camera\n      chain_sensor_name: arm\n```\n\n#### Chain Parameters\n\nFor each chain, the following parameters can be defined:\n\n * ``topic`` - The namespace of the ``control_msgs::FollowJointTrajectory``\n   server used to control this chain.\n * ``planning_group`` - Optional parameter, when set to a non-empty string\n   ``robot_calibration`` will call MoveIt to plan a collision free path from\n   the current robot pose to the next capture pose. When this parameter is\n   not set, the trajectory simply interpolates from the current pose to the\n   next capture pose without collision awareness - so you need to be careful\n   when defining your series of capture poses.\n * ``joints`` - A list of joints that this group comprises.\n\n#### Finder Parameters\n\nAt a minimum, the following parameters must be set for all finders:\n\n * ``type`` - Name of the plugin to load.\n * ``camera_sensor_name`` - Every finder outputs observations from some\n   sensor - this name must match the name used later in ``calibrate.yaml``.\n * ``chain_sensor_name`` - Every finder outputs observations from some\n   chain - this name must match the name used later in ``calibrate.yaml``.\n * ``debug`` - Most finders have a debug parameter which will insert the\n   raw image or point cloud into the observation. This makes the capture\n   bagfile larger but aids in debugging.\n\nThe following types are currently included with ``robot_calibration``\nalthough you can create your own plugins. Each finder has it's own\nadditional parameters:\n\n * ``robot_calibration::CheckerboardFinder`` - Detects checkerboards in\n   a point cloud.\n    * ``topic`` - Name of topic of type ``sensor_msgs::PointCloud2``.\n    * ``points_x`` - Number of corners in the X direction of the checkerboard.\n    * ``points_y`` - Number of corners in the Y direction of the checkerboard.\n    * ``size`` - Size of checkerboard squares, in meters.\n * ``robot_calibration::CheckerboardFinder2d`` - Detects checkerboards in\n   an image:\n    * ``topic`` - Name of topic of type ``sensor_msgs::Image``.\n    * ``points_x`` - Number of corners in the X direction of the checkerboard.\n    * ``points_y`` - Number of corners in the Y direction of the checkerboard.\n    * ``size`` - Size of checkerboard squares, in meters.\n * ``robot_calibration::LedFinder`` - controls and detects a series of LEDs,\n   which can be a built-in alternative to having a robot hold the checkerboard.\n    * ``gripper_led_action`` - Namespace of the gripper LED action server.\n    * ``topic`` - Name of topic of type ``sensor_msgs::PointCloud2``.\n    * ``max_error`` - Maximum distance detected LED can be from expected pose,\n      in meters.\n    * ``max_inconsistency`` - Maximum relative difference between two LEDs in\n      the same capture pose, in meters.\n    * ``max_iterations`` - Maximum number of times to toggle the LEDs for a given\n      capture pose.\n    * ``gripper_led_frame`` - The robot link which the ``leds`` are defined in.\n    * ``leds`` - Definition of the LED poses. For each LED, you need to specify\n      a ``code`` which is sent to the action server to turn that LED on, as well\n      as ``x``, ``y``, and ``z`` offsets relative to ``gripper_led_frame`` for\n      the expected pose of that LED. These values will be used to generate\n      the chain observation.\n * ``robot_calibration::PlaneFinder`` - Detects planes in a point cloud. This\n   will filter out points outside the limits, and then iteratively find the\n   largest plane until a desired one is found. This is commonly used to align\n   a sensor with the ground.\n    * ``topic`` - Name of topic of type ``sensor_msgs::PointCloud2``.\n    * ``points_max`` - Maximum number of points to use in the observation\n    * The cloud can be pre-filtered using the ``min_x``, ``max_x``, ``min_y``,\n      ``max_y``, ``min_z``, and ``max_z`` parameters.\n    * The desired orientation of the plane can be used by setting ``normal_a``,\n      ``normal_b``, ``normal_c`` parameters - if all are 0, the biggest plane\n      will be selected regardless of orientation. This is particularly useful\n      if the robot might be looking partially at the wall as well as the desired\n      floor surface.\n    * ``normal_angle`` - If a desired orientation vector is set, the candidate\n      plane normal must be within this angle of the desired normal, in radians.\n * ``robot_calibration::ScanFinder`` - Detects points in a laser scan, and then\n   repeats them vertically. This can be used to align a laser scanner against\n   a plane detected by a 3d camera.\n    * ``topic`` - Name of topic of type ``sensor_msgs::LaserScan``.\n    * ``transform_frame`` -- Frame to transform the laser scan into, usually\n      ``base_link``.\n    * ``min_x``, ``max_x``, ``min_y``, and ``max_y`` are used to limit the\n      laser scan points that are used. They are defined in the ``transform_frame``.\n    * ``z_repeats`` - How many times to copy the points vertically.\n    * ``z_offset`` - Distance between repeated points.\n\nAdditionally, any finder that subscribes to a depth camera has the following parameters:\n\n * ``camera_info_topic``: The topic name for the camera info.\n * ``camera_driver``: Namespace of the camera driver, only used for Primesense-like\n   devices which have ``z_offset_mm`` and ``z_scaling`` parameters.\n\n### Calibration Configuration\n\nThe ``calibrate.yaml`` configuration file specifies the configuration for\noptimization. This specifies several items:\n\n * ``base_link`` - Frame used for internal calculations. Typically, the root of the\n   URDF is used. Often `base_link`.\n * ``calibration_steps`` - In ROS 2, multistep calibration is fully supported. The\n   parameter ``calibration_steps`` should be a list of step names. A majority of\n   calibrations probably only use a single step, but the step name must still\n   be in a YAML list format.\n\n```yaml\nrobot_calibration:\n  ros__parameters:\n    base_link: torso_lift_link\n    calibration_steps:\n    - single_calibration_step\n    single_calibration_step:\n      models:\n      - first_model\n      first_model:\n        type: first_model_type\n```\n\nFor each calibration step, there are several parameters:\n\n * ``models`` - List of model names. Each model will then be defined in a\n   parameter block defined by the name. Models define how to reproject\n   observation points into the fixed frame. The basic model is a\n   kinematic chain. Additional models can reproject through a kinematic\n   chain and then a sensor, such as a 3d camera. Once loaded, models\n   will be used by the error blocks to compute the reprojection errors\n   between different sensor observations.\n * ``free_params`` - Defines the names of single-value free parameters. These\n   can be the names of a joint for which the joint offset should be calculated,\n   camera parameters such as focal lengths or the driver offsets for\n   Primesense devices. If attempting to calibrate the length of a robot\n   link, use `free_frames` to define the axis that is being calibrated.\n * ``free_frames`` - Defines the names of multi-valued free parameters that\n   are 6-d transforms. Also defines which axis are free. X, Y, and Z can all\n   be independently set to free parameters. Roll, pitch and yaw can also be\n   set free, however it is important to note that because calibration\n   internally uses an angle-axis representation, either all 3 should be set\n   free, or only one should be free. You should never set two out of three\n   to be free parameters.\n * ``free_frames_initial_values`` - Defines the initial offset values for\n   ``free_frames``. X, Y, Z offsets are in meters. ROLL, PITCH, YAW are in\n   radians. This is most frequently used for setting the initial estimate\n   of the checkerboard position, see details below.\n * ``error_blocks`` - List of error block names, which are then defined\n   under their own namespaces.\n\nFor each model, the `type` must be specified. The type should be one of:\n\n * ``chain3d`` - Represents a kinematic chain from the `base_link` to the `frame`\n   parameter (which in MoveIt/KDL terms is usually referred to as the `tip`).\n * ``camera3d`` - Represents a kinematic chain from the `base_link` to the `frame`\n   parameter, and includes the pinhole camera model parameters (cx, cy, fx, fy)\n   when doing projection of the points. This model only works if your sensor\n   publishes CameraInfo. Further, the calibration obtained when this model is\n   used and any of the pinhole parameters are free parameters is only valid if\n   the physical sensor actually uses the CameraInfo for 3d projection (this\n   is generally true for the Primesense/Astra sensors).\n * ``camera2d`` - Similar to `camera3d`, but for a 2d finder. Currently only\n   works with the output of the ``CheckerboardFinder2d``.\n\nFor each error block, the ``type`` must be specified. In addition to the\n``type`` parameter, each block will have additional parameters:\n\n * ``chain3d_to_chain3d`` - The most commonly used error block type.\n   This error block can compute the difference in reprojection\n   between two 3D \"sensors\" which tell us the position of\n   certain features of interest. Sensors might be a 3D camera or an arm\n   which is holding a checkerboard. Was previously called \"camera3d_to_arm\":\n    * `model_a` - First `chain3d` or `camera3d` model to use in computing\n      reprojection error.\n    * `model_b` - Second `chain3d` or `camera3d` model to use in computing\n      reprojection error.\n * ``chain3d_to_camera2d``- Currently only used for the `CheckerboardFinder2d`:\n    * `model_2d` - `camera2d` model to use in computing reprojection error.\n    * `model_3d` - `chain3d` or `camera3d` model to use in computing\n      reprojection error.\n    * `scale` - Scalar to multiply summed error by - note that error computed\n      in this block is in *pixel* space, rather than *metric* space like most\n      other error blocks.\n * ``chain3d_to_mesh`` - This error block type can compute the closeness between\n   projected 3d points and a mesh. The mesh must be part of the robot body.\n   This is commonly used to align the robot sensor with the base of the robot,\n   using points that were found by the `RobotFinder` plugin:\n    * `model` - `chain3d` or `camera3d` model to use in computing reprojection\n      error.\n    * `link_name` -Name of the link in the URDF for which mesh to use.\n * ``chain3d_to_plane`` - This error block can be used to compare projected\n   points to a plane. Each observation point is reprojected, then the sum\n   of distance to plane for each point is computed. The most common use case\n   is making sure that the ground plane a robot sees is really on the ground:\n    * `model` - The `camera3d` model for reprojection.\n    * `a`, `b`, `c`, `d` - Parameters for the desired plane equation, in the\n      form `ax + by + cz + d = 0`.\n    * `scale` - Since the error computed is a distance from the plane over\n      many points, scaling the error relative to other error blocks is often\n      required.\n * ``plane_to_plane`` - This error block is able to compute the difference\n   between two planes. For instance, 3d cameras may not have the resolution\n   to actually see a checkerboard, but we can align important axis by\n   making sure that a wall seen by both cameras is aligned. For each observation,\n   the points are assumed to form a plane:\n    * `model_a` - First `chain3d` or `camera3d` model to use in computing\n      reprojection error.\n    * `model_b` - Second `chain3d` or `camera3d` model to use in computing\n      reprojection error.\n    * `normal_scale` - The normal error is computed as the difference between\n      the two plane normals and then multiplied by this scalar.\n    * `offset_scale` - The offset error is computed as the distance from\n      the centroid of the first plane to the second plane and then\n      multiplied by this scalar.\n * ``outrageous`` - Sometimes, the calibration is ill-defined in certain dimensions,\n   and we would like to avoid one of the free parameters from becoming\n   absurd. An outrageous error block can be used to limit a particular\n   parameter:\n    * `param` - Free parameter to monitor.\n    * `joint_scale` - If `param` is a joint name, multiply the free param value\n      by this scalar.\n    * `position_scale` - If `param` is a free frame, multiply the metric distance\n      in X, Y, Z by this scalar.\n    * `rotation_scale` - If `param` is a free frame, multiply the angular distance\n      of the free parameter value by this scalar.\n\n### Calibration Poses\n\nThe final piece of configuration is the actual poses from which the robot should\ncapture data. This YAML file can be created by running the `capture_poses` script.\nYou will be prompted to move the robot to the desired pose and press ENTER, when\ndone collecting all of your poses, you can type EXIT.\nThis will create `calibration_poses.yaml` which is an array of capture poses:\n\n```yaml\n- features: []\n  joints:\n  - first_joint\n  - second_joint\n  positions:\n  - -0.09211555123329163\n  - 0.013307283632457256\n- features: []\n  joints:\n  - first_joint\n  - second_joint\n  positions:\n  - -1.747204065322876\n  - -0.07186950743198395\n```\n\nBy default, every finder is used for every capture pose. In some cases, you might\nwant to specify specific finders by editing the `features`:\n\n```yaml\n# This sample pose uses only the `ground_plane_finder` feature finder\n- features:\n  - ground_plane_finder\n  joints:\n  - first_joint\n  - second_joint\n  positions:\n  - -0.09211555123329163\n  - 0.013307283632457256\n# This sample pose will use all features\n- features: []\n  joints:\n  - first_joint\n  - second_joint\n  positions:\n  - -1.747204065322876\n  - -0.07186950743198395\n```\n\n#### Checkerboard Configuration\n\nWhen using a checkerboard, we need to estimate the transformation from the\nthe tip of the kinematic chain to the virtual ``checkerboard`` frame.\nCalibration will be faster and more accurate if the initial estimate of\nthis transformation is close to the actual\nvalue, especially with regards to rotation.\n\nThe simplest way to check your initial estimate is to run the calibration with\nonly the six DOF of the checkerboard as free parameters. The output values will\nbe the X, Y, Z, and A, B, C of the transformation. It is important to note that\nA, B, C are NOT roll, pitch, yaw -- they are the axis-magnitude representation.\nTo get roll, pitch and yaw, run the ``to_rpy`` tool with your values of A, B,\nand C:\n```\nros2 run robot_calibration to_rpy A B C\n```\nThis will print the ROLL, PITCH, YAW values to put in for initial values. Then\ninsert the values in the calibration.yaml:\n```yaml\nfree_frames_initial_values:\n- checkerboard\ncheckerboard_initial_values:\n  x: 0.0\n  y: 0.225\n  z: 0\n  roll: 0.0\n  pitch: 1.571\n  yaw: 0.0\n```\n\n[This tool](https://markhedleyjones.com/projects/calibration-checkerboard-collection)\ncan be helfpul for creating checkerboards.\n\n### Exported Results\n\nThe exported results consist of an updated URDF file, and one or more updated\ncamera calibration YAML files. By default, these files will by exported into\nthe /tmp folder, with filenames that include a timestamp of generation. These\nfiles need to be installed in the correct places to be properly loaded.\n\nThe [fetch_calibration](https://github.com/fetchrobotics/fetch_ros/tree/indigo-devel/fetch_calibration)\npackage has an example python script for installing the updated files.\n\nWithin the updated URDF file, there are two types of exported results:\n\n * Changes to free_frames are applied as offsets in the joint origins.\n * Changes to free_params (joint offsets) are applied as \"calibration\" tags\n   in the URDF. In particular, they are applied as \"rising\" tags. These\n   should be read by the robot drivers so that the offsets can be applied\n   before joint values are used for controllers. The offsets need to be added\n   to the joint position read from the device. The offset then typically\n   needs to be subtracted from the commanded position sent to the device.\n\nIf your robot does not support the \"calibration\" tags, it might be possible\nto use only free_frames, setting only the rotation in the joint axis to be\nfree.\n\n## The _base_calibration_node_\n\nTo run the _base_calibration_node_ node, you need a somewhat open space with a large\n(~3 meters wide) wall that you can point the robot at.\n\nStarting with the `0.10` release of `robot_calibration`, the actual movements the\nrobot does can be programmed via the `calibration_steps` parameter:\n\n * \u003ccode\u003ecalibration_steps\u003c/code\u003e - should be a list of string names of calibration\n   steps to run.\n * \u003ccode\u003estep_name/type\u003c/code\u003e - should be either `spin` or `rollout`.\n * \u003ccode\u003estep_name/velocity\u003c/code\u003e - velocity to move the robot. This will be\n   interpreted as angular velocity for `spin` steps and linear velocity for `rollout`\n   steps.\n * \u003ccode\u003estep_name/rotations\u003c/code\u003e - only valid for `spin` steps. Number of\n   rotations to complete at given `velocity`.\n * \u003ccode\u003estep_name/distance\u003c/code\u003e - only valid for `rollout` steps. Distance\n   in meters, to rollout the robot.\n\nAdditional parameters:\n\n * \u003ccode\u003eaccel_limit\u003c/code\u003e - acceleration limit for `spin` steps (radians/second^2).\n * \u003ccode\u003elinear_accel_limit\u003c/code\u003e - acceleration limit for `rollout` steps (meters/second^2).\n * \u003ccode\u003emin_angle/max_angle\u003c/code\u003e how much of the laser scan to use when\n   measuring the wall angle (radians).\n\nNode topics:\n\n * \u003ccode\u003e/odom\u003c/code\u003e - the node subscribes to this odom data. Message type\n   is \u003ccode\u003enav_msgs/Odometry\u003c/code\u003e.\n * \u003ccode\u003e/imu\u003c/code\u003e - the node subscribes to this IMU data. Message type\n   is \u003ccode\u003esensor_msgs/IMU\u003c/code\u003e.\n * \u003ccode\u003e/base_scan\u003c/code\u003e - the node subscribes to this laser data. Message type\n   is \u003ccode\u003esensor_msgs/LaserScan\u003c/code\u003e.\n * \u003ccode\u003e/cmd_vel\u003c/code\u003e - the node publishes rotation commands to this topic, unless\n   manual mode is enabled. Message type is \u003ccode\u003egeometry_msgs/Twist\u003c/code\u003e.\n\nThe output of the node is a series of scalars to apply (where a value of 1.0 means\nthere is currently no error):\n\n```\n[base_calibration_node-1] track_width_scale: 0.986743\n[base_calibration_node-1] imu_scale: 0.984465\n[base_calibration_node-1] rollout_scale: 0.981911\n```\n\nThe application of these values is largely dependent on the drivers being used\nfor the robot. For robots using _ros_control_ or _robot_control_ there is a\n`track_width` parameter typically supplied as a ROS parameter in your launch file.\n\nNote: in ROS 1, these scalars were pre-multiplied by the existing `track_width`\nor `imu_scale` - however, with the lack of a unified parameter server in ROS 2,\nthis is no longer done.\n\n## The _magnetometer_calibration_ node\n\nThe _magnetometer_calibration_ node records magnetometer data and can compute\nthe _hard iron_ offsets. After calibration, the magnetometer can be used as\na compass (typically by piping the data through _imu_filter_madgwick_ and\nthen _robot_localization_).\n\nNode parameters:\n\n * \u003ccode\u003e~rotation_manual\u003c/code\u003e - if set to true, the node will not publish command\n   velocities and the user will have to manually rotate the magnetometer. Default: false.\n * \u003ccode\u003e~rotation_duration\u003c/code\u003e - how long to rotate the robot, in seconds.\n * \u003ccode\u003e~rotation_velocity\u003c/code\u003e - the yaw velocity to rotate the robot, in rad/s.\n\nNode topics:\n\n * \u003ccode\u003e/imu/mag\u003c/code\u003e - the node subscribes to this magnetometer data. Message type\n   is \u003ccode\u003esensor_msgs/MagneticField\u003c/code\u003e.\n * \u003ccode\u003e/cmd_vel\u003c/code\u003e - the node publishes rotation commands to this topic, unless\n   manual mode is enabled. Message type is \u003ccode\u003egeometry_msgs/Twist\u003c/code\u003e.\n\nThe output of the calibration is three parameters, _mag_bias_x_, _mag_bias_y_,\nand _mag_bias_z_, which can be used with the \u003ccode\u003eimu_filter_madgwick\u003c/code\u003e package.\n\n### Migrating from ROS1\n\nThere are a number of changes in migrating from ROS1 to ROS2. Some of these are\ndue to differences in the ROS2 system, others are to finally cleanup mistakes\nmade in earlier version of robot_calibration.\n\nThe `chains`, `models`, `free_frames` and `features` parameters used to be lists of YAML\ndictionaries. That format is not easily supported in ROS2 and so they are now\nlists of string names and the actual dictionaries of information appear under\nthe associated name. For instance, in ROS1, you might have:\n\n```yaml\nmodels:\n - name: arm\n   type: chain\n   frame: wrist_roll_link\n - name: camera\n   type: camera3d\n   frame: head_camera_rgb_optical_frame\n```\n\nIn ROS2, this becomes:\n```yaml\nmodels:\n- arm\n- camera\narm:\n  type: chain3d\n  frame: wrist_roll_link\ncamera:\n  type: camera3d\n  frame: head_camera_rgb_optical_frame\n```\n\nNOTE: the \"chain\" type has been renamed \"chain3d\" in ROS2 for consistency (and to allow\na future chain2d).\n\nMulti-step calibration is now fully supported. A new parameter, `calibration_steps` must\nbe declared as a list of step names. The `models` and free parameters are then specified\nfor each step. As an example:\n\n```yaml\ncalibration_steps:\n- first_calibration_step\n- second_calibration_step\nfirst_calibration_step:\n  models: ...\n  free_params: ...\nsecond_calibration_step:\n  models: ...\n  free_params: ...\n```\n\nThe capture poses can now be specified as YAML. The `convert_ros1_bag_to_yaml` script\ncan be run in ROS1 to export your ROS1 bagfile as a YAML file that can be loaded in ROS2.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmikeferguson%2Frobot_calibration","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmikeferguson%2Frobot_calibration","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmikeferguson%2Frobot_calibration/lists"}