Skip to content

Conversation

@neverorfrog
Copy link
Contributor

@neverorfrog neverorfrog commented Dec 2, 2025

This pull request introduces improvements to the simulation's multi-threaded rendering and sensor update infrastructure. The main changes are the addition of a thread pool for concurrent robot updates, a robust EGL-based offscreen rendering system for camera sensors, and improved thread safety and performance in sensor data handling.

Rendering and EGL Integration:

  • Added EGL offscreen rendering support for camera sensors, including shared display management (SharedEGLDisplay) and per-camera contexts (CameraContext). Cameras now lazily initialize their EGL context on worker threads and use MuJoCo's snapshot data for rendering (Mujoco best practice) [1] [2] [3] [4] [5]

Threading and Concurrency:

  • Introduced a generic ThreadPool utility for parallelizing robot updates in RobotManager, enabling each robot's update to run concurrently and improving simulation performance. The pool size is set to the number of hardware threads. [1] [2] [3] [4]
  • Refactored SimulationThread to operate on the entire MujocoContext object, facilitating thread-safe access to simulation and snapshot data. [1] [2]

Sensor Architecture and Data Handling:

  • Enhanced the base Sensor class to support frequency-limited updates using time intervals, preventing unnecessary computation and improving determinism. [1] [2]
  • Camera sensors now use thread-safe image buffers and vertical image flipping for correct rendering alignment. They also read from snapshot data to avoid race conditions.

MuJoCo Context Management:

  • MujocoContext now maintains a separate snapshot of simulation data for safe concurrent reading by sensors, and provides thread-safe methods for updating and accessing this snapshot. [1] [2]

@FlavioFoxes
Copy link
Member

GG. Ho lasciato solo un commento su una cosa perché non l'ho capita, però il resto mi pare ok

Copy link
Member

@DaniAffCH DaniAffCH left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ci sono cose che non mi sono chiarissime, soprattutto rispetto alla concorrenza. Per il resto va bene imo

Comment on lines 52 to 58
void updateSnapshot();

// Get thread-safe read access to snapshot
mjData* getSnapshot() const {
return dataSnapshot;
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non capisco perchè la gestione degli snapshot è thread safe.

Mi sembra che tu fai lock sul write ma mai sul read. Quindi se qualcuno potrebbe cambiare il dato durante una read. No?

Inoltre l'unico che chiama updateSnapshot è SimulationThread::run(). Quindi in quali casi si ha una scrittura concorrente?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

stavo facendo best effort, ma effettivamente era sbagliato. ho messo il lock anche in lettura

Comment on lines +57 to +68
std::vector<std::future<void>> futures;

{
std::lock_guard lock(mutex_);
for (std::shared_ptr<Robot> r : robots_) {
futures.push_back(threadPool_.enqueue([r]() { r->update(); }));
}
}

// Wait for all robot updates to complete
for (auto& future : futures) {
future.wait();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perchè fare gli update in parallelo e joinare subito dopo è necessario?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perché altrimenti un robot potrebbe sovrascrivere lo snapshot acceduto da un altro

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.

4 participants