{"id":13721165,"url":"https://github.com/KumarRobotics/multicam_calibration","last_synced_at":"2025-05-07T13:32:01.969Z","repository":{"id":50547880,"uuid":"117025898","full_name":"KumarRobotics/multicam_calibration","owner":"KumarRobotics","description":null,"archived":false,"fork":false,"pushed_at":"2023-02-14T22:12:54.000Z","size":10541,"stargazers_count":122,"open_issues_count":0,"forks_count":38,"subscribers_count":46,"default_branch":"master","last_synced_at":"2025-04-11T13:13:14.884Z","etag":null,"topics":["apriltags","camera-calibration","ceres-solver","ros"],"latest_commit_sha":null,"homepage":null,"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/KumarRobotics.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":"2018-01-10T23:55:02.000Z","updated_at":"2025-04-11T03:47:36.000Z","dependencies_parsed_at":"2024-11-14T10:42:07.431Z","dependency_job_id":null,"html_url":"https://github.com/KumarRobotics/multicam_calibration","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/KumarRobotics%2Fmulticam_calibration","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/KumarRobotics%2Fmulticam_calibration/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/KumarRobotics%2Fmulticam_calibration/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/KumarRobotics%2Fmulticam_calibration/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/KumarRobotics","download_url":"https://codeload.github.com/KumarRobotics/multicam_calibration/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252886477,"owners_count":21819723,"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":["apriltags","camera-calibration","ceres-solver","ros"],"created_at":"2024-08-03T01:01:13.153Z","updated_at":"2025-05-07T13:31:58.324Z","avatar_url":"https://github.com/KumarRobotics.png","language":"C++","funding_links":[],"categories":["Sensor Processing"],"sub_categories":["Calibration and Transformation"],"readme":"# multicam_calibration - extrinsic and intrinsic calbration of cameras\n\n## Installation\n\nDownload the package:\n\t\n\tmkdir catkin_ws\n\tcd catkin_ws\n\tmkdir src\n\tcd src\n\tgit clone https://github.com/KumarRobotics/multicam_calibration.git\n\nYou will need the following packages in your ROS workspace:\n\n\tgit clone https://github.com/catkin/catkin_simple\n\tgit clone --recursive https://github.com/versatran01/apriltag.git\n\n\nAnd probably libceres:\n\n\tsudo apt install libceres-dev\n\n\nWhat else you are missing you'll find out now:\n\n\tcd catkin_ws\n\tcatkin config -DCMAKE_BUILD_TYPE=Release\n\tcatkin build\n\n## How to use:\n\nFirst, produce the best starting guess you can come up with,\nand edit it into ``calib/example/example_camera-initial.yaml``:\n\n\tcam0:\n\t  camera_model: pinhole\n\t  intrinsics: [605.054, 604.66, 641.791, 508.728]\n\t  distortion_model: equidistant\n\t  distortion_coeffs: [-0.0146915, 0.000370396, -0.00425216, 0.0015107]\n\t  resolution: [1280, 1024]\n\t  rostopic: /rig/left/image_mono\n\tcam1:\n\t  T_cn_cnm1:\n\t  - [ 0.99999965648, -0.00013331925,  0.00081808159, -0.19946344647]\n\t  - [ 0.00013388601,  0.99999975107, -0.00069277676, -0.00005674605]\n\t  - [-0.00081798903,  0.00069288605,  0.99999942540,  0.00010022941]\n\t  - [ 0.00000000000,  0.00000000000,  0.00000000000,  1.00000000000]\n\t  camera_model: pinhole\n\t  intrinsics: [605.097, 604.321, 698.772, 573.558]\n\t  distortion_model: equidistant\n\t  distortion_coeffs: [-0.0146155, -0.00291494, -0.000681981, 0.000221855]\n\t  resolution: [1280, 1024]\n\t  rostopic: /rig/right/image_mono\n\nAdjust the topics to match your camera sources.\n\nYou must use an aprilgrid target for calibration, layout follows Kalibr conventions and \nis specified in ``config/aprilgrid.yaml``.\n\nThen launch the camera calibration:\n\n\troslaunch multicam_calibration calibration.launch\n\t\nYou can see the camera images and the detected tags overlaid with any of the ros\nimage visualization tools.\n![Example Calibration Session](images/example_gui.jpg)\nThere is a sample perspective file in the config directory:\n\n\trqt --perspective-file=config/example.perspective\n\nThen play your calibration bag (or do live calibration):\n\n\trosbag play falcam_rig_2018-01-09-14-28-56.bag\n\nYou should see the tags detected, and output like this on the terminal:\n\n\ttype is multicam_calibration/CalibrationNodelet\n\t[ INFO] [1515674455.127216052]: added camera: cam0\n\t[ INFO] [1515674455.130332740]: added camera: cam1\n\t[ INFO] [1515674455.131238617]: not using approximate sync\n\t[ INFO] [1515674455.132790610]: writing extracted corners to file corners.csv\n\t[ INFO] [1515674458.646217104]: frame number:   10, total number of tags found:  349 336\n\t[ INFO] [1515674459.958243084]: frame number:   20, total number of tags found:  698 686\n\t[ INFO] [1515674461.349852261]: frame number:   30, total number of tags found:  1048 1036\n\t... more lines here ....\n\t[ WARN] [1515674512.667679323]: no detections found, skipping frame!\n\t[ INFO] [1515674512.757430315]: frame number:  410, total number of tags found:  11896 13300\n\nWhen you think you have enough frames collected, you can start the calibration:\n\n\trosservice call /multicam_calibration/calibration\n\t\nThis should give you output like this:\n\n\tNum params: 2476\n\tNum residuals: 201928\n\titer      cost      cost_change  |gradient|   |step|    tr_ratio  tr_radius  ls_iter  iter_time  total_time\n\t0  4.478809e+03    0.00e+00    5.32e+06   0.00e+00   0.00e+00  1.00e+04        0    2.45e-01    3.10e-01\n\t1  1.291247e+03    3.19e+03    2.03e+05   1.46e+00   1.55e+00  3.00e+04        1    5.11e-01    8.21e-01\n\t2  1.288842e+03    2.40e+00    6.22e+03   2.38e-01   1.04e+00  9.00e+04        1    4.56e-01    1.28e+00\n\t3  1.288794e+03    4.79e-02    3.19e+02   3.57e-02   1.02e+00  2.70e+05        1    4.37e-01    1.71e+00\n\t4  1.288792e+03    2.27e-03    3.73e+01   7.64e-03   1.01e+00  8.10e+05        1    4.38e-01    2.15e+00\n\t5  1.288792e+03    2.61e-05    5.09e+00   7.20e-04   1.01e+00  2.43e+06        1    4.38e-01    2.59e+00\n\t6  1.288792e+03    6.92e-08    5.35e-01   3.46e-05   1.03e+00  7.29e+06        1    4.37e-01    3.03e+00\n\n\tSolver Summary (v 1.12.0-eigen-(3.2.92)-lapack-suitesparse-(4.4.6)-cxsparse-(3.1.4)-openmp)\n\n\tOriginal                  Reduced\n\tParameter blocks                          410                      410\n\tParameters                               2476                     2476\n\tResidual blocks                           409                      409\n\tResidual                               201928                   201928\n\n\tMinimizer                        TRUST_REGION\n\n\tSparse linear algebra library    SUITE_SPARSE\n\tTrust region strategy     LEVENBERG_MARQUARDT\n\t\n\tGiven                     Used\n\tLinear solver          SPARSE_NORMAL_CHOLESKY   SPARSE_NORMAL_CHOLESKY\n\tThreads                                     4                        4\n\tLinear solver threads                       1                        1\n\tLinear solver ordering              AUTOMATIC                      410\n\t\n\tCost:\n\tInitial                          4.478809e+03\n\tFinal                            1.288792e+03\n\tChange                           3.190017e+03\n\t\n\tMinimizer iterations                        7\n\tSuccessful steps                            7\n\tUnsuccessful steps                          0\n\t\n\tTime (in seconds):\n\tPreprocessor                           0.0653\n\t\n\tResidual evaluation                  0.0680\n\tJacobian evaluation                  1.4113\n\tLinear solver                        1.5961\n\tMinimizer                              3.2011\n\t\n\tPostprocessor                          0.0000\n\tTotal                                  3.2663\n\t\n\tTermination:                      CONVERGENCE (Function tolerance reached. |cost_change|/cost: 1.930077e-13 \u003c= 1.000000e-12)\n\t\n\t[ INFO] [1515674589.074056064]: writing calibration to /home/pfrommer/Documents/foo/src/multicam_calibration/calib/example/example_camera-2018-01-11-07-43-09.yaml\n\tcam0:\n\tcamera_model: pinhole\n\tintrinsics: [604.355, 604.153, 642.488, 508.135]\n\tdistortion_model: equidistant\n\tdistortion_coeffs: [-0.014811, -0.00110814, -0.00137418, 0.000474477]\n\tresolution: [1280, 1024]\n\trostopic: /rig/left/image_mono\n\tcam1:\n\tT_cn_cnm1:\n\t- [ 0.99999720028,  0.00030730438,  0.00234627487, -0.19936845450]\n\t- [-0.00030303357,  0.99999829718, -0.00182038902,  0.00004464487]\n\t- [-0.00234683029,  0.00181967292,  0.99999559058,  0.00029671670]\n\t- [ 0.00000000000,  0.00000000000,  0.00000000000,  1.00000000000]\n\tcamera_model: pinhole\n\tintrinsics: [604.364, 603.62, 698.645, 573.02]\n\tdistortion_model: equidistant\n\tdistortion_coeffs: [-0.0125438, -0.00503567, 0.00031359, 0.000546495]\n\tresolution: [1280, 1024]\n\trostopic: /rig/right/image_mono\n\t[ INFO] [1515674589.251025662]: ----------------- reprojection errors: ---------------\n\t[ INFO] [1515674589.251045482]: total error:     0.283519 px\n\t[ INFO] [1515674589.251053450]: avg error cam 0: 0.28266 px\n\t[ INFO] [1515674589.251059520]: avg error cam 1: 0.284286 px\n\t[ INFO] [1515674589.251070091]: max error: 8.84058 px at frame: 110 for cam: 1\n\t[ INFO] [1515674589.251410620]: -------------- simple homography test ---------\n\t[ INFO] [1515674589.331235450]: camera: 0 points: 47700 reproj err: 0.440283\n\t[ INFO] [1515674589.331257726]: camera: 1 points: 53252 reproj err: 0.761365\n\nIn the ``calib/example`` directory you can now find the output of the calibration:\n\n\tls -1\n\texample_camera-2018-01-11-08-24-22.yaml\n\texample_camera-initial.yaml\n\texample_camera-latest.yaml\n\n## Parameters\n\n- ``use_approximate_sync``: (default: false) uses the ROS approximate sync framework to\n  approximately synchronize image frames with different message header\n  stamps.\n- ``corners_file``: if a corners file is specified, such corners file is\n  loaded as input data when the calibration node starts up, as if\n  these corners had been detected by \n  feeding images to the calibration node. This allows repeating of\n  previously done calibrations by keeping the corners file instead of\n  all the images. Whenever points are fed into the calibration node,\n  it writes the corners to ``~/.ros/corners.csv``.\n- ``run_calib_no_init``: run calibration right after loading the\n  corners file. This is mostly for debugging purposes.\n- ``fix_intrinsics``: fixes all intrinsics. Note that more\n  fine-grained fixing of intrinsics for individual cameras can be done\n  on the fly with ROS service calls.\n- ``record_bag``: was supposed to record the images that were used for\n  calibration, but this feature is currently broken due to some ROS\n  bug.\n- ``outlier_pixel_threshold`` (default: -1). If specified greater than\n  0 will remove any detected corners that exceed the error threshold\n  and re-run the calibration again. Note: new option, has not seen\n  much testing yet.\n- ``output_filename``, ``latest_link_name``, ``calib_dir``, and\n  ``results_dir`` combined specify where to look for the initial files\n  and where the calibration results will go. The parameterization is\n  somewhat confusing so it's best to look at the example launch files\n  and/or the source code.\n- ``detector_type``: (default: ``Mit``) allows to switch between the\n  MIT and the ``Umich`` version of the apriltag implementation\n- ``tag_border``: (only valid if using the ``Mit`` detector, specifies\n  the width of the black border frame of the tags, defaults to 2).\n\n## Managed calibrations\n\nSometimes a calibration consists of a sequence of steps, for example: first the\nintrinsics of each sensor, then the extrinsics of the sensors with\nrespect to each other. This is particularly useful when image data\nbetween sensors is not synchronized.\n\nTo help with this, you can write a little python program that does\nthat. In fact, you just have to modify the section below in\n``src/example_calib_manager.py``, and voila, when you trigger your\ncalibration manager, it will in turn run multiple calibrations via\nservice calls into the calibration node, each time retaining the\nprevious calibration's output as initial value. Here is an example\nsection, adjust as needed:\n\n        # first do intrinsics of cam0\n        set_p(FIX_INTRINSICS, \"cam0\", False)\n        set_p(FIX_EXTRINSICS, \"cam0\", True)\n        set_p(SET_ACTIVE,     \"cam0\", True)\n        set_p(FIX_INTRINSICS, \"cam1\", True)\n        set_p(FIX_EXTRINSICS, \"cam1\", True)\n        set_p(SET_ACTIVE,     \"cam1\", False)\n        run_cal()\n        # then do intrinsics of cam1\n        set_p(FIX_INTRINSICS, \"cam0\", True)\n        set_p(FIX_EXTRINSICS, \"cam0\", True)\n        set_p(SET_ACTIVE,     \"cam0\", False)\n        set_p(FIX_INTRINSICS, \"cam1\", False)\n        set_p(FIX_EXTRINSICS, \"cam1\", True)\n        set_p(SET_ACTIVE,     \"cam1\", True)\n        run_cal()\n        # now extrinsics between the two\n        set_p(FIX_INTRINSICS, \"cam0\", True)\n        set_p(FIX_EXTRINSICS, \"cam0\", True)\n        set_p(SET_ACTIVE,     \"cam0\", True)\n        set_p(FIX_INTRINSICS, \"cam1\", True)\n        set_p(FIX_EXTRINSICS, \"cam1\", False)\n        set_p(SET_ACTIVE,     \"cam1\", True)\n        run_cal()\n\n## Unit tests\n\nFor unit testing of the calibration code, refer to [this page](test/README.md).\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FKumarRobotics%2Fmulticam_calibration","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FKumarRobotics%2Fmulticam_calibration","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FKumarRobotics%2Fmulticam_calibration/lists"}