Skip to content

Recreating DepthCamera sensor in the same scene causes crash #548

@amaldevh

Description

@amaldevh

Environment

  • OS Version: Ubuntu 22.04
  • Source or binary build?
    Binary, gz-sim9

Description

  • Expected behavior: We should be able to remove and create sensors without causing crash
  • Actual behavior: When removing a DepthCamera sensor using SensorManager and recreating it from the same SDF, the program crashes with the following error:
    ./OgreMain/src/OgreHlmsDatablock.cpp:199: virtual Ogre::HlmsDatablock::~HlmsDatablock(): Assertion `mLinkedRenderables.empty() && "This Datablock is still being used by some Renderables." " Change their Datablocks before destroying this."' failed.
    Note that this issue doesn't occur wth other sensor types (RGB for example).

Steps to reproduce

  1. Minimal reproduction code
#include <iostream>
#include <thread>
#include <chrono>

#include <sdf/Sensor.hh>
#include <gz/common/Console.hh>
#include <gz/rendering/RenderingIface.hh>
#include <gz/rendering/RenderEngine.hh>
#include <gz/rendering/Scene.hh>
#include <gz/sensors/Manager.hh>
#include <gz/sensors/DepthCameraSensor.hh>

static sdf::Sensor MakeDepthCamSdf()
{
    sdf::Sensor s;
    s.SetName("repro_depth");
    s.SetType(sdf::SensorType::DEPTH_CAMERA);

    sdf::Camera *cam = new sdf::Camera();
    cam->SetImageWidth(320);
    cam->SetImageHeight(240);
    cam->SetFarClip(10.0);
    cam->SetNearClip(0.1);
    cam->SetHorizontalFov(gz::math::Angle::HalfPi);
    s.SetCameraSensor(*cam);

    // Minimal update rate so we create renderables quickly
    s.SetUpdateRate(30.0);

    return s;
}

static sdf::Sensor MakeRGBCamSdf()
{
    sdf::Sensor s;
    s.SetName("repro_rgb");
    s.SetType(sdf::SensorType::CAMERA);

    sdf::Camera *cam = new sdf::Camera();
    cam->SetImageWidth(320);
    cam->SetImageHeight(240);
    cam->SetFarClip(10.0);
    cam->SetNearClip(0.1);
    cam->SetHorizontalFov(gz::math::Angle::HalfPi);
    s.SetCameraSensor(*cam);

    // Minimal update rate so we create renderables quickly
    s.SetUpdateRate(30.0);

    return s;
}

struct SceneManager{
    SceneManager(std::string engineName="ogre2"):engineName(engineName){
        engine = gz::rendering::engine(engineName);
        if (!engine){
            throw std::runtime_error("couldnt create engine with name "+engineName);
        }
        scene = engine->CreateScene("repro_scene");
        if (!scene){
            throw std::runtime_error("couldnt create scene");
        }
        scene->SetBackgroundColor(gz::math::Color(0.1f, 0.1f, 0.1f));
    };
    ~SceneManager(){
        engine->DestroyScene(scene);
        gz::rendering::unloadEngine(engineName);
    };
    gz::rendering::RenderEngine* engine;
    const std::string engineName = "ogre2";
    gz::rendering::ScenePtr scene;
};

int main()
{
    gz::common::Console::SetVerbosity(4);
    SceneManager scene_mgr;
    gz::sensors::Manager mgr;
    auto sdf_ = MakeRGBCamSdf();
    // first rgb camera test
    // each iteration will create and then destory sensor
    for (int k =0; k<3; ++k){    
        auto *base = mgr.CreateSensor<gz::sensors::CameraSensor>(sdf_);
        auto *rgb = dynamic_cast<gz::sensors::CameraSensor*>(base);
        rgb->SetScene(scene_mgr.scene);
        rgb->SetParent("repro_link");
        auto conn = rgb->ConnectImageCallback(
            [](const gz::msgs::Image &)
            {
            // no-op
            });
        for (int i = 0; i < 100; ++i){
                mgr.RunOnce(std::chrono::steady_clock::duration(std::chrono::milliseconds(16)));
                std::this_thread::sleep_for(std::chrono::milliseconds(1));
        }
    {
    auto renderCam = rgb->RenderingCamera();
    if (renderCam)
    {
        std::cout << "[Repro] Destroying RGBCamera render object directly...\n";
        renderCam->Destroy();
    }

    std::cout << "[Repro] Removing sensor from Manager...\n";
    mgr.Remove(rgb->Id());
        }
    }
    // next depth camera test
    sdf_ = MakeDepthCamSdf();
    for (int k =0; k<3; ++k){    
        auto *base = mgr.CreateSensor<gz::sensors::DepthCameraSensor>(sdf_);
        auto *depth = dynamic_cast<gz::sensors::DepthCameraSensor*>(base);
        depth->SetScene(scene_mgr.scene);
        depth->SetParent("repro_link");
        auto conn = depth->ConnectImageCallback(
            [](const gz::msgs::Image &)
            {
            // no-op
            });
        for (int i = 0; i < 100; ++i){
                mgr.RunOnce(std::chrono::steady_clock::duration(std::chrono::milliseconds(16)));
                std::this_thread::sleep_for(std::chrono::milliseconds(1));
        }
    {
    auto renderCam = depth->DepthCamera();
    if (renderCam)
    {
        std::cout << "[Repro] Destroying DepthCamera render object directly...\n";
        renderCam->Destroy();
    }

    std::cout << "[Repro] Removing sensor from Manager...\n";
    mgr.Remove(depth->Id());
        }
    }

    std::cout << "Done.\n";
    return 0;
}
cmake_minimum_required(VERSION 3.22.1 FATAL_ERROR)
project(repro_test)
add_executable(debug_main minimal_repro.cc)
find_package(gz-rendering9-ogre2)
find_package(gz-rendering9 REQUIRED)
find_package(gz-common6 REQUIRED)
find_package(gz-sensors9 REQUIRED COMPONENTS camera depth_camera )

set(GZ_SIM_VER 9)
set(GZ_SENSOR_VER 9)
set(GZ_COMMON_VER 6)
set(GZ_RENDERING_VER 9)
target_link_libraries(debug_main 
 gz-common${GZ_COMMON_VER}::gz-common${GZ_COMMON_VER}
 gz-rendering${GZ_RENDERING_VER}::gz-rendering${GZ_RENDERING_VER}
 gz-sensors${GZ_SENSOR_VER}::camera
 gz-sensors${GZ_SENSOR_VER}::depth_camera
)

Output

./debug_main 
(2025-08-20 22:13:25.877) [info] [RenderEngineManager.cc:514] Loading plugin [gz-rendering-ogre2]
libEGL warning: egl: failed to create dri2 screen
libEGL warning: egl: failed to create dri2 screen
(2025-08-20 22:13:26.695) [debug] [CameraSensor.cc:343] Camera images for [repro_rgb] advertised on [/camera]
(2025-08-20 22:13:26.696) [debug] [CameraSensor.cc:633] Camera info for [repro_rgb] advertised on [/camera_info]
(2025-08-20 22:13:26.698) [warning] [Ogre2Camera.cc:423] Ogre2Camera::SetVisibilityMask: Mask bits c0000000 are set but will be ignored as they conflict with the reserved bits used internally by the ogre2 backend.
(2025-08-20 22:13:26.698) [debug] [CameraSensor.cc:442] Enabling camera sensor: 'repro_rgb' data generation.
[Repro] Destroying RGBCamera render object directly...
[Repro] Removing sensor from Manager...
(2025-08-20 22:13:26.827) [debug] [CameraSensor.cc:343] Camera images for [repro_rgb] advertised on [/camera]
(2025-08-20 22:13:26.827) [debug] [CameraSensor.cc:633] Camera info for [repro_rgb] advertised on [/camera_info]
(2025-08-20 22:13:26.827) [warning] [Ogre2Camera.cc:423] Ogre2Camera::SetVisibilityMask: Mask bits c0000000 are set but will be ignored as they conflict with the reserved bits used internally by the ogre2 backend.
(2025-08-20 22:13:26.827) [debug] [CameraSensor.cc:442] Enabling camera sensor: 'repro_rgb' data generation.
[Repro] Destroying RGBCamera render object directly...
[Repro] Removing sensor from Manager...
(2025-08-20 22:13:26.940) [debug] [CameraSensor.cc:343] Camera images for [repro_rgb] advertised on [/camera]
(2025-08-20 22:13:26.940) [debug] [CameraSensor.cc:633] Camera info for [repro_rgb] advertised on [/camera_info]
(2025-08-20 22:13:26.940) [warning] [Ogre2Camera.cc:423] Ogre2Camera::SetVisibilityMask: Mask bits c0000000 are set but will be ignored as they conflict with the reserved bits used internally by the ogre2 backend.
(2025-08-20 22:13:26.940) [debug] [CameraSensor.cc:442] Enabling camera sensor: 'repro_rgb' data generation.
[Repro] Destroying RGBCamera render object directly...
[Repro] Removing sensor from Manager...
(2025-08-20 22:13:27.056) [debug] [DepthCameraSensor.cc:284] Depth images for [repro_depth] advertised on [/camera/depth]
(2025-08-20 22:13:27.056) [debug] [CameraSensor.cc:633] Camera info for [repro_depth] advertised on [/camera/camera_info]
(2025-08-20 22:13:27.057) [debug] [DepthCameraSensor.cc:312] Points for [repro_depth] advertised on [/camera/depth/points]
[Repro] Destroying DepthCamera render object directly...
[Repro] Removing sensor from Manager...
(2025-08-20 22:13:27.177) [debug] [DepthCameraSensor.cc:284] Depth images for [repro_depth] advertised on [/camera/depth]
(2025-08-20 22:13:27.177) [debug] [CameraSensor.cc:633] Camera info for [repro_depth] advertised on [/camera/camera_info]
(2025-08-20 22:13:27.177) [debug] [DepthCameraSensor.cc:312] Points for [repro_depth] advertised on [/camera/depth/points]
debug_main: ./OgreMain/src/OgreHlmsDatablock.cpp:199: virtual Ogre::HlmsDatablock::~HlmsDatablock(): Assertion `mLinkedRenderables.empty() && "This Datablock is still being used by some Renderables." " Change their Datablocks before destroying this."' failed.
Aborted (core dumped)

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    Status

    Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions