## For instruction on writing tutorials
## http://www.ros.org/wiki/WritingTutorials
####################################
##FILL ME IN
####################################
## for a custom note with links:
## note =
## for the canned note of "This tutorial assumes that you have completed the previous tutorials:" just add the links
## note.0=[[vigir_pluginlib/Tutorials/CreateAndExportPlugins|Create and Export new Plugin]]
## note.1=[[vigir_pluginlib/Tutorials/UsingPluginWithParameter|How to use Dynamic Parameters in Plugins]]
## note.2=[[vigir_pluginlib/Tutorials/WorkingWithPluginManager|Working with the Plugin Manager]]
## descriptive title for the tutorial
## title = Plugin Description Inheritance
## multi-line description to be displayed in search
## description = The plugin system supports complex inheritance rules for plugin definitions. This tutorial explains how to take use of this feature.
## the next tutorial description (optional)
## next =
## links to next tutorial (optional)
## next.0.link=
## next.1.link=
## what level user is this tutorial for
## level= AdvancedCategory
## keywords = plugin, description, inheritance
####################################
<<IncludeCSTemplate(TutorialCSHeaderTemplate)>>

## AUTOGENERATED DO NOT DELETE
## TutorialCategory
## FILL IN THE STACK TUTORIAL CATEGORY HERE

<<Anchor(plugin_description_inheritance)>>

== Basic Inheritance ==
The plugin manager supports complex plugin definitions using an entire inheritance tree. For this purpose the tag `import` is used to signal to import all properties from the parent which may be overwritten afterwards by local values if given. The `import` tag applies also recursively. The example yaml config file used [[vigir_pluginlib/Tutorials/UsingPluginWithParameter#plugin_parameters|here]] can be extended to:
{{{
#!yaml
# PLUGIN DESCRIPTION FILE
my_concrete_plugin:
  type_class_package: my_concrete_plugins_pkg
  type_class: my_concrete_plugins_ns::MyConcretePlugin
  base_class_package: my_interface_plugins_pkg
  base_class: my_interface_plugins_ns::MyInterfacePlugin
  params:
    my_int: 42
    my_float: 3.14
    my_array: [1, 2, 3]

my_concrete_plugin_2:
  import: my_concrete_plugin    # Import properties from 'my_concrete_plugin'
  params:
    my_int: 2                   # Override param 'my_int'
    my_bool: True               # Adding new param

my_concrete_plugin_3:
  import: my_concrete_plugin_2  # Import properties from 'my_concrete_plugin_2'
  params:
    my_int: 3                   # Override param 'my_int' again!
    my_float: 4.2               # Override param 'my_float'
}}}

== Application to Plugin Sets ==
In order to provide more convenient usage of the plugin system, the plugin manager supports to load namely plugin sets. A plugin sets is a composition of multiple plugins to be active (instantiated) when this set is loaded.

A plugin set is given as yaml file and must be loaded into the same namespace as the plugin manager lives. Such a plugin set has followig structure:
{{{
#!yaml
# PLUGIN SET FILE
plugin_sets:                            # Do not remove this line, all plugin sets ...
                                        # ... have to be loaded into this namespace
  my_plugin_set_A:                      # Name of first plugin set
    my_concrete_plugin: none            # Using my_concrete_plugin as is ...
                                        # ... (defined by plugin description config)
    my_plugin_1:                        # Name of customized plugin (import syntax)
     import: my_concrete_plugin         # Inherit properties from my_concrete_plugin ...
                                        # ... (defined by plugin description config)
     params:                            # Define/override additional parameters ...
                                        # ... (see plugin parameters)
       my_int: 1024                     # Overload 'my_int' with new value (previously 42)

    ...

  my_plugin_set_B:                      # Name of second plugin set
    my_concrete_plugin:                 # Using my_concrete_plugin as is (override syntax)..
                                        # ... (defined by plugin description config) ...
      params:                           # ... but overriding some params ...
        my_int: 256                     # ... e.g. here 'my_int'  (previously 42)

  ...
}}}
'''Note:''' [[#plugin_description_inheritance|Inheritance of plugin descriptions]] works as well within plugin sets.

This plugin set config file must be loaded into the same namespace as the plugin manager, e.g. via rosparam tag in a launch file (assuming it is located at config/plugin_sets.yaml):
{{{
#!xml
<rosparam file="$(find my_concrete_plugins_pkg)/config/plugin_sets.yaml" command="load" />
}}}

Plugin set can be simply loaded by calling directly one of following methods on the plugin manager:
{{{
#!cplusplus
bool vigir_pluginlib::PluginManager::loadPluginSet(const std::vector<msgs::PluginDescription>& plugin_descriptions);
bool vigir_pluginlib::PluginManager::loadPluginSet(const std::string& name);
}}}
The first one just handles the given list of plugin descriptions as plugin set while latter just loads the named plugin set as specified by the plugin set config file loaded into the rosparam server. Alternatively ros topics, service and action server are available as listed [[vigir_pluginlib/Tutorials/WorkingWithPluginManager#ros_api|here]].

'''Note:''' The plugin manager detects the difference of requested plugin set and all already instantiated plugins. Thus, it will spawn only new plugins and delete all instantiated plugins which are not given in the plugin set. All other plugins will not be touched.