Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gui_system_plugin: clarify description in README #2253

Merged
merged 4 commits into from
Aug 7, 2024

Conversation

jrutgeer
Copy link
Contributor

The original text was:

Ignition Gazebo supports any kind of Ignition GUI plugin
(ignition::gui::Plugin). Gazebo GUI plugins are a special type of Ignition
GUI plugin which also have access to entity and component updates coming from
the server.

The current text is nonsense:

Gazebo GUI plugins are a special type of Gazebo GUI plugin

I propose to change to:

Gazebo supports any kind of GUI plugin (gz-gui library: gz::gui::Plugin). However, GuiSystem plugins (gz-sim library: gz::sim::GuiSystem) are a special type of GUI plugin, which also have access to entity and component updates coming from the server.


It is still not a good description though, but I can't propose a better description as I don't understand it:

What is "entity and component updates coming from the server"?

According to the documentation Plugin Types:

To interact with the server-side scene, you'll need to write an gz::sim::System.
To interact with the client-side scene, you'll need to write an gz::gui::Plugin, or a more specialized gz::sim::GuiSystem if you need to access entities and components.

It is confusing that this document states a gz::gui::Plugin for "updates coming from the server" and the other documentation states gz::sim::GuiSystem is client-side.

@jrutgeer jrutgeer requested a review from mjcarroll as a code owner November 21, 2023 10:29
@github-actions github-actions bot added the 🎵 harmonic Gazebo Harmonic label Nov 21, 2023
Copy link

codecov bot commented Nov 21, 2023

Codecov Report

All modified and coverable lines are covered by tests ✅

Comparison is base (14f8796) 65.64% compared to head (bf78731) 65.62%.

Additional details and impacted files
@@             Coverage Diff             @@
##           gz-sim8    #2253      +/-   ##
===========================================
- Coverage    65.64%   65.62%   -0.02%     
===========================================
  Files          324      324              
  Lines        30917    30917              
===========================================
- Hits         20295    20290       -5     
- Misses       10622    10627       +5     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@mjcarroll
Copy link
Contributor

Good catch, I think your rewording makes sense.

What is "entity and component updates coming from the server"?

In this case, the entity and component updates are coming from the simulation server via the SceneBroadcaster system.

The GUI (simulation client) and Server (simulation server) each maintain a copy of the ECM, and the state is periodically syncronized from the server to the client. GuiSystem plugins allow for interaction with the ECM state in the GUI.

Given this context is the explanation clearer? Should we add something like this?

@mjcarroll mjcarroll self-assigned this Nov 21, 2023
@jrutgeer
Copy link
Contributor Author

jrutgeer commented Nov 21, 2023

This is what I think to understand.
There are a few questions:

gz::gui::Plugin

A gz::gui::Plugin is a plugin that defines a widget to be loaded into a GUI window.

That GUI window can be:

  • The one that shows the running simulation,
  • Or any stand-alone GUI window (there doesn't even need to be a simulation running),

A gz::gui::Plugin can be used to implement general functionality, e.g.:

  • Instantiate a ROS node in the plugin to send ROS messages upon click of a button,
  • The gz::gui::plugins::ImageDisplay plugin shows images received through gz-transport
    (e.g. from a simulation sensor),
  • The gz::gui::plugins::MinimalScene plugin creates a gz::rendering::Scene and ensures that it gets rendered into the GUI window. This plugin however does not populate the scene (this is done by another plugin, see below).
  • Etc.

A gz::gui::Plugin has no access to entities and components.


gz::sim::GuiSystem

A gz::sim::GuiSystem is identical to a gz::gui::Plugin in that it is also a plugin to be loaded into a Gui window. However:

A gz::sim::GuiSystem has access to the ECM of the GUI process (i.e. the frontend process),

For this to work, the ECM of the GUI process must be kept in sync with the ECM of the simulation loop (i.e. of the backend process).

  • This is done by the SceneBroadcaster system plugin,
  • It is a one-way process: ECM changes are sent from backend process to frontend process only.
    • So if you want to add entities in both processes, you need to:
      • Load a system plugin in the backend process that inserts the entities into the backend ECM (e.g. the UserCommands system),
      • Use gz-transport to communicate from the frontend to that backend system plugin,
      • The frontend ECM will be synced to the backend ECM by the SceneBroadcaster.
  • It's not clear to me how the 'receiving end' for the SceneBroadcaster is configured.
    E.g. let's say I have one backend process with SceneBroadcaster plugin and two GUI windows. Will both automatically have an updated ECM?
    If so: what if I don't run GuiSystem plugins in one of those GUI windows (e.g. just some buttons and visualisations to interact with the simulation through gz-transport). That's a lot of unnecessary communication then?

Wrt. gz::gui::Plugin, the gz::sim::GuiSystem interface defines one extra function : update().

  • From the documentation: update() is called every time the system is stepped.
    • What does that mean, 'stepped'?
    • Aren't the GUI updates generally done at 60Hz (except in specific cases)? As opposed to the simulation step frequency?
  • update() is called from a Gazebo Transport thread, so any interaction with Qt should be done through signals and slots.

The gz::sim::GzSceneManager is a GuiSystem that updates the 3D scene (of the MinimalScene gui plugin) according to the frontend ECM.

  • What happens if a GuiSystem adds entities to the frontend ECM in its update() and what defines the order that the updates() are called?
    E.g. how to ensure that the GzSceneManager updates the scene with the newly added entity?
  • Do these frontend-added entities need to be re-added in each iteration? Or are they persistent?
  • How do frontend and backend avoid duplicate entity ID's?

@scpeters scpeters changed the title Description became unclear due to rename Ignition --> Gazebo gui_system_plugin: clarify description in README Nov 21, 2023
@azeey
Copy link
Contributor

azeey commented Jan 19, 2024

It's not clear to me how the 'receiving end' for the SceneBroadcaster is configured.
E.g. let's say I have one backend process with SceneBroadcaster plugin and two GUI windows. Will both automatically have an updated ECM?
If so: what if I don't run GuiSystem plugins in one of those GUI windows (e.g. just some buttons and visualisations to interact with the simulation through gz-transport). That's a lot of unnecessary communication then?

Yes, the SceneBroadcaster will publish the State message and both GUI windows will receive the update, assuming both GUI windows were created using gz::sim::gui::createGui. If you don't want to run GuiSystem plugins, I think you can just create gz::gui::Application yourself as in this example.

From the documentation: update() is called every time the system is stepped.
What does that mean, 'stepped'?
Aren't the GUI updates generally done at 60Hz (except in specific cases)? As opposed to the simulation step frequency?

Stepped is probably the wrong word here since that could imply physics/simulation steps. You are correct in the the SceneBroadcaster publishes the State message at 60Hz (except in specific cases).

update() is called from a Gazebo Transport thread, so any interaction with Qt should be done through signals and slots.

This is no longer the case as of #1095. Update is now called from the Qt thread.'

What happens if a GuiSystem adds entities to the frontend ECM in its update() and what defines the order that the updates() are called?

The order of Update calls follows the order in which the plugins are listed in the SDFormat file.

E.g. how to ensure that the GzSceneManager updates the scene with the newly added entity?
Do these frontend-added entities need to be re-added in each iteration? Or are they persistent?

The synchronization mechanism should not remove any entities that weren't also removed from the server, i.e, for the entity to be removed, it must have existed in the backend/server ECM and a system on the backend must of requested the removal of the entity.

How do frontend and backend avoid duplicate entity ID's?

Not sure about this. I don't think there's anything to prevent this

I also wanted to mention that there is some level of GUI->Server sync that happens when the play button is pressed.
There's some additional context here about it.

@azeey azeey added the beta Targeting beta release of upcoming collection label Jul 29, 2024
@azeey azeey enabled auto-merge (squash) August 6, 2024 23:26
@azeey azeey disabled auto-merge August 7, 2024 22:52
@azeey
Copy link
Contributor

azeey commented Aug 7, 2024

The ABI checker failed, but I'll go ahead and merge this since it's just a documentation change.

@azeey azeey merged commit fab620a into gazebosim:gz-sim8 Aug 7, 2024
8 of 9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
beta Targeting beta release of upcoming collection 🎵 harmonic Gazebo Harmonic
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

4 participants