> For clean Markdown of any page, append .md to the page URL. > For a complete documentation index, see https://docs.stereolabs.com/docs/tutorials/positional-tracking/llms.txt. > For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.stereolabs.com/_mcp/server. # Tutorial - Using Camera Tracking This tutorial shows how to enable the Positional Tracking module and get the real-time position and orientation (pose) of the camera in the world reference frame. The program loops until 1000 positions are grabbed. We assume that you have followed the previous tutorials. ## Getting Started * First, download the latest version of the [ZED SDK](https://www.stereolabs.com/developers/). * Download the [Positional Tracking](https://github.com/stereolabs/zed-sdk/tree/master/tutorials/tutorial%204%20-%20positional%20tracking/) sample code in C, C++, Python or C#. ## Code Overview ### Open the camera As in previous tutorials, we create, configure and open the ZED. **`C++`** ```cpp C++ // Create a ZED camera object Camera zed; // Set configuration parameters InitParameters init_params; init_params.camera_resolution = RESOLUTION::HD720; // Use HD720 video mode (default fps: 60) init_params.coordinate_system = COORDINATE_SYSTEM::RIGHT_HANDED_Y_UP; // Use a right-handed Y-up coordinate system init_params.coordinate_units = UNIT::METER; // Set units in meters // Open the camera ERROR_CODE err = zed.open(init_params); if (err != ERROR_CODE::SUCCESS) exit(-1); ``` **`Python`** ```python Python # Create a ZED camera object zed = sl.Camera() # Set configuration parameters init_params = sl.InitParameters() init_params.camera_resolution = sl.RESOLUTION.HD720 # Use HD720 video mode (default fps: 60) # Use a right-handed Y-up coordinate system init_params.coordinate_system = sl.COORDINATE_SYSTEM.RIGHT_HANDED_Y_UP init_params.coordinate_units = sl.UNIT.METER # Set units in meters # Open the camera err = zed.open(init_params) if err != sl.ERROR_CODE.SUCCESS: exit(1) ``` **`C#`** ```csharp C# // Create a ZED camera object Camera zed = new Camera(0); // Set configuration parameters InitParameters init_params = new InitParameters(); init_params.resolution = RESOLUTION.HD720; // Use HD720 video mode (default fps: 60) init_params.coordinateSystem = COORDINATE_SYSTEM.RIGHT_HANDED_Y_UP; // Use a right-handed Y-up coordinate system init_params.coordinateUnits = UNIT.METER; // Set units in meters // Open the camera ERROR_CODE err = zed.Open(ref init_params); if (err != ERROR_CODE.SUCCESS) Environment.Exit(-1); ``` ### Enable positional tracking Once the camera is opened, we must enable the positional tracking module with `enablePositionalTracking()` in order to get the position and orientation of the ZED. **`C++`** ```cpp C++ // Enable positional tracking with default parameters PositionalTrackingParameters tracking_parameters; err = zed.enablePositionalTracking(tracking_parameters); if (err != ERROR_CODE::SUCCESS) exit(-1); ``` **`Python`** ```python Python # Enable positional tracking with default parameters tracking_parameters = sl.PositionalTrackingParameters() err = zed.enable_positional_tracking(tracking_parameters) if err != sl.ERROR_CODE.SUCCESS: exit(1) ``` **`C#`** ```csharp C# // Enable positional tracking with default parameters PositionalTrackingParameters trackingParameters = new PositionalTrackingParameters(); err = zed.EnablePositionalTracking(ref trackingParameters); if (err != ERROR_CODE.SUCCESS) Environment.Exit(-1); ``` In the above example, we use the default tracking parameters set in the ZED SDK. For the list of available parameters, check the [Tracking API](https://www.stereolabs.com/docs/api/group__PositionalTracking__group.html) docs. ### Capture pose data Now that motion tracking is enabled, we create a loop to grab and retrieve the camera position. The camera position is given by the class `Pose`. This class contains the translation and orientation of the camera, as well as image timestamp and tracking confidence. A pose is always linked to a reference frame. The SDK provides two reference frames: `REFERENCE_FRAME::WORLD` and `REFERENCE_FRAME::CAMERA`. For more information, see the [Coordinate Frames](/docs/development/zed-sdk/modules/positional-tracking/coordinate-frames/) section. In this tutorial, we retrieve the camera position in the World Frame. **`C++`** ```cpp C++ // Track the camera position during 1000 frames int i = 0; sl::Pose zed_pose; while (i < 1000) { if (zed.grab() == ERROR_CODE::SUCCESS) { // Get the pose of the left eye of the camera with reference to the world frame zed.getPosition(zed_pose, REFERENCE_FRAME::WORLD); // Display the translation and timestamp printf("Translation: Tx: %.3f, Ty: %.3f, Tz: %.3f, Timestamp: %llu\n", zed_pose.getTranslation().tx, zed_pose.getTranslation().ty, zed_pose.getTranslation().tz, (unsigned long long)zed_pose.timestamp.getNanoseconds()); // Display the orientation quaternion printf("Orientation: Ox: %.3f, Oy: %.3f, Oz: %.3f, Ow: %.3f\n\n", zed_pose.getOrientation().ox, zed_pose.getOrientation().oy, zed_pose.getOrientation().oz, zed_pose.getOrientation().ow); i++; } } ``` **`Python`** ```python Python # Track the camera position during 1000 frames i = 0 zed_pose = sl.Pose() runtime_parameters = sl.RuntimeParameters() while i < 1000: if zed.grab(runtime_parameters) == sl.ERROR_CODE.SUCCESS: # Get the pose of the left eye of the camera with reference to the world frame zed.get_position(zed_pose, sl.REFERENCE_FRAME.WORLD) # Display the translation and timestamp py_translation = sl.Translation() tx = round(zed_pose.get_translation(py_translation).get()[0], 3) ty = round(zed_pose.get_translation(py_translation).get()[1], 3) tz = round(zed_pose.get_translation(py_translation).get()[2], 3) print("Translation: Tx: {0}, Ty: {1}, Tz {2}, Timestamp: {3}\n".format(tx, ty, tz, zed_pose.timestamp.get_milliseconds())) # Display the orientation quaternion py_orientation = sl.Orientation() ox = round(zed_pose.get_orientation(py_orientation).get()[0], 3) oy = round(zed_pose.get_orientation(py_orientation).get()[1], 3) oz = round(zed_pose.get_orientation(py_orientation).get()[2], 3) ow = round(zed_pose.get_orientation(py_orientation).get()[3], 3) print("Orientation: Ox: {0}, Oy: {1}, Oz {2}, Ow: {3}\n".format(ox, oy, oz, ow)) i = i + 1 ``` **`C#`** ```csharp C# // Track the camera position during 1000 frames int i = 0; sl.Pose pose = new sl.Pose(); RuntimeParameters runtimeParameters = new RuntimeParameters(); while (i < 1000) { if (zed.Grab(ref runtimeParameters) == ERROR_CODE.SUCCESS) { // Get the pose of the left eye of the camera with reference to the world frame zed.GetPosition(ref pose,REFERENCE_FRAME.WORLD); // Display the translation and timestamp Console.WriteLine("Translation : " + pose.translation + ", Timestamp : " + pose.timestamp); //Display the orientation quaternion Console.WriteLine("Rotation : " + pose.rotation); i++; } } ``` ### Inertial Data If an IMU is available (ex: ZED 2/2i, ZED Mini, ZED X family), the Positional Tracking module will fuse internal visual and inertial data to provide improved position tracking. You can also access IMU data using the code below: **`C++`** ```cpp C++ SensorsData sensor_data; if (zed.getSensorsData(sensor_data, TIME_REFERENCE::IMAGE) == ERROR_CODE::SUCCESS) { // Get IMU orientation auto imu_orientation = sensor_data.imu.pose.getOrientation(); // Get IMU acceleration auto acceleration = sensor_data.imu.linear_acceleration; cout << "IMU Orientation: {" << imu_orientation << "}, Acceleration: {" << acceleration << "}\n"; } ``` **`Python`** ```python Python sensors_data = sl.SensorsData() zed.get_sensors_data(sensors_data, sl.TIME_REFERENCE.IMAGE) zed_imu = sensors_data.get_imu_data() # Get IMU orientation zed_imu_pose = sl.Transform() ox = round(zed_imu.get_pose(zed_imu_pose).get_orientation().get()[0], 3) oy = round(zed_imu.get_pose(zed_imu_pose).get_orientation().get()[1], 3) oz = round(zed_imu.get_pose(zed_imu_pose).get_orientation().get()[2], 3) ow = round(zed_imu.get_pose(zed_imu_pose).get_orientation().get()[3], 3) print("IMU Orientation: Ox: {0}, Oy: {1}, Oz {2}, Ow: {3}\n".format(ox, oy, oz, ow)) # Get IMU acceleration acceleration = [0,0,0] zed_imu.get_linear_acceleration(acceleration) ax = round(acceleration[0], 3) ay = round(acceleration[1], 3) az = round(acceleration[2], 3) print("IMU Acceleration: Ax: {0}, Ay: {1}, Az {2}\n".format(ax, ay, az)) ``` **`C#`** ```csharp C# SensorsData sensors_data = new SensorsData(); if (zed.GetSensorsData(ref sensors_data, TIME_REFERENCE.IMAGE) == ERROR_CODE.SUCCESS) { // Get IMU orientation Quaternion imu_orientation = sensors_data.imu.fusedOrientation; // Get IMU acceleration Vector3 acceleration = sensors_data.imu.linearAcceleration; Console.WriteLine("IMU Orientation : " + imu_orientation); Console.WriteLine("Acceleration : " + acceleration); } ``` For more information on Camera-IMU and other onboard sensors, check the [Sensors](/docs/development/zed-sdk/modules/sensors/) section. ### Close the Camera After tracking the ZED camera position for 1000 frames, we disable the tracking module and close the camera. **`C++`** ```cpp C++ // Disable positional tracking and close the camera zed.disablePositionalTracking(); zed.close(); ``` **`Python`** ```python Python # Disable positional tracking and close the camera zed.disable_positional_tracking() zed.close() ``` **`C#`** ```csharp C# // Disable positional tracking and close the camera zed.DisablePositionalTracking(); zed.Close(); ``` #### Advanced Example To learn how to retrieve and display the live position and orientation of the camera in a 3D window, transform pose data and change coordinate systems and units, check the advanced [Motion Tracking](https://github.com/stereolabs/zed-sdk/tree/master/positional%20tracking) sample code.