Profiles
Compositions allow to define self-contained networks. These networks have to be exposed as actions into the system, which is what is accessible to the coordination layer and externally to the user. Moreover, these networks aim ultimately at being as system- and application-independent as possible, allowing their reuse in different contexts and/or with different configurations.
The place where they are exported as actions, and fine-tuned to an application/system need is the Profile. We will go through the basics about profiles in this section, to significantly expand in the next, where we talk about reusable models.
Definition
Profiles are defined inside a module with the profile
statement, which
creates and registers a profile object in the enclosing module. For instance,
the following code snippet creates a profile whose full name is
AppName::Profiles::ProfileName
:
module AppName
module Profiles
profile "ProfileName" do
end
end
end
Naming Convention Profiles are by convention defined under the AppName::Profiles
namespace (e.g. CommonModels::Profiles
for the common_models
bundle).
They are saved in models/profiles/
. The file
names should be the snake_case version of the profile name (e.g.
models/profiles/profile_name.rb
for the profile defined above).
Generation Template for a profile, following Syskit's naming and filesystem conventions, can be created with
syskit gen profile name/of_profile
for instance
syskit gen profile rovers/localization
Registering Networks on Profiles
A component network when registered on a profile is called a definition
and is created with the define
statement. From the
basics:
module SyskitBasics
module Profiles
profile 'ArmControl' do
define 'arm_cartesian_constant_control',
Compositions::ArmCartesianConstantControlWdls
define 'arm_joint_position_constant_control',
Compositions::JointPositionConstantControl
end
end
end
Note models used within the composition need to be loaded at the toplevel
of the composition file, before the composition definition. orogen models with
the using_task_library
statement, other models by require
'ing the file that
defines it.
Once created, the definition is available as a method on the profile object,
using the pattern ${definition_name}_def
. This allows to create new
definitions based on other ones. Modifiers can directly be called on the model
object passed as argument to define
.
An example that combines both can be found in the basics section:
define 'arm_joint_position_constant_control',
Compositions::JointPositionConstantControl
define 'arm_safe_position',
arm_joint_position_constant_control_def
.with_arguments(setpoint: UR10_SAFE_POSITION)
Common Patterns
Specifying Configuration and Arguments
To set the configuration and/or arguments of a toplevel model before defining
it, pass the with_conf
(resp. with_arguments
) call to the model, as:
define 'arm_safe_position',
arm_joint_position_constant_control_def
.with_arguments(setpoint: UR10_SAFE_POSITION)
In addition, it is possible to change the configuration/arguments of a child of a composition. This uses dependency injection mechanisms that will be detailed in the next section, but the pattern is easy enough to use:
define 'cartesian_control_wdls_slow', arm_cartesian_constant_control_def.
use('control.twist2joint_velocity' =>
OroGen.cart_ctrl_wdls.WDLSSolver.with_conf('default', 'slow'))
The string in the use
statement is the path to the child that is being
refined (in this case, the twist2joint_velocity
child of the control
child
in the arm_cartesian_constant_control
definition).
use
vs composition configurations This mechanism
looks very much like the composition configurations.
Composition configurations are meant to be used when some configurations are
really expected to be present on the composition, as for instance if these
configurations are used by a higher-level mechanism. The use
statement is
better for the other cases, as it does not assume that all useful
configurations will be known at the composition's design time.
use
vs composition argument forwarding This mechanism
also looks very much like the argument forwarding.
Use argument forwarding when the argument makes sense on the composition. In
the basics section, it really makes sense that a constant control composition
has a setpoint
argument, and that is therefore how it has been implemented.
use
is for the other cases.