I am getting the error sl::FUSION_ERROR_CODE::MODULE_NOT_ENABLED when enabling the spatial mapping on the fusion module. I previously thought it was because the positional tracking module was not enabled, but now I have managed to enable that I still cannot enable spatial mapping.
Here is the code running remotely on the jetson (this seems to be working correctly)
// Standard includes
#include <iostream>
#include <string>
#include <thread>
#include <vector>
// ZED includes
#include <sl/Camera.hpp>
// Sample includes
#include "utils.hpp"
template <typename CameraType>
void acquisition(CameraType& zed) {
auto infos = zed.getCameraInformation();
while (!exit_app) {
//auto state = zed.read();
auto state = zed.grab();
if (state != sl::ERROR_CODE::SUCCESS) {
std::cout << "error in reading: " << state << std::endl;
}
auto sm_state = zed.getSpatialMappingState();
if (sm_state != sl::SPATIAL_MAPPING_STATE::OK){
std::cout << "error in spatial mapping: " << sm_state << std::endl;
}
}
std::cout << infos.camera_model << "[" << infos.serial_number << "] QUIT \n";
// disable Streaming
zed.stopPublishing();
// close the Camera
zed.close();
}
template <typename CameraType, typename IP>
bool openCamera(CameraType& zed, const int sn, const int port, const int camera_fps = 60) {
IP init_parameters;
init_parameters.camera_resolution = sl::RESOLUTION::AUTO;
init_parameters.depth_mode = sl::DEPTH_MODE::NEURAL;
init_parameters.input.setFromSerialNumber(sn);
init_parameters.camera_fps = camera_fps;
init_parameters.coordinate_system = sl::COORDINATE_SYSTEM::LEFT_HANDED_Y_UP;
init_parameters.open_timeout_sec = 10;
init_parameters.depth_stabilization = 0;
// Open the camera
const sl::ERROR_CODE open_err = zed.open(init_parameters);
if (open_err <= sl::ERROR_CODE::SUCCESS) {
std::cout << toString(zed.getCameraInformation().camera_model) << "_SN" << sn << " Opened" << std::endl;
} else {
std::cout << "ZED SN:" << sn << " Error: " << open_err << std::endl;
zed.close();
return false;
}
zed.setCameraSettings(sl::VIDEO_SETTINGS::WHITEBALANCE_TEMPERATURE, 3700);
sl::PositionalTrackingParameters positional_tracking_parameters;
positional_tracking_parameters.mode = sl::POSITIONAL_TRACKING_MODE::GEN_3;
if (zed.enablePositionalTracking(positional_tracking_parameters) != sl::ERROR_CODE::SUCCESS)
{
std::cout << "Failed to enable positional tracking" << std::endl;
}
sl::SpatialMappingParameters spatial_mapping_parameters;
spatial_mapping_parameters.map_type = sl::SpatialMappingParameters::SPATIAL_MAP_TYPE::FUSED_POINT_CLOUD;
if (zed.enableSpatialMapping(spatial_mapping_parameters) != sl::ERROR_CODE::SUCCESS)
{
std::cout << "Failed to enable spatial mapping" << std::endl;
}
// Enable streaming
sl::CommunicationParameters commParams;
commParams.setForLocalNetwork(port);
const sl::ERROR_CODE stream_err = zed.startPublishing(commParams);
if (stream_err <= sl::ERROR_CODE::SUCCESS) {
std::cout << toString(zed.getCameraInformation().camera_model) << "_SN" << sn << " Enabled streaming" << std::endl;
} else {
std::cout << "ZED SN:" << sn << " Streaming initialization error: " << stream_err << std::endl;
zed.close();
return false;
}
std::cout << "Streaming on port " << port << std::endl;
return true;
}
/// Function to print device information
void printDeviceInfo(const std::vector<sl::DeviceProperties>& devs) {
for (const auto& dev : devs)
std::cout << "ID : " << dev.id << ", model : " << dev.camera_model << " , S/N : " << dev.serial_number
<< " , state : " << dev.camera_state << std::endl;
}
int main(int argc, char** argv) {
// Get the list of available ZED cameras
const std::vector<sl::DeviceProperties> dev_stereo_list = sl::Camera::getDeviceList();
printDeviceInfo(dev_stereo_list);
const int nb_stereo = dev_stereo_list.size();
if (nb_stereo == 0) {
std::cout << "No ZED Detected, exit program" << std::endl;
return EXIT_FAILURE;
}
bool zed_open = false;
// Open the Stereo cameras
std::vector<sl::Camera> zeds_stereo(nb_stereo);
for (int z = 0; z < nb_stereo; ++z) {
const int port = 30000 + (10 * z); // Example port assignment
zed_open |= openCamera<sl::Camera, sl::InitParameters>(zeds_stereo[z], dev_stereo_list[z].serial_number, port);
}
if (!zed_open) {
std::cout << "No ZED opened, exit program" << std::endl;
return EXIT_FAILURE;
}
// Create a grab thread for each opened camera
std::vector<std::thread> thread_pool(nb_stereo); // compute threads
for (int z = 0; z < nb_stereo; z++) {
if (zeds_stereo[z].isOpened())
thread_pool[z] = std::thread(acquisition<sl::Camera>, std::ref(zeds_stereo[z]));
}
// Ctrl+C to close
SetCtrlHandler();
std::cout << "Press Ctrl+C to exit" << std::endl;
while (!exit_app) { // main loop
sl::sleep_ms(20);
}
// stop all running threads
std::cout << "Exit signal, closing ZEDs" << std::endl;
sl::sleep_ms(100);
// Wait for every thread to be stopped
for (auto& th : thread_pool)
if (th.joinable())
th.join();
std::cout << "Program exited" << std::endl;
return EXIT_SUCCESS;
}
And here is a snippet of the code I am running on a windows machine which connects to the jetson:
void FusionThreadLoop() {
sl::Timestamp last_update = 0;
bool wait_for_map = false;
while (running) {
if (fused_mgr.fusion.process() == sl::FUSION_ERROR_CODE::SUCCESS) {
auto ts = sl::getCurrentTimeStamp();
if (!wait_for_map && (ts.getMilliseconds() - last_update.getMilliseconds() > 100)) {
fused_mgr.fusion.requestSpatialMapAsync();
wait_for_map = true;
}
if (wait_for_map && fused_mgr.fusion.getSpatialMapRequestStatusAsync() == sl::FUSION_ERROR_CODE::SUCCESS) {
{
std::lock_guard<std::mutex> lock(fused_mgr.data_mutex);
fused_mgr.fusion.retrieveSpatialMapAsync(fused_mgr.fused_map);
fused_mgr.point_count = static_cast<int>(fused_mgr.fused_map.vertices.size());
fused_mgr.is_new_data = true;
}
wait_for_map = false;
last_update = ts;
}
}
else {
PluginLog("fusion.process() failed");
}
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
}
DLLEXPORT bool InitFusedPointCloud(const char* config_path) {
if (running) return true;
// Read setup config
auto configurations = sl::readFusionConfigurationFile(config_path,
sl::COORDINATE_SYSTEM::LEFT_HANDED_Y_UP, sl::UNIT::METER);
if (configurations.empty()) return false;
for (auto& config : configurations) {
PluginLog("Trying to connect to: "
+ std::to_string(config.serial_number)
+ " On port: "
+ std::to_string(config.communication_parameters.getPort()));
}
running = true;
sl::InitFusionParameters init_fusion_params;
init_fusion_params.coordinate_units = sl::UNIT::METER;
init_fusion_params.coordinate_system = sl::COORDINATE_SYSTEM::LEFT_HANDED_Y_UP;
init_fusion_params.verbose = true;
if (fused_mgr.fusion.init(init_fusion_params) != sl::FUSION_ERROR_CODE::SUCCESS) {
PluginLog("Failed to init fusion");
return false;
}
for (auto& config : configurations) {
// Subscribe the active camera to Fusion
PluginLog("Fusion trying to subscribe to camera: " + std::to_string(config.serial_number));
auto state = fused_mgr.fusion.subscribe(config.serial_number, config.communication_parameters,
config.pose, config.override_gravity);
if (state != FUSION_ERROR_CODE::SUCCESS) {
PluginLog("Failed to subscribe to camera: "
+ std::to_string(config.serial_number)
+ " Error: "
+ std::string(toString(state)));
}
}
sl::PositionalTrackingFusionParameters positional_tracking_param;
if (fused_mgr.fusion.enablePositionalTracking(positional_tracking_param) != sl::FUSION_ERROR_CODE::SUCCESS) {
PluginLog("Failed to enable positional tracking");
return false;
}
// Enable Spatial Mapping for Fused Point Cloud
sl::SpatialMappingFusionParameters spatial_params;
spatial_params.map_type = sl::SpatialMappingParameters::SPATIAL_MAP_TYPE::FUSED_POINT_CLOUD;
spatial_params.use_chunk_only = false;
auto state = fused_mgr.fusion.enableSpatialMapping(spatial_params); // <<< ERROR HERE
if (state != sl::FUSION_ERROR_CODE::SUCCESS) {
PluginLog("Failed to enable spatial mapping: " + std::string(state));
return false;
}
fusion_worker_thread = std::thread(FusionThreadLoop);
return true;
}
I can connect to the stream correctly, I get a success when subscribing to the fusion streams, but I get an error when enabling spatial mapping on the fusion module.
Thank you for sharing the code. I compared it with the official multi-camera spatial mapping sample, and I found some differences that you should fix first.
Jetson sender
Do not enable Spatial Mapping on the camera. The publisher only needs enablePositionalTracking, because the mapping is performed by the Fusion module. Remove zed.enableSpatialMapping(...) and the getSpatialMappingState() check in the acquisition loop; this also frees GPU resources on the Jetson.
Use the same units on the sender and on Fusion. The sender uses the default unit (MILLIMETER), while Fusion uses METER. Add init_parameters.coordinate_units = sl::UNIT::METER; in openCamera.
Stop if positional tracking fails. Currently the sender logs the error and continues publishing; the sample closes the camera and returns false instead, so the failure does not silently propagate to Fusion.
Windows Fusion host
Check the subscriptions. Keep a list of the cameras successfully subscribed, and exit if it is empty, as the sample does. Currently the application continues even if every subscribe call fails.
Print the error correctly.std::string(state) does not convert the enum to text; use sl::toString(state).
Use the same SDK version on both hosts. The Windows machine must run the same ZED SDK version as the Jetson (v5.5).
Isolating the problem
The sample runs the publisher and Fusion in the same process. Please run it on the Jetson with the camera set as INTRA_PROCESS in the Fusion configuration file: if it works locally, we can focus on the network workflow.
If the problem persists after these changes, please share the complete console output of both the Fusion application (you already have verbose = true) and the Jetson sender.
After implementing the changes you suggested to both the jetson sender and the host I get the same error message when trying to enable fusion: `sl::FUSION_ERROR_CODE::NOT_ENABLED`. The SDK versions are both 5.5.
I have tried to run the sample on the jetson with the communication type set to INTRA_PROCESS and I don’t get an error, but the fusion doesn’t work either. The visualisation window pops up but remains completely blank and there is no output from the application in terminal other than the opening of the cameras and there is no mesh saved. Here is the log:
```
: /usr/local/zed/samples/spatial mapping/multi camera/cpp/build$ ./ZED_SpatialMappingFusion Calibration_12-10-26-11-55.json
Try to open ZED 40293886..[2026-10-21 08:10:15 UTC][ZED][INFO] Logging level INFO
[2026-10-21 08:10:16 UTC][ZED][INFO] Using GMSL input… Switched to default resolution HD1200
[2026-10-21 08:10:20 UTC][ZED][INFO] [Init] Camera FW version: 2001
[2026-10-21 08:10:20 UTC][ZED][INFO] [Init] Video mode: HD1200@30
[2026-10-21 08:10:20 UTC][ZED][INFO] [Init] Serial Number: S/N 40293886
[2026-10-21 08:10:20 UTC][ZED][INFO] [Init] Depth mode selected: NEURAL. Ensure this mode matches your application’s performance and accuracy requirements. See Depth Modes | StereoLabs for help.
. ready !
Try to open ZED 41142247..[2026-10-21 08:10:21 UTC][ZED][INFO] Logging level INFO
[2026-10-21 08:10:22 UTC][ZED][INFO] Using GMSL input… Switched to default resolution HD1200
[2026-10-21 08:10:24 UTC][ZED][INFO] [Init] Camera FW version: 2001
[2026-10-21 08:10:24 UTC][ZED][INFO] [Init] Video mode: HD1200@30
[2026-10-21 08:10:24 UTC][ZED][INFO] [Init] Serial Number: S/N 41142247
[2026-10-21 08:10:24 UTC][ZED][INFO] [Init] Depth mode selected: NEURAL. Ensure this mode matches your application’s performance and accuracy requirements. See Depth Modes | StereoLabs for help.
. ready !
[2026-10-21 08:10:26 UTC][ZED][INFO] Fusion Logging level INFO
[2026-10-21 08:10:27 UTC][ZED][WARNING] Gravity alignment issues detected. Recomputing alignment…
[2026-10-21 08:10:27 UTC][ZED][WARNING] Gravity alignment issues detected. Recomputing alignment…
```
Also, I noticed in the documentation under Fusion.enableSpatialMapping() there is this warning
Warning
This fuction is only available for INTRA_PROCESS communication type.
This implies that fusion spatial mapping does not work on network pipelines.
This contradicts what the documentation pages for fusion and spatial mapping, which you linked, imply.
Is multi-cam spatial mapping via the fusion module supported via networked cameras?