Skip to content

Run the solar panel line-of-sight ray cast on the render thread (fixes #44) - #50

Open
asimonov wants to merge 3 commits into
space-ros:mainfrom
asimonov:solar_panel_render_thread
Open

Run the solar panel line-of-sight ray cast on the render thread (fixes #44)#50
asimonov wants to merge 3 commits into
space-ros:mainfrom
asimonov:solar_panel_render_thread

Conversation

@asimonov

@asimonov asimonov commented Sep 4, 2026

Copy link
Copy Markdown
Member

Fixes #44. Stacked on #48 (the first two commits are that PR's; only the last one, "Run the solar panel line-of-sight ray cast on the render thread", is this one) — merge after it.

SolarPanelPlugin created and cast a rendering RayQuery from PostUpdate. Gazebo Harmonic executes ISystemPostUpdate systems on parallel worker threads, so the rover's three panel instances hit the Ogre scene concurrently with each other and with the Sensors system's render thread, corrupting the heap within seconds of spawning (malloc_consolidate(): invalid chunk sizestd::bad_alloc, or SIGSEGV / SIGBUS on other runs). Bisecting by disabling one plugin at a time: only disabling this plugin keeps the server alive.

All rendering access now happens in a gz::sim::events::PostRender callback on the render thread; PostUpdate hands the sun-to-panel ray over under a mutex and takes back the latest line-of-sight result. The power computation is unchanged, and the ray query is created once instead of on every simulation step. The same structure runs on Fortress.

Verification

  • Harmonic, Jazzy demo (lunar_pole_exploration_rover: Migrate to ROS 2 Jazzy and Gazebo Harmonic (#164) demos#165) headless: with this change the server runs for the whole test session (drive, rotate, camera sweeps, sensor switching) with no crash output; without it, it dies within seconds of the rover spawning. Solar output 106.786 W at rest, identical to the Fortress reading, rising to ~129 W as the rover turns.
  • Fortress, Humble demo image built from demos main against this branch: server alive, plugins loaded from the image build, solar ~106.7 W, battery 30 V / 100 %.

…).

SolarPanelPlugin, RechargeableBatteryPlugin, SensorPowerSystemPlugin and
RadioisotopeThermalGeneratorPlugin were written against the Ignition Fortress
API and, since space-ros#41, only built on Humble. They now target the Gazebo Harmonic
(gz-sim 8) API: gz::sim, gz::rendering and gz::sensors namespaces, gz/ header
paths, the GZ_ADD_PLUGIN registration macros and the gz* console macros. Each
message type gets its own include, as gz-msgs 10 no longer provides them
transitively.

Fortress ships gz/ redirect headers for all of these namespaces but not for
the GZ_ / gz prefixed macros, so plugins/gz_compat.hh maps those onto their
Ignition names when they are missing. One set of sources therefore builds on
both distributions; CMakeLists.txt and package.xml select the Ignition system
packages on Humble and the ROS gz_*_vendor packages otherwise, and the
environment hook sets both IGN_GAZEBO_* and GZ_SIM_* paths.
…ros#47).

The ros2_control hardware plugin and the Gazebo system plugins have different
names on the two: ign_ros2_control/IgnitionSystem and ignition-gazebo-*-system
on Fortress, gz_ros2_control/GazeboSimSystem and gz-sim-*-system on Harmonic.
xacro properties keyed on ROS_DISTRO select the right set, so the same model
serves the Humble demo and the Jazzy one.

The gz_ros2_control plugin also referenced its controller configuration via
$(find lunar_pole_exploration_rover), coupling the model to a package in the
demos repository. The configuration now lives with the model, as the curiosity
rover's does.
…e-ros#44).

Gazebo runs ISystemPostUpdate systems on parallel worker threads.
SolarPanelPlugin created a rendering RayQuery and cast it from PostUpdate, so
the three panel instances on the rover hit the Ogre scene concurrently with
each other and with the Sensors system's render thread. Under Harmonic that
corrupts the heap within seconds of the rover spawning (malloc_consolidate,
std::bad_alloc, SIGSEGV or SIGBUS depending on the run). Disabling this one
plugin makes the crash go away; disabling either of the other two does not.

Move all rendering access into a gz::sim::events::PostRender callback, which
runs on the render thread. PostUpdate now only reads the entity state it needs
from the ECM, hands the sun-to-panel ray to the render thread under a mutex,
takes back the latest line-of-sight result and publishes the power output. The
power computation itself is unchanged. The unused static scene event and
SetScene hook are removed, and the ray query is created once instead of on
every simulation step.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

SolarPanelPlugin corrupts the heap on Gazebo Harmonic: rendering from PostUpdate

1 participant