Skip to content

Commit

Permalink
review of the basics section, and update to the OroGen. syntax
Browse files Browse the repository at this point in the history
  • Loading branch information
doudou committed Oct 13, 2017
1 parent a2118e7 commit 85ba190
Show file tree
Hide file tree
Showing 15 changed files with 255 additions and 207 deletions.
90 changes: 45 additions & 45 deletions source/basics/composition.html.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,9 @@ style="opacity: 0.4;">in grey</span>

In Syskit, one has to _declare_ how components must be connected together to
form a function, and then can request the system to actually run that function.

This page deals with the first step (design). The [next
page](constant_generator.html) will create the command generator, and we
will then [_deploy_ the network](deployment.html) and run it.
page](constant_generator.html) will create the command generator, and we will
then [_deploy_ the network](deployment.html) and run it.

But let's not get too much ahead of ourselves. We will need to first install
the control package that will implement the control.
Expand Down Expand Up @@ -87,7 +86,9 @@ The "first match" line is always the package set where the package is defined. I
</div>
</div>

To install the package, add it in the `layout` section of `autoproj/manifest`:
In this tutorial, we will want to use the `control/orogen/cart_ctrl_wdls` which
uses the KDL library to do cartesian control of a robotic arm. To install the
package, add it in the `layout` section of `autoproj/manifest`:

~~~yaml
layout:
Expand All @@ -108,17 +109,17 @@ And finally build and install
amake --all
~~~

## Binding the components together {#composition}
## Using the installed components

Now that everything's installed, go back within the bundle folder. You may for
instance do `acd b/syskit` ([more about `acd`](day_to_day.html#acd))
Now that everything's installed, go back within the bundle folder. You may not
use `acd` for this ([more about `acd`](day_to_day.html#acd)) yet, since the
bundle has not been registered in autoproj.

Compositions declare groups of components and connects them together. In
addition, we will see later on that they can be seen by the rest of the system as
components themselves, i.e. they can be used and connected in other
compositions.
Compositions declare groups of components and connects them together. Once
defined, compositions can be used in other compositions to build more complex
networks.

Let's create our `arm_cartesian_control_wdls` composition
Let's create our first building block, the `ArmCartesianControlWdls` composition

~~~
$ syskit gen cmp arm_cartesian_control_wdls
Expand All @@ -128,37 +129,37 @@ $ syskit gen cmp arm_cartesian_control_wdls
create test/compositions/test_arm_cartesian_control_wdls.rb
~~~

<div class="panel panel-info">
<div class="panel-heading" id="orogen">
OroGen packages in Syskit
</div>
<div class="panel-body">
As described in our [brief introduction](index.html), oroGen packages are
where the functionality implemented in the library packages are "packaged" into things
that can be used at runtime. To be used in Syskit, these oroGen components must be first imported using the
`using_task_library` statement. In our case, `cart_ctrl_wdls`, this is done with
As described in our [brief introduction](index.html), oroGen packages are where
the functionality implemented in the library packages are "packaged" into
things that can be used at runtime. To be used in Syskit, these oroGen
components must be first imported using the `using_task_library` statement. In
our case, `cart_ctrl_wdls`, this is done with

~~~ruby
using_task_library "cart_ctrl_wdls"
~~~

This loads the oroGen project, and imports the components in it to make them
available in the Syskit models. The name of the imported models is mapped from
the oroGen naming scheme to the Syskit naming scheme by CamelCasing the project
name, e.g. `cart_ctrl_wdls` becomes `CartCtrlWdls` and the
available in the Syskit models. The task models from the oroGen project are
then made available within the Syskit app under the
`OroGen.project_name.ComponentName` scheme, e.g. the
`cart_ctrl_wdls::ToPosConverter` component is accessible under
`OroGen::CartCtrlWdls::ToPosConverter` in Syskit.
`OroGen.cart_ctrl_wdls.ToPosConverter` in Syskit.

In case you're not sure about the naming, just add the `using_task_library` statement
at the toplevel of a file and load it with `syskit ide`. If we do so in our newly created `models/compositions/arm_cartesian_control_wdls.rb` and run
In case you're not sure about the naming, just add the `using_task_library`
statement at the toplevel of a file and load it with `syskit ide`.

Let's do so in our newly created
`models/compositions/arm_cartesian_control_wdls.rb`. Then, run

~~~
syskit ide models/compositions/arm_cartesian_control_wdls.rb
syskit ide -rgazebo models/compositions/arm_cartesian_control_wdls.rb
~~~

![Name mapping between oroGen and Syskit](media/syskit_name_mapping.png){: .fullwidth}
</div>
</div>

**Note** Leave the IDE open, we will reuse it
{: .note}

We now want to build the cartesian control network. What each component does in
the `cart_ctrl_wdls` project can be found by reading the documentation displayed
Expand All @@ -181,8 +182,8 @@ using_task_library 'cart_ctrl_wdls'
module SyskitBasics
module Compositions
class ArmCartesianControlWdls < Syskit::Composition
add OroGen::CartCtrlWdls::WDLSSolver, as: 'twist2joint_velocity'
add OroGen::CartCtrlWdls::CartCtrl, as: 'position2twist'
add OroGen.cart_ctrl_wdls.WDLSSolver, as: 'twist2joint_velocity'
add OroGen.cart_ctrl_wdls.CartCtrl, as: 'position2twist'
add CommonModels::Devices::Gazebo::Model, as: 'arm'
end
end
Expand All @@ -191,12 +192,11 @@ end

At this stage, we will have to connect the ports together. To see what inputs
and outputs are available, one can have a look at the component's `.orogen`
files. The alternative is to open the `syskit ide -rgazebo` and inspect the composition
file as follows (`-rgazebo` is necessary because we are importing models from
`common_models`). **Leave the IDE open after this, we will reuse it**
files. The alternative is to use the IDE. Click the `Reload Models` button and
open the composition page:

<div class="fluid-video">
<iframe width="853" height="480" src="https://www.youtube.com/embed/hTBYnlc0J3Q?rel=0&amp;showinfo=0" frameborder="0" allowfullscreen></iframe>
<iframe width="853" height="480" src="https://www.youtube.com/embed/9Sz7gREngHM?rel=0&amp;showinfo=0" frameborder="0" allowfullscreen></iframe>
</div>

We may now start adding connections in the composition definition. The `as`
Expand All @@ -210,8 +210,8 @@ command to the actual arm command input:

~~~ruby
class ArmCartesianControlWdls < Syskit::Composition
add OroGen::CartCtrlWdls::WDLSSolver, as: 'twist2joint_velocity'
add OroGen::CartCtrlWdls::CartCtrl, as: 'position2twist'
add OroGen.cart_ctrl_wdls.WDLSSolver, as: 'twist2joint_velocity'
add OroGen.cart_ctrl_wdls.CartCtrl, as: 'position2twist'
add CommonModels::Devices::Gazebo::Model, as: 'arm'

position2twist_child.ctrl_out_port.
Expand All @@ -221,7 +221,9 @@ class ArmCartesianControlWdls < Syskit::Composition
end
~~~

And hit the "Reload Models" button at the top of the IDE window
And hit the "Reload Models" button at the top of the IDE window. Syntax errors
(such as a misspelled port name) are shows at the bottom of the view. Just
click reload after you fixed them.

Let's inspect the remaining unconnected input ports. There's `command`,
`cartesian_status` and `joint_status` ports that obviously need to be connected
Expand All @@ -234,9 +236,7 @@ arm_child.joints_status_port.

However, the cartesian position feedback is not directly provided by the Gazebo
model. Fortunately, the `control/orogen/robot_frames` project provides components
to do the joint-to-cartesian conversion.

Add it now to the workspace [in the same way we added
to do the joint-to-cartesian conversion. Add it now to the workspace [in the same way we added
`control/orogen/cart_ctrl_wdls`](#add_package), import it in the composition
file with `using_task_library` and reload models within the IDE.
Then, finally add it to the composition.
Expand All @@ -251,10 +251,10 @@ using_task_library 'robot_frames'
module SyskitBasics
module Compositions
class ArmCartesianControlWdls < Syskit::Composition
add OroGen::CartCtrlWdls::WDLSSolver, as: 'twist2joint_velocity'
add OroGen::CartCtrlWdls::CartCtrl, as: 'position2twist'
add OroGen.cart_ctrl_wdls.WDLSSolver, as: 'twist2joint_velocity'
add OroGen.cart_ctrl_wdls.CartCtrl, as: 'position2twist'
add CommonModels::Devices::Gazebo::Model, as: 'arm'
add OroGen::RobotFrames::SingleChainPublisher, as: 'joint2pose'
add OroGen.robot_frames.SingleChainPublisher, as: 'joint2pose'

position2twist_child.ctrl_out_port.
connect_to twist2joint_velocity_child.desired_twist_port
Expand Down
59 changes: 30 additions & 29 deletions source/basics/constant_generator.html.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@ sort_info: 30

<div class="callout callout-info">
**Where are we ?** We have created
`SyskitBasics::Compositions::ArmCartesianControlWdls`, which positions an arm
at a cartesian position. The cartesian position is provided outside the
[The `SyskitBasics::Compositions::ArmCartesianControlWdls` composition](composition.html), which positions an arm
at a given cartesian position. The cartesian position is provided outside the
network. We will now create and integrate both the generator to provide this
setpoint, as well as the generator to maintain a constant joint position.
The next pages will then bind the result to the simulation and finally deploy and run it.
We will also learn how to write unit tests.

Below, the parts we will handle on this page are <span style="color:
#5bc0de;">in blue</span>.
Expand All @@ -23,36 +25,27 @@ Below, the parts we will handle on this page are <span style="color:
- TOC
{:toc}

[The control network we just created](composition.html) does not have a command
generator. The first generator one usually creates is a constant one, creating an
interface to send a constant command from Syskit into a control network.

We will create the command generator now, then bind the result [to the simulation](devices.html)
and finally [deploy and run it](deployment.html).

We will also learn how to write unit tests.

## The Cartesian Constant Generator

For the command, let's generate a single constant command. It will allow us to
move the arm tip from one point to another, expressed in the cartesian frame.

The first thing is to find out what's the data type of the port. If we look at
The first step is to find out what's the data type of the port. If we look at
the dataflow in the `ArmCartesianControlWdls` composition, we find:

![Datatype of the cartesian command](media/arm_cartesian_control_wdls_dataflow.svg){: .fullwidth}

The type name is `/base/samples/RigidBodyState`. Types like this one are
defined when implementing components, which is something we will see
[later](../type_system). You can have an overview of the
types already available in your Rock workspace by starting the
`rock-browse` tool.
types already available in your Rock workspace by looking at the `Types` section
in the IDE's model browser. Clicking on a port will lead you to this port's
type page. Right-clicking on any page allows to go to previous pages.

`bundles/common_models` provides `Compositions::ConstantGenerator`, a generic
implementation of a component that periodically emits a value of a certain type. This generator is
a `Syskit::RubyTaskContext`, which is like an oroGen component that is part of
the Syskit process. It's useful to create very simple components without having
to get through the whole oroGen step. It is also used in tests to stub existing components.
a `Syskit::RubyTaskContext`, which a component that is executed as part of
the Syskit process. It is useful to create very simple components without having
to get through the process of creating a full-fledged C++ component. It is also used in tests to stub existing components.

`ConstantGenerator` is generic, so it's not used as-is. One instead
creates a specific component for the task at hand. In our case, we'll create
Expand All @@ -70,7 +63,13 @@ $ syskit gen ruby_task arm_cartesian_constant_command_generator
~~~

The easiest way to reuse the constant generator is to subclass our generator
from it, by using the `ConstantGenerator.for(type)` method:
from it, by using the `ConstantGenerator.for(type)` method. We first have
to import the type. `typekits` are the units that define types in a rock system, so we have to import
`/base/samples/RigidBodyState`'s typekit, which is listed on the type's page:

![Finding a typekit for a type](media/type_to_typekit.png){: .fullwidth}

To import it, one must use the `import_types_from` stanza. Let's put it all together:

~~~ruby
import_types_from 'base'
Expand Down Expand Up @@ -125,7 +124,7 @@ part](../type_system). For now, just accept it.
{: .callout .callout-info}

This kind of "high-level argument shadowing low-level
arguments must have a one-to-N relationship (usually one-to-one). It is
arguments" sugar must have a one-to-N relationship (usually one-to-one). It is
possible but not trivial, under the Syskit argument handling, to "aggregate"
multiple high-level arguments into a low-level one.
{: .callout .callout-warning}
Expand Down Expand Up @@ -202,6 +201,10 @@ and all the tests for a given robot configuration with
$ syskit test -rgazebo
~~~

**Note** that the our new tests would not be run by simply calling `syskit test
-rgazebo`, as the generator and composition models are not loaded within the gazebo configuration (yet).
{: .note}

The IDE also gives an interface to the tests. It will display all the tests for
the given robot configuration and allow to start them separately. It also
allows to auto-run all the discovered tests, and re-run tests when the files
Expand Down Expand Up @@ -235,7 +238,7 @@ end

The `expect_execution` construct is the Syskit starting point for all things
asynchronous in tests. Sending and receiving samples requires the constant
generator to be executed, and therefore Syskit's own execution loop.
generator to be executed - and therefore Syskit's own execution loop as well.
{: .callout .callout-info}

Rock's time representation has a precision of one microsecond, while Linux
Expand Down Expand Up @@ -274,9 +277,8 @@ end
## Creating the ArmCartesianConstantControlWdls Composition

Now that we have a generator, let's bind it to our control loop to have
something that can move and hold our arm to a given pose.

We'll create the composition now.
something that can move and hold our arm to a given pose. This is obviously
going to be done by a composition as well.

~~~
$ syskit gen cmp arm_cartesian_constant_control_wdls
Expand Down Expand Up @@ -448,7 +450,6 @@ syskit gen ruby_task joint_position_constant_generator
~~~ruby
require 'models/compositions/constant_generator'
import_types_from 'base'
require 'base/float'

module SyskitBasics
module Compositions
Expand All @@ -464,10 +465,10 @@ module SyskitBasics
joint_commands = setpoint.each_value.map do |position|
Types.base.JointState.new(
position: position,
speed: Base.unset,
effort: Base.unset,
raw: Base.unset,
acceleration: Base.unset)
speed: Float::NAN,
effort: Float::NAN,
raw: Float::NAN,
acceleration: Float::NAN)
end
self.values = Hash['out' =>
Types.base.commands.Joints.new(
Expand Down
Loading

0 comments on commit 85ba190

Please sign in to comment.