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

Config file loading options #1012

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions include/ignition/gazebo/gui/Gui.hh
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,24 @@ namespace gui
/// ign-tools. Set to the name of the application if using ign-tools)
/// \param[in] _guiConfig The GUI configuration file. If nullptr, the default
/// configuration from IGN_HOMEDIR/.ignition/gazebo/gui.config will be used.
/// \return Zero if ran successfully.
IGNITION_GAZEBO_GUI_VISIBLE int runGui(int &_argc, char **_argv,
const char *_guiConfig);

/// \brief Run GUI application
/// \param[in] _argc Number of command line arguments (Used when running
/// without ign-tools. Set to 1 if using ign-tools). Note: The object
/// referenced by this variable must continue to exist for the lifetime of the
/// application.
/// \param[in] _argv Command line arguments (Used when running without
/// ign-tools. Set to the name of the application if using ign-tools)
/// \param[in] _guiConfig The GUI configuration file. If nullptr, the default
/// configuration from IGN_HOMEDIR/.ignition/gazebo/gui.config will be used.
/// \param[in] _guiConfigOption Options for loading GUI configuration.
/// \return Zero if ran successfully.
IGNITION_GAZEBO_GUI_VISIBLE int runGui(int &_argc, char **_argv,
const char *_guiConfig, const char *_guiConfigOption = nullptr);

/// \brief Create a Gazebo GUI application
/// \param[in] _argc Number of command line arguments (Used when running
/// without ign-tools. Set to 1 if using ign-tools). Note: The object
Expand All @@ -60,11 +75,36 @@ namespace gui
/// IGN_HOMEDIR/.ignition/gazebo/gui.config will be used.
/// \param[in] _loadPluginsFromSdf If true, plugins specified in the world
/// SDFormat file will get loaded.
/// \return The GUI application.
IGNITION_GAZEBO_GUI_VISIBLE
std::unique_ptr<ignition::gui::Application> createGui(
int &_argc, char **_argv, const char *_guiConfig,
const char *_defaultGuiConfig = nullptr, bool _loadPluginsFromSdf = true);

/// \brief Create a Gazebo GUI application
/// \param[in] _argc Number of command line arguments (Used when running
/// without ign-tools. Set to 1 if using ign-tools). Note: The object
/// referenced by this variable must continue to exist for the lifetime of the
/// application.
/// \param[in] _argv Command line arguments (Used when running without
/// ign-tools. Set to the name of the application if using ign-tools)
/// \param[in] _guiConfig The GUI configuration file. If nullptr, the default
/// configuration from IGN_HOMEDIR/.ignition/gazebo/gui.config will be used.
/// \param[in] _defaultGuiConfig The default GUI configuration file. If no
/// plugins were added from a world file or from _guiConfig, this
/// configuration file will be loaded. If this argument is a nullptr or if the
/// file does not exist, the default configuration from
/// IGN_HOMEDIR/.ignition/gazebo/gui.config will be used.
/// \param[in] _loadPluginsFromSdf If true, plugins specified in the world
/// SDFormat file will get loaded.
/// \param[in] _guiConfigOption Options for loading GUI configuration.
/// \return The GUI application.
IGNITION_GAZEBO_GUI_VISIBLE
std::unique_ptr<ignition::gui::Application> createGui(
int &_argc, char **_argv, const char *_guiConfig,
const char *_defaultGuiConfig, bool _loadPluginsFromSdf,
const char *_guiConfigOption);

} // namespace gui
} // namespace IGNITION_GAZEBO_VERSION_NAMESPACE
} // namespace gazebo
Expand Down
16 changes: 14 additions & 2 deletions src/cmd/cmdgazebo.rb.in
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,15 @@ COMMANDS = { 'gazebo' =>
" provided, the default installed config is \n"\
" used. \n"\
"\n"\
" --gui-config-option [arg] Options for combining GUI configs with GUI \n"\
" plugins defined on the world SDF file. \n"\
" Available options: \n"\
" * prepend: Load all plugins from the GUI config \n"\
" first, then all plugins from the SDF \n"\
" file. \n"\
" * merge: Same as prepend, but only the last \n"\
" instance of each plugin is loaded. \n"\
"\n"\
" --physics-engine [arg] Ignition Physics engine plugin to load. \n"\
" Gazebo will use DART by default. \n"\
" (ignition-physics-dartsim-plugin) \n"\
Expand Down Expand Up @@ -282,6 +291,9 @@ class Cmd
opts.on('--gui-config [arg]', String) do |c|
options['gui_config'] = c
end
opts.on('--gui-config-option [arg]', String) do |c|
options['gui_config_option'] = c
end
opts.on('--physics-engine [arg]', String) do |e|
options['physics_engine'] = e
end
Expand Down Expand Up @@ -465,7 +477,7 @@ See https://github.com/ignitionrobotics/ign-gazebo/issues/44 for more info."
ENV['RMT_PORT'] = '1501'
Process.setpgid(0, 0)
Process.setproctitle('ign gazebo gui')
Importer.runGui(options['gui_config'])
Importer.runGui(options['gui_config'], options['gui_config_option'])
end

Signal.trap("INT") {
Expand Down Expand Up @@ -503,7 +515,7 @@ See https://github.com/ignitionrobotics/ign-gazebo/issues/44 for more info."
end

ENV['RMT_PORT'] = '1501'
Importer.runGui(options['gui_config'])
Importer.runGui(options['gui_config'], options['gui_config_option'])
end
rescue
puts "Library error: Problem running [#{options['command']}]() "\
Expand Down
2 changes: 1 addition & 1 deletion src/cmd/ign.cc
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ extern "C" int runServer(const char *_sdfString,
}

//////////////////////////////////////////////////
extern "C" int runGui(const char *_guiConfig)
extern "C" int runGui(const char *_guiConfig, const char *_guiConfigOption)
{
ignition::common::SignalHandler sigHandler;
bool sigKilled = false;
Expand Down
36 changes: 35 additions & 1 deletion src/gui/Gui.cc
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,16 @@ namespace gui
std::unique_ptr<ignition::gui::Application> createGui(
int &_argc, char **_argv, const char *_guiConfig,
const char *_defaultGuiConfig, bool _loadPluginsFromSdf)
{
return createGui(_argc, _argv, _guiConfig, _defaultGuiConfig,
_loadPluginsFromSdf, nullptr);
}

//////////////////////////////////////////////////
std::unique_ptr<ignition::gui::Application> createGui(
int &_argc, char **_argv, const char *_guiConfig,
const char *_defaultGuiConfig, bool _loadPluginsFromSdf,
const char *_guiConfigOption)
{
ignition::common::SignalHandler sigHandler;
bool sigKilled = false;
Expand Down Expand Up @@ -162,6 +172,9 @@ std::unique_ptr<ignition::gui::Application> createGui(
std::size_t runnerCount = 0;

// Configuration file from command line

// TODO can't load config here because we may override it with SDF below

if (_guiConfig != nullptr && std::strlen(_guiConfig) > 0 &&
std::string(_guiConfig) != "_playback_")
{
Expand Down Expand Up @@ -222,6 +235,19 @@ std::unique_ptr<ignition::gui::Application> createGui(
runner->setParent(ignition::gui::App());
++runnerCount;

// Config options
if (_guiConfigOption != nullptr && std::strlen(_guiConfigOption) > 0)
{
auto option = std::string(_guiConfig);
if (option == "prepend")
{
}
else if (option == "merge")
{
}
}


// Load plugins after creating GuiRunner, so they can access worldName
if (_loadPluginsFromSdf)
{
Expand Down Expand Up @@ -290,7 +316,15 @@ std::unique_ptr<ignition::gui::Application> createGui(
//////////////////////////////////////////////////
int runGui(int &_argc, char **_argv, const char *_guiConfig)
{
auto app = gazebo::gui::createGui(_argc, _argv, _guiConfig);
return runGui(_argc, _argv, _guiConfig, nullptr);
}

//////////////////////////////////////////////////
int runGui(int &_argc, char **_argv, const char *_guiConfig,
const char *_guiConfigOption)
{
auto app = gazebo::gui::createGui(_argc, _argv, _guiConfig, nullptr, true,
_guiConfigOption);
if (nullptr != app)
{
// Run main window.
Expand Down
5 changes: 3 additions & 2 deletions src/ign.cc
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,7 @@ extern "C" int runServer(const char *_sdfString,
}

//////////////////////////////////////////////////
extern "C" int runGui(const char *_guiConfig)
extern "C" int runGui(const char *_guiConfig, const char *_guiConfigOption)
{
// argc and argv are going to be passed to a QApplication. The Qt
// documentation has a warning about these:
Expand All @@ -368,5 +368,6 @@ extern "C" int runGui(const char *_guiConfig)
// be converted to a const char *. The const cast is here to prevent a warning
// since we do need to pass a char* to runGui
char *argv = const_cast<char *>("ign-gazebo-gui");
return ignition::gazebo::gui::runGui(argc, &argv, _guiConfig);
return ignition::gazebo::gui::runGui(argc, &argv, _guiConfig,
_guiConfigOption);
}
3 changes: 2 additions & 1 deletion src/ign.hh
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,9 @@ extern "C" int runServer(const char *_sdfString,

/// \brief External hook to run simulation GUI.
/// \param[in] _guiConfig Path to Ignition GUI configuration file.
/// \param[in] _guiConfigOption Option for loading GUI configs.
/// \return 0 if successful, 1 if not.
extern "C" int runGui(const char *_guiConfig);
extern "C" int runGui(const char *_guiConfig, const char *_guiConfigOption);

/// \brief External hook to find or download a fuel world provided a URL.
/// \param[in] _pathToResource Path to the fuel world resource, ie,
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
61 changes: 48 additions & 13 deletions tutorials/gui_config.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,35 @@ There are a few places where the GUI configuration can come from:
2. A `<gui>` element inside an SDF file
3. The default configuration file at `$HOME/.ignition/gazebo/gui.config` \*

Each of the items above takes precedence over the ones below it. For example,
if a user chooses a `--gui-config`, the SDF's `<gui>` element is ignored. And
the default configuration file is only loaded if no configuration is passed
through the command line or the SDF file.

> \* For log-playback, the default file is
Each of the items above takes precedence over the ones below it by default.
For example, if a user chooses a `--gui-config`, the SDF's `<gui>` element is
ignored. The default configuration file is loaded if no configuration is
passed through the command line or the SDF file.

The default behaviour can be overridden using the `--gui-config-option`
command line argument, which offers options:

* `prepend`: Load plugins from both the config file and the SDF file. The config
Copy link
Contributor

Choose a reason for hiding this comment

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

The only thing that I think could be troublesome here is if you had duplicate plugins. The scenario that I'm thinking of would be having "specific" configuration in the SDF file and "generic" configuration in the gui.config file.

In that case, I think that you would want to prefer the "specific" configuration from the SDF file.

The implementation should take into account this scenario as well as the possibility of having duplicated plugins from the two configurations available.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah that's complicated to handle, because there are valid use cases for duplicate plugins, on both the GUI and the server. You may want multiple ImageDisplays or multiple WindEffects, for example.

I don't have a good idea on how to handle that. Maybe each plugin can be responsible for shortcutting multiple instantiation?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I added a merge option to cover this use case, with an example. Let me know what you think 4ab37d6. Coming back to this after so many months, now I think this will be my favorite option.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I reduced the number of options to 2 in d7a7677 and will work on the implementation now

file is loaded first.
* `merge`: Like `prepend`, but only the last instance of each plugin is loaded,
which should usually come from the SDF file.

The table below summarizes how all the options behave together.

Not all
combinations are useful, but we cover all corner cases (i.e. there's no point
in providing a config and also opting to `ignore` it):

--gui-config | SDF `<gui>` | --gui-config-option | Result
------------ | ------------ | ----------------------- | ------
empty | no plugins | empty / prepend / merge | Load plugins from `$HOME/.ignition/gazebo/gui.config`
provided | no plugins | empty / prepend / merge | Load plugins from `--gui-config`
empty | has plugins | empty | Load plugins from SDF
empty | has plugins | prepend / merge | Load plugins from `$HOME/.ignition/gazebo/gui.config` then SDF, merging as needed
provided | has plugins | empty | Load plugins from `--gui-config`
provided | has plugins | prepend / merge | Load plugins from `--gui-config` then SDF, merging as needed

> For log-playback, the default file is
> `$HOME/.ignition/gazebo/playback_gui.config`

## Try it out
Expand Down Expand Up @@ -138,9 +161,9 @@ configuration files from the command line.
Let's start by creating a custom configuration file, but instead of editing by
hand, we'll create it from the UI.

1. Let's start loading the SDF world we created above, with the `<gui>` element back:
1. Start loading the SDF world we created above, with the `<gui>` element back:

`ign gazebo <path to>/fuel_preview.sdf`
`ign gazebo <path to>/fuel_preview.sdf`

2. Now from the top-right menu, choose to add the "View Angle" plugin. This
plugin has convenient buttons to change the camera angle, try them out!
Expand All @@ -156,21 +179,33 @@ hand, we'll create it from the UI.

7. Close Gazebo

@image html files/gui_config/save_config.gif
@image html files/gui_config/save_config.gif

1. Take a look at the saved file if you're curious, it will look a lot like
8. Take a look at the saved file if you're curious, it will look a lot like
the default file, but with more properties defined.

2. Finally, let's load the previous world, with our custom configuration:
9. Finally, let's load the previous world, with our custom configuration:

`ign gazebo <path to>/fuel_preview.sdf --gui-config <path to>saved.config`

3. Gazebo should open with your custom layout.
10. Gazebo should open with your custom layout.

@image html files/gui_config/cmd_line.png

**Tip**: From the top-left menu, you can choose "Save client configuration" to
save directly to `$HOME/.ignition/gazebo/gui.config`.

@image html files/gui_config/cmd_line.png
**Tip**: In case you want to use the default GUI layout without editing the SDF file to
remove `<gui>`, you can pass `--gui-config $HOME/.ignition/gazebo/gui.config`:

#### Options

The above gives you other plugins, but the 3D scene isn't nicely formatted to
view the model (blue background, diagonal camera angle...). In order to get all
the default plugins, but format the 3D scene as it is in the SDF, we can use the
`merge` option:

`ign gazebo --gui-config-option merge <path to>/fuel_preview.sdf`

@image html files/gui_config/fuel_preview_merge.png