> For clean Markdown of any page, append .md to the page URL. > For a complete documentation index, see https://docs.stereolabs.com/docs/development/zed-sdk/modules/global-localization/vio-gnss-calibration/llms.txt. > For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.stereolabs.com/_mcp/server. # VIO GNSS calibration ## Summary GNSS and **V**isual **I**nertial **O**dometry (VIO) calibration is an important step for fusion. GNSS positions are globally referenced and always aligned to the North, while VIO reference and orientation depend on the camera's starting point. Combining this data requires finding the world transformation that allows the projection of the VIO reference frame into the GNSS reference frame, and vice versa. The differences between the VIO and GNSS trajectories of the **same moving agent** are illustrated in the following figure. It is important to note that these trajectories have different origins, highlighting the need for alignment between the VIO and GNSS systems. Please also note that synchronized GNSS / VIO data pairs are linked by a thin gray line. ![](/_fern-img/b9dadd7c252cfcfece26bc864df3dc201be5a1b78bd00e2ccf0c9d1ede27c84d.webp) The VIO path sent for fusion is consistently aligned with gravity. As illustrated in the following figure, aligning the VIO and GNSS systems requires determining 4 parameters: * The **yaw rotation** (1 parameter) between the GNSS coordinate system and the VIO coordinate system. * The **translation** (3 parameters: X-Y-Z) difference between the start of VIO acquisition and the start of GNSS acquisition. ![](/_fern-img/4b5af1c303413c8ace30900eb271b4e37f1fe2e21fe9cb06f0990a460ceaea9f.webp) Once calibrated our fusion module is able to project the GNSS into VIO or vice versa. The left figure illustrates GNSS projected on VIO and the right figure illustrates VIO projected on GNSS. ![](/_fern-img/8695c097237276f83da29c8839468654ba056108a557fd53aa41f69045a8d0c1.webp)![](/_fern-img/ec5a32ad53baacce1ec4732e174da4d3b4a97ca2e616e09d6c1135d71c158c84.webp) ## Coordinate system model In all our schematics, the transformations are expressed in a coordinate-basis form. Let’s explain this. Let’s suppose that you have two coordinate systems **A** and **B**. The two coordinate systems can be related to each other through another coordinate system named W, as shown in the schematic below: ![](/_fern-img/a6b2a45569dc869e544a1dbee9864a4ff47cce0bdfdb8194da16f46a069a2b96.webp) The transformation matrix that allows a coordinate system change between B and A can be defined as `Tab = inverse(A) x B`: ![](/_fern-img/0a921ae3daf668bc52d0cbefb86732cd07832642625935266af6a7faaeb1b548.webp) Let’s now consider a transformation expressed in coordinate system `A`, noted `Ta`, and the same transformation expressed in coordinate system `B`, noted `Tb`, following the schematic below. The link between these transformations can be noted as: $$ T_b = T_{ab}^{-1} \times T_a \times T_{ab} $$ and $$ T_a = T_{ab} \times T_b \times T_{ab}^{-1} $$ ![](/_fern-img/7b759bb72e7c4bba7c68708df75117652180da5b52bf6fbadf2ed4a03978f0f0.webp) Following our definitions above, we can define the VIO and GNSS coordinate systems and establish the link between them. This is expressed in the schematic below. The `Tcalib` transformation is what is estimated by GNSS / VIO calibration. It can be retrieved using the [getGeoTrackingCalibration](https://www.stereolabs.com/docs/api/classsl_1_1Fusion.html#a97a79c2a9c28bbecd17e3c34271f7f6d) method. On the other hand, the `Tantenna` transformation is provided through the `gnss_antenna_position` parameter. If it is not specified, it will be set to identity. ![](/_fern-img/f628b75ffffde654c18551bf704913f021a2a141083a8a77368f38a3078538ab.webp) With the help of the schematic above, we can define the link between GNSS and VIO: $$ T_{VIO-projected-in-GNSS} = T_{calib} \times T_{VIO} \times T_{antenna} $$ $$ T_{GNSS-projected-in-VIO} = T_{calib}^{-1} \times T_{GNSS} \times T_{antenna} $$ These formulas are helpful for understanding what is done under the hood. However, in practice please use [Camera2Geo](https://www.stereolabs.com/docs/api/classsl_1_1Fusion.html#ae2d7b895506db48198cfcd231c87b02d) and [Geo2Camera](https://www.stereolabs.com/docs/api/classsl_1_1Fusion.html#a8daf9d6290cfc043cdce45ee1926b94f) functions that project VIO or GNSS into the requested coordinate system. ## GNSS / VIO calibration stop criteria The GNSS/VIO calibration process halts based on calibration uncertainty according to stopping criteria. Put simply, calibration concludes when a significant level of confidence in the `T_calib` transformation is obtained. The following figure shows this principle in 2D. ![](/_fern-files/stereolabs.docs.buildwithfern.com/fe75724ce4cff5d92974916b31277e88c09eeab1872e42924404a9f4076ee2dc/docs/development/zed-sdk/modules/global-localization/images/vio_gnss_coordinate_sys_uncertainty.gif) ### Set target calibration uncertainty with the API The API provides the ability to specify the target calibration uncertainty. Here are the main attributes: * **Target yaw uncertainty:** You can set the target yaw uncertainty by using the [target\_yaw\_uncertainty](https://www.stereolabs.com/docs/api/structsl_1_1GNSSCalibrationParameters.html#a6611a1154a726191bbf496b54394b990) attribute. * **Target translation uncertainty:** You can set the target translation uncertainty by using the [target\_translation\_uncertainty](https://www.stereolabs.com/docs/api/structsl_1_1GNSSCalibrationParameters.html#a1d3898f6509613cf665d937ca4710844) attribute. > **Note** > > By default, only the yaw uncertainty is taken as the final calibration criterion. If you want to include translation, you need to set the [enable\_translation\_uncertainty\_target](https://www.stereolabs.com/docs/api/structsl_1_1GNSSCalibrationParameters.html#a8ff63f3619c58c5070503d43bd30ab26) parameter to `true`. ### My application needs quick estimation of the GNSS / VIO calibration If your use-case requires a quick estimation of the current [GeoPose](https://www.stereolabs.com/docs/api/classsl_1_1GeoPose.html), you can enable the option [enable\_rolling\_calibration](https://www.stereolabs.com/docs/api/structsl_1_1GNSSCalibrationParameters.html#a9bedf754ca68763518bb28cd686ff67a). This allows the system to utilize the initial calibration estimation for computing [GeoPose](https://www.stereolabs.com/docs/api/classsl_1_1GeoPose.html), even if the accuracy of these initial estimations may not be optimal yet. ## Set calibration parameters inside SDK As introduced previously, the calibration parameters can be set using the [GNSSCalibrationParameters](https://www.stereolabs.com/docs/api/structsl_1_1GNSSCalibrationParameters.html) object. Here is a full example: **`C++`** ```cpp C++ sl::PositionalTrackingFusionParameters positional_tracking_fusion_parameters; sl::GNSSCalibrationParameters gnss_calibration_parameter; gnss_calibration_parameter.enable_reinitialization = false; gnss_calibration_parameter.enable_translation_uncertainty_target = false; gnss_calibration_parameter.gnss_vio_reinit_threshold = 5; gnss_calibration_parameter.target_yaw_uncertainty = 1e-2; gnss_calibration_parameter.gnss_antenna_position = sl::float3(0, 0, 0); // Please set your Antenna position here positional_tracking_fusion_parameters.gnss_calibration_parameters = gnss_calibration_parameter; positional_tracking_fusion_parameters.enable_GNSS_fusion = true; sl::FUSION_ERROR_CODE tracking_error_code = fusion.enablePositionalTracking(positional_tracking_fusion_parameters); ```