The ZED SDK allows you to add depth, motion sensing and spatial AI to your application. Available as a standalone installer, it includes applications, tools and sample projects with source code.
ZED SDK 5.5 introduces a new generation of body tracking. GEN_2 is more robust in crowded scenes and to unusual body orientations, and it detects people further from the camera. It is up to 18% faster and up to 14% more accurate than GEN_1. Neural depth gains a precision selector: InitParameters::depth_precision set to INT8 trades a small amount of accuracy for a faster depth runtime and a lower memory footprint, up to 25% faster with 3 cameras or more. The Person & Head detection models detect people about 50% further out and are far more reliable in top-down or partially occluded views, and custom object detection models can now be optimized ahead of time instead of on first use.
Camera support extends to the ZED X One Core, over MIPI through the ZED Link MIPI capture card or over Camera-over-Ethernet through a Holoscan sensor bridge. A new center-of-exposure frame timestamp helps align frames with sensors that timestamp when they measure, such as a LiDAR. On Jetson, the zero-copy capture API exposes its DMA-buffer pool and can return the rectified pair directly as NV12 DMA-BUF buffers, with an experimental backend that keeps rectification entirely off the GPU.
On the platform side, TensorRT 11 is supported with its own installers, any installer now runs on the TensorRT version in its name or newer within the same major, and the Linux installers require fewer system packages. GEN_3 positional tracking is faster per frame and can be told how much GPU it may use. Numerous fixes round out the release, across white balance and video settings, IMU bias, GMSL capture stability, SVO recording, local streaming, spatial mapping and body-tracking fusion.
Sep 17, 2026
sl::InitParameters::depth_precision to select the precision of NEURAL depth inference. FP16 is the default and keeps the current behavior; INT8 trades a small amount of accuracy for a faster depth runtime and a lower memory footprint, and is supported by DEPTH_MODE::NEURAL only. It is up to 14% faster than FP16 on Orin NX (single camera) and 23% on Thor when using more than 2 cameras. Always safe to set: the SDK falls back to FP16, and says so in the log, when the depth mode or the GPU does not support INT8. Turing GPUs without tensor cores (T1000, T600, T400, T500, T1200, T2000 and the GTX 16 series) are in that case, and FP16 is faster on them anyway. Available in the C++, C, Python and C# APIs, and in ZED Depth Viewer..exr) support to sl::Mat::write() and sl::Mat::read() for float matrices (F32_C1, F32_C3, F32_C4), so a depth map, disparity map or point cloud can be saved and reloaded with its values unchanged, infinite and invalid pixels included, where PNG rescales them to 16-bit integers and PFM writes them as 0. The files are standard EXR and compatible with any OpenEXR-capable tool (with OpenCV, set OPENCV_IO_ENABLE_OPENEXR=1, and note that opencv-python 5 dropped the codec). Writing .exr is float-only: an 8- or 16-bit image returns ERROR_CODE::FAILURE. sl_save_current_depth() and its wrapper equivalents accept an .exr filename as well. Available in the C++, C, Python and C# APIs.sl::Mat::write() and sl::Mat::read() ignoring a file extension written in capitals. depth.PNG, cloud.PLY or image.JPG fell through to the default format for the matrix type, so a F32_C1 depth map named .PNG was written as PFM data and a F32_C3 point cloud as ASCII, under a filename claiming otherwise. The extension is now matched regardless of case.sl::InitParameters::allow_depth_cuda_graph, which lets the SDK record the depth computation once and replay it at each grab(), lowering CPU cost and depth runtime by 10%, most noticeably on Jetson. At 4 cameras on Thor, depth costs 20% less time and gives back 12 points of CPU. Off by default; enabling it gives the SDK a larger share of the GPU, leaving less headroom for other work on the same GPU, including your own code. Best-effort and DEPTH_MODE::NEURAL only, falling back to the regular computation if the recording fails, with the depth output unchanged. Available in the C++, C, Python and C# APIs.sl::MODEL::ZED_XONE_CORE), the ZED X One GS variant connected over MIPI through the ZED Link MIPI capture card. Detection, capture, resolutions and sensors behave like the ZED X One GS. Available in the C++, C, Python and C# APIs, the ROS 2 wrapper (camera_model: zedxonecore) and the ZED tools.sl::INPUT_TYPE::HOLOSCAN), alongside the existing MIPI connection. Requires a Holoscan sensor bridge and JetPack 7.2 (L4T 39.2) or newer.sl::INPUT_TYPE::MIPI and sl::BUS_TYPE::MIPI for cameras connected directly to a MIPI capture card.sl::TIME_REFERENCE::IMAGE_CENTER_OF_EXPOSURE to getTimestamp(), returning the middle of the frame's exposure instead of the start of the sensor readout given by sl::TIME_REFERENCE::IMAGE (unchanged, both can be used together). For applications aligning frames with sensors that timestamp when they measure, such as a LiDAR or robot joints. Supported on ZED X, ZED X Mini, ZED X One GS and ZED X One 4K, for live cameras, SVO files and streams; returns 0 on inputs that carry no per-frame exposure (USB and HDR models), so check the value before using it. On the rolling-shutter ZED X One 4K it refers to the frame's first row. Available in the C++, C, Python and C# APIs.HealthStatus::duplicated_image, raised when the content of a frame is identical to one already received even though its timestamp is new: a repeating or stalled stream, which until now was only mentioned in the verbose log. Reported like the other health checks, so it needs InitParameters::enable_image_validity_check enabled (default).sl::Camera::open() and sl::CameraOne::open() returning ERROR_CODE::CANNOT_START_CAMERA_STREAM instead of ERROR_CODE::CAMERA_NOT_DETECTED when no camera of the requested kind was connected.sl::Camera::open() terminating the calling application instead of returning an error when the camera could not be prepared for rectification, typically with an unusable calibration.sl::VIDEO_SETTINGS::WHITEBALANCE_TEMPERATURE responded backwards, a higher requested temperature made the image cooler instead of warmer, and crushed the blue channel to black at the warm end of the range, with a pronounced green cast on ZED X One 4K. Manual white balance now tracks the requested temperature across the full 2800–11000 K range. Automatic white balance was not affected.EXPOSURE_COMPENSATION set to 10 read back as 9). Affects EXPOSURE_COMPENSATION, DENOISING, SHARPNESS, ANALOG_GAIN, DIGITAL_GAIN, AUTO_ANALOG_GAIN_RANGE and SCENE_ILLUMINANCE on GMSL cameras (ZED X / ZED X One families), for live cameras as well as values read from SVO files and streams.InitParameters.input.setVirtualStereoFromCameraIDs() and setVirtualStereoFromSerialNumbers() returning false ("no error") when given invalid camera identifiers or an out-of-range virtual serial number. They now return true on every error path, as documented. Code that treated true as success should be updated.sl::Camera::open() could hang forever if the internal stream receiver was blocked waiting for packets.ZED_SDK_IMU_DISABLE=1 or unavailable: on a host with no local calibration file and no internet access, open() failed with CALIBRATION_FILE_NOT_AVAILABLE instead of falling back to it.getSVOPositionAtTimestamp() returning the wrong frame, on sl::Camera and sl::CameraOne: the last frame of an SVO was never returned, since asking for the newest frame's timestamp answered with the frame before it, and a timestamp falling between two frames could resolve to either side of it. It now returns the closest frame at or before the requested timestamp. Applications indexing an SVO by timestamp to align it with a LiDAR, a robot log or another camera were reading one frame off.getSVOPositionAtTimestamp(), on sl::Camera and sl::CameraOne: every call made with a timestamp outside the range covered by the SVO leaked an image buffer, several megabytes each time.setSVOPosition() occasionally leaving the reader on a different frame than the requested one, on Jetson and with SVO files recorded before the SVO2 format. The following grab() then returned a neighbouring frame, in some cases while the seek itself had reported success. Only happened while the machine was busy, which made it look intermittent.getSensorsData() rotating continuously on a perfectly static camera, with camera_moving_state stuck on MOVING, when an invalid gyroscope bias had previously been stored on the device. Such a stored value is now detected and ignored, the bias is re-estimated automatically, and the invalid value can no longer be written back to the camera. Affected cameras recover on their own; running ZED Calibration is no longer needed.grab(). retrieveMeasure(), retrieveVoxelMeasure(), setRegionOfInterest(), findFloorPlane(), findPlaneAtHit(), resetPositionalTracking(), disableSpatialMapping() and the recording and streaming enable/disable calls could run while grab() was still processing the current frame; they now wait for it to complete. Applications that keep every SDK call on the grab thread were not affected.--network=host containers). A real mismatch still warns, and now names both versions.sl::VIDEO_SETTINGS::AEC_AGC_ROI being refused when the region reached the right or bottom edge of the image, the usual case for metering a full-width band such as the horizon or the top third. setCameraSettings() returned an error and automatic exposure kept metering the previously set region, so the ROI looked ignored, while narrower regions always worked. Reported on the ZED X One 4K; it affected every ZED X and ZED X One model except the HDR ones, which do not implement the setting.getCameraSettings() reporting a failure and an empty rectangle when reading sl::VIDEO_SETTINGS::AEC_AGC_ROI back after a reset, on the same cameras. Resetting the ROI returns automatic exposure to metering the whole frame, so it now reads back as the full image with success, the same answer as on a camera where no ROI has been set yet.SL_ENABLE_ADVANCED_CAPTURE_API) on Jetson GMSL cameras, for publisher/subscriber pipelines that want no syscall left in the per-frame path. sl::Camera::getRawBufferPoolFds() (and the sl::CameraOne equivalent) returns the dmabuf descriptors backing the capture pool, so a publisher shares them with its subscribers once and then publishes only a {generation, fd} pair per frame through shared memory. Descriptors carry a generation counter and a syscall-free isValid() check that turns false before the pool is destroyed on camera close or capture recovery, so a stale descriptor is always detectable: re-query the pool and re-share it when that happens. Not available on the HDR camera family, which has no stable buffer pool. C++ only.sl::Camera::retrieveImage(RawBuffer&, bool rectified), which returns the rectified stereo pair as native NV12 DMA-BUF buffers, consumable without any CPU copy by GStreamer (NVMM caps), a V4L2 encoder or an external NPU. By default an on-demand GPU remap fills them, costing one extra pass for the retrieved frame only. Experimental: with ZED_SDK_EXPERIMENTAL_RECTIFICATION_BACKEND set to VIC or CPU, a GMSL camera and DEPTH_MODE::NONE or DEPTH_MODE::CUSTOM, the remap runs on the selected engine and the whole capture-to-rectified pipeline performs no GPU work at all, leaving the GPU fully available to the application. In that mode depth stabilization, RuntimeParameters::remove_saturated_areas, positional tracking, object detection and body tracking are unavailable, and the added blocking remap (~10 ms at 1920x1200 on Orin) caps the sustainable frame rate: validated at 30 FPS. C++ only.SVO_COMPRESSION_MODE::LOSSLESS: mono frames were handled as if they were a stereo side-by-side pair, so recordings came out unusable. Playback now also warns when a frame cannot be decoded instead of stopping silently, which made an unreadable or truncated file indistinguishable from the end of the recording.enableRecording() producing unusable SVO2 files on the HDR camera family (ZED X HDR, ZED X HDR Mini, ZED X HDR Max and ZED X One HDR): recording reported success but no image was ever written, leaving a file with no frame to play back. Recordings on these cameras now contain their images, in every compression mode.grab() with positional tracking enabled, most noticeably on Jetson.PositionalTrackingParameters::compute_preference to control how much GPU positional tracking may use. POSITIONAL_TRACKING_MODE::GEN_3 runs on the CPU by default but some operations have both implementations; set PREFER_GPU to make tracking faster and reduce the per-frame time of grab(), at the cost of using the GPU. POSITIONAL_TRACKING_MODE::GEN_1 computes depth and so uses the GPU regardless of the setting. Available in the C++, C, Python and C# APIs.POSITIONAL_TRACKING_MODE::GEN_3 on long sessions, caused by concurrent access to the internal map.BodyTrackingParameters::model_gen (sl::BODY_TRACKING_MODEL_GEN) to select which body tracking network runs. GEN_2 is a new bottom-up architecture, more robust in crowded scenes and to unusual body orientations, and it detects people further from the camera. It is the default on HUMAN_BODY_ACCURATE and HUMAN_BODY_MEDIUM (BODY_18 / BODY_34), where it is up to 18% faster and up to 14% more accurate than GEN_1. Set model_gen to GEN_1 for the previous network. Available across the C++, C, Python and C# APIs.HUMAN_BODY_MEDIUM gains accuracy at the cost of more inference time; use HUMAN_BODY_FAST or GEN_1 to keep the previous timing.BodyTrackingParameters::allow_reduced_precision_inference has no effect on GEN_2, which always runs in FP16.PERSON_HEAD_BOX_FAST and PERSON_HEAD_BOX_ACCURATE): people are detected much further from the camera and far more reliably in top-down or partially occluded views, with around five times fewer false detections on scenes with no one in them. PERSON_HEAD_BOX_ACCURATE gains roughly 50% recall at long range for the same inference time. The new models are downloaded automatically on first use, no API change.sl::optimizeCustomAIModel() to optimize a custom object detection ONNX model ahead of time, so enableObjectDetection() with OBJECT_DETECTION_MODEL::CUSTOM_YOLOLIKE_BOX_OBJECTS, CUSTOM_RFDETRLIKE_BOX_OBJECTS or CUSTOM_BOX_OBJECTS_AUTODETECT starts immediately instead of optimizing the model on first use. Intended to be called once when installing or deploying an application; the input resolution given to it must match the ObjectDetectionParameters::custom_onnx_dynamic_input_shape the application uses. Available in the C++, C, Python and C# APIs.sl::Mesh::applyTexture() producing an untextured mesh, and clearing the mesh geometry when texturing failed: the images used for texturing were only collected on part of the frames, so most scans had too few of them. The mesh is now left untouched, with a clear error, when no texture can be generated.sl::CommunicationParameters in LOCAL_NETWORK mode), typically hit when Jetson senders publish to a Windows receiver and additional cameras are subscribed: the process could abort (0xc0000409) instead of reporting an error. Received metadata is no longer reinterpreted across platforms, and a malformed body/object payload is now dropped with a warning instead of terminating the process. This also affected ZED 360.sl::Fusion::enableBodyTracking() failing with BODY_FORMAT_MISMATCH when called before the subscribed senders have delivered their first body data (e.g. right after subscribe(), as done in the samples): the module stayed permanently disabled and retrieveBodies() returned empty results with no visible cause. It now waits for the senders to report their format and starts automatically on the following process() calls; a real body-format mismatch between senders is still rejected, now with a warning log. Late-subscribed cameras no longer make retrieveBodies() fail with BODY_FORMAT_MISMATCH while their first data is in flight.tensorrt10.9 package on any 10.9+, a tensorrt11.0 package on any 11.x. On Linux a compatible TensorRT already installed is kept instead of overwritten (--force_bundled_tensorrt to override).zlib1g, libusb-1.0-0, udev and wget; the GUI tools additionally pull Qt and mesa-utils. The bundled copies are private to the SDK, so applications using their own libjpeg or libpng are unaffected.setcap cap_sys_nice=eip <your_app>).ZED_SDK_CAPTURE_THREAD_SCHED_POLICY and ZED_SDK_SENSORS_THREAD_SCHED_POLICY: fifo (default), rr, other or batch, set independently for each thread.ZED_SDK_CAPTURE_THREAD_PRIORITY (default 99) and ZED_SDK_SENSORS_THREAD_PRIORITY (default 50): 1 to 99, clamped to the range the selected policy accepts.ZED_SDK_CAPTURE_THREAD_AFFINITY: off to stop pinning capture threads to a CPU core, or a core list such as 2,3 to keep them on a subset.open() of each module takes as long as it did on a fresh install. Subsequent runs are unaffected, and the depth, detection and body tracking results are unchanged. Plan for it on deployed systems that expect a fast first start, and note that the machine needs internet access (or a pre-populated model directory) for that first run.sl::downloadAIModel() returning ERROR_CODE::FAILURE for sl::AI_MODELS::REID_ASSOCIATION even when the model had been downloaded correctly. Provisioning scripts that check the return value reported a failure that retrying could never clear, since the model was already there.sl_mat_write() ignoring the compression level, so a PNG or JPEG written from C always used the format default instead of the requested quality. The level is now a parameter of the function, so existing calls need the extra argument; pass -1 to keep the previous behavior. Writing .exr is lossless and ignores the level.SL_ObjectDetectionParameters::allow_reduced_precision_inference and SL_BodyTrackingParameters::allow_reduced_precision_inference having no effect: the value was accepted and dropped, so detection and body tracking always ran at full precision whatever was requested. It now reaches the module and is reported back by sl_get_object_detection_parameters() and sl_get_body_tracking_parameters(). Also affects the C# API, which uses the same structures.SL_InitParameters::enable_image_validity_check from bool to int, matching the C++ API. Only levels 0 and 1 could be expressed before, so the stricter image checks were unreachable from C and C#. Existing code passing true or false keeps working in C.DeviceProperties.gmslPort not being readable: the ZED SDK filled it but the field was not exposed, so a camera's serial number could not be mapped to its physical GMSL port from C#.Mat.Write() ignoring its compressionLevel argument, so a PNG or JPEG always used the format default instead of the requested quality.MODEL.ZED_X_HDR, MODEL.ZED_X_HDR_MINI and MODEL.ZED_X_HDR_MAX, which were missing from the enum. GetCameraModel() and DeviceProperties.cameraModel returned an unnamed value on the ZED X HDR family.ERROR_CODE.CANNOT_START_CAMERA_STREAM, the name the rest of the ZED SDK and its documentation use for that code. ERROR_CODE.CAMERA_ALREADY_IN_USE is kept as a deprecated alias with the same value, so existing code still compiles.InitParameters.enableImageValidityCheck from bool to int, matching the C++ API, which makes the stricter image checks reachable. Code assigning true or false must assign 1 or 0 instead.Camera.get_device_list() and CameraOne.get_device_list() leaving most DeviceProperties fields at their default values: gmsl_port was always -1 and i2c_port always 0, so a camera's serial number could not be mapped to its physical GMSL port from Python. All fields now carry the same values as in the C++ API.-onnx <path> [WxH] command-line option to optimize a custom object-detection ONNX model ahead of time, so enableObjectDetection() with OBJECT_DETECTION_MODEL::CUSTOM_YOLOLIKE_BOX_OBJECTS, CUSTOM_RFDETRLIKE_BOX_OBJECTS or CUSTOM_BOX_OBJECTS_AUTODETECT starts instantly instead of optimizing the model on first use. The optional input size (default 512x512) must match the ObjectDetectionParameters::custom_onnx_dynamic_input_shape used by the application.For older releases and changelog, see the ZED SDK release archive.