Skip to content

Commit

Permalink
Allow rendering to be forced externally (#1475)
Browse files Browse the repository at this point in the history
Signed-off-by: Michel Hidalgo <[email protected]>
  • Loading branch information
hidmic authored Jun 15, 2022
1 parent 0184de3 commit 1c90252
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 8 deletions.
33 changes: 29 additions & 4 deletions include/gz/sim/rendering/Events.hh
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@ namespace gz
using SceneUpdate = gz::common::EventT<void(void),
struct SceneUpdateTag>;

/// \brief The render event is emitted before rendering updates.
/// \brief The pre render event is emitted before rendering updates.
/// The event is emitted in the rendering thread so rendering
/// calls can ben make in this event callback
/// calls can be made in this event callback
///
/// For example:
/// \code
Expand All @@ -55,16 +55,41 @@ namespace gz
using PreRender = gz::common::EventT<void(void),
struct PreRenderTag>;

/// \brief The render event is emitted after rendering updates.
/// \brief The render event is emitted during rendering updates.
/// The event is emitted in the rendering thread so rendering
/// calls can ben make in this event callback
/// calls can be made in this event callback
///
/// For example:
/// \code
/// eventManager.Emit<gz::sim::events::Render>();
/// \endcode
using Render = gz::common::EventT<void(void),
struct RenderTag>;

/// \brief The post render event is emitted after rendering updates.
/// The event is emitted in the rendering thread so rendering
/// calls can be made in this event callback
///
/// For example:
/// \code
/// eventManager.Emit<gz::sim::events::PostRender>();
/// \endcode
using PostRender = gz::common::EventT<void(void),
struct PostRenderTag>;

/// \brief The force render event may be emitted outside the
/// rendering thread to force rendering calls ie. to ensure
/// rendering occurs even if it wasn't seemingly necessary.
///
/// Useful for custom, out-of-tree rendering sensors that
/// need the rendering thread to perform an update.
///
/// For example:
/// \code
/// eventManager.Emit<gz::sim::events::ForceRender>();
/// \endcode
using ForceRender = gz::common::EventT<void(void),
struct ForceRenderTag>;
}
} // namespace events
} // namespace sim
Expand Down
28 changes: 25 additions & 3 deletions src/systems/sensors/Sensors.cc
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,9 @@ class gz::sim::systems::SensorsPrivate
/// \brief Flag to signal if rendering update is needed
public: bool updateAvailable { false };

/// \brief Flag to signal if a rendering update must be done
public: std::atomic<bool> forceUpdate { false };

/// \brief Thread that rendering will occur in
public: std::thread renderThread;

Expand All @@ -129,6 +132,9 @@ class gz::sim::systems::SensorsPrivate
/// \brief Connection to events::Stop event, used to stop thread
public: gz::common::ConnectionPtr stopConn;

/// \brief Connection to events::ForceRender event, used to force rendering
public: gz::common::ConnectionPtr forceRenderConn;

/// \brief Update time for the next rendering iteration
public: std::chrono::steady_clock::duration updateTime;

Expand Down Expand Up @@ -185,6 +191,9 @@ class gz::sim::systems::SensorsPrivate
/// \brief Stop the rendering thread
public: void Stop();

/// \brief Force rendering thread to render
public: void ForceRender();

/// \brief Update battery state of sensors in model
/// \param[in] _ecm Entity component manager
public: void UpdateBatteryState(const EntityComponentManager &_ecm);
Expand Down Expand Up @@ -275,7 +284,7 @@ void SensorsPrivate::RunOnce()
this->renderUtil.Update();
}

if (!this->activeSensors.empty())
if (!this->activeSensors.empty() || this->forceUpdate)
{
// disable sensors that are out of battery or re-enable sensors that are
// being charged
Expand Down Expand Up @@ -344,6 +353,7 @@ void SensorsPrivate::RunOnce()
// publish data
IGN_PROFILE("RunOnce");
this->sensorManager.RunOnce(this->updateTime);
this->eventManager->Emit<events::Render>();
}

// re-enble sensors
Expand All @@ -366,6 +376,7 @@ void SensorsPrivate::RunOnce()
}

this->updateAvailable = false;
this->forceUpdate = false;
lock.unlock();
this->renderCv.notify_one();
}
Expand Down Expand Up @@ -422,6 +433,12 @@ void SensorsPrivate::Stop()
}
}

//////////////////////////////////////////////////
void SensorsPrivate::ForceRender()
{
this->forceUpdate = true;
}

//////////////////////////////////////////////////
void Sensors::RemoveSensor(const Entity &_entity)
{
Expand Down Expand Up @@ -540,6 +557,9 @@ void Sensors::Configure(const Entity &/*_id*/,
this->dataPtr->stopConn = _eventMgr.Connect<events::Stop>(
std::bind(&SensorsPrivate::Stop, this->dataPtr.get()));

this->dataPtr->forceRenderConn = _eventMgr.Connect<events::ForceRender>(
std::bind(&SensorsPrivate::ForceRender, this->dataPtr.get()));

// Kick off worker thread
this->dataPtr->Run();
}
Expand Down Expand Up @@ -573,7 +593,8 @@ void Sensors::PostUpdate(const UpdateInfo &_info,
{
std::unique_lock<std::mutex> lock(this->dataPtr->renderMutex);
if (!this->dataPtr->initialized &&
(_ecm.HasComponentType(components::Camera::typeId) ||
(this->dataPtr->forceUpdate ||
_ecm.HasComponentType(components::Camera::typeId) ||
_ecm.HasComponentType(components::DepthCamera::typeId) ||
_ecm.HasComponentType(components::GpuLidar::typeId) ||
_ecm.HasComponentType(components::RgbdCamera::typeId) ||
Expand Down Expand Up @@ -623,7 +644,8 @@ void Sensors::PostUpdate(const UpdateInfo &_info,
this->dataPtr->sensorMaskMutex.unlock();

if (!activeSensors.empty() ||
this->dataPtr->renderUtil.PendingSensors() > 0)
this->dataPtr->renderUtil.PendingSensors() > 0 ||
this->dataPtr->forceUpdate)
{
if (this->dataPtr->disableOnDrainedBattery)
this->dataPtr->UpdateBatteryState(_ecm);
Expand Down
2 changes: 1 addition & 1 deletion tutorials/rendering_plugins.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ events. Here's how to do it:

### Render events on the server

The server plugin will need to listen to `gz::sim::events::PreRender` or
The server plugin will need to listen `gz::sim::events::PreRender`, `gz::sim::events::Render` or
`gz::sim::events::PostRender` events.

Here's how to do it:
Expand Down

0 comments on commit 1c90252

Please sign in to comment.