The example shows how to implement robot hardware with separate communication
to each actuator.

Example 7: “6-DOF robot”

A full tutorial for a 6 DOF robot for intermediate ROS 2 users.

Example 8: “Using transmissions”

_RRBot_ with an exposed transmission interface.

Example 9: “Gazebo Classic”

Demonstrates how to switch between simulation and hardware.

Example 10: “GPIO interfaces”

Industrial robot with GPIO interfaces

Example 11: “CarlikeBot”

_CarlikeBot_ with a bicycle steering controller

Example 12: “Controller chaining”

The example shows a simple chainable controller and its integration to form a
controller chain to control the joints of _RRBot_ .


In the ROS 1 wiki for ` roslaunch ` , it says ( [
https://wiki.ros.org/roslaunch/Architecture
](https://wiki.ros.org/roslaunch/Architecture) ):


TODO: Anything we choose not to support in the requirements vs. the
“separation of concern section”, and also any alternatives which we considered
but rejected in the reference implementation proposal.


###  Mapping to Programming Languages and Markup Languages


1. **publish_frequency** . Please modify the publication frequency to suit your needs, with a minimum value of 1 Hz.


##  Requirements


####  Deterministic Startup


controls/ros2_control_demos/actions/workflows/galactic-semi-binary-
build.yml?branch=galactic)
|  [ Documentation ](https://control.ros.org/galactic/index.html)
[ API Reference ](https://control.ros.org/galactic/doc/api/index.html)
**Foxy** |  [ ` foxy ` ](https://github.com/ros-
controls/ros2_control_demos/tree/foxy) |  [ ![Foxy Binary
Build](https://github.com/ros-
controls/ros2_control_demos/actions/workflows/foxy-binary-
build.yml/badge.svg?branch=foxy) ](https://github.com/ros-
controls/ros2_control_demos/actions/workflows/foxy-binary-
build.yml?branch=foxy)
[ ![Foxy Semi-Binary Build](https://github.com/ros-
controls/ros2_control_demos/actions/workflows/foxy-semi-binary-
build.yml/badge.svg?branch=foxy) ](https://github.com/ros-
controls/ros2_control_demos/actions/workflows/foxy-semi-binary-
build.yml?branch=foxy)
|  [ Documentation ](https://control.ros.org/foxy/index.html)
[ API Reference ](https://control.ros.org/foxy/doc/api/index.html)

###  Explanation of different build types


Any  operating system process  can become ROS specific by having at least one
ROS Node within it. Having one or more “plain” ROS nodes in a process doesn’t
add new standardized ways to get information into or out of the  operating
system process  that contains them, though ROS topics, services, parameters,
etc. can be accessed during runtime. It does however, add some specific kinds
of inputs during execution and it also can affect how the process reacts to
signals.


####  Shell Evaluation


  Examples Overview  

Example 1: RRBot

_RRBot_ \- or ‘’Revolute-Revolute Manipulator Robot’’ - a simple position
controlled robot with one hardware interface. This example also demonstrates
the switching between different controllers.

Example 2: DiffBot

_DiffBot_ , or ‘’Differential Mobile Robot’’, is a simple mobile base with
differential drive. The robot is basically a box moving according to
differential drive kinematics.

Example 3: “RRBot with multiple interfaces”

_RRBot_ with multiple interfaces.

Example 4: “Industrial robot with integrated sensor”

_RRBot_ with an integrated sensor.

Example 5: “Industrial robot with externally connected sensor”

_RRBot_ with an externally connected sensor.

Example 6: “Modular robot with separate communication to each actuator”


  * [ ![@christophfroehlich](https://avatars.githubusercontent.com/u/3367244?s=64&v=4) ](https://github.com/christophfroehlich)
  * [ ![@destogl](https://avatars.githubusercontent.com/u/1918204?s=64&v=4) ](https://github.com/destogl)
  * [ ![@bmagyar](https://avatars.githubusercontent.com/u/3524577?s=64&v=4) ](https://github.com/bmagyar)
  * [ ![@dependabot\[bot\]](https://avatars.githubusercontent.com/in/29110?s=64&v=4) ](https://github.com/apps/dependabot)
  * [ ![@olivier-stasse](https://avatars.githubusercontent.com/u/400341?s=64&v=4) ](https://github.com/olivier-stasse)
  * [ ![@Karsten1987](https://avatars.githubusercontent.com/u/5419873?s=64&v=4) ](https://github.com/Karsten1987)
  * [ ![@ARK3r](https://avatars.githubusercontent.com/u/22005547?s=64&v=4) ](https://github.com/ARK3r)
  * [ ![@github-actions\[bot\]](https://avatars.githubusercontent.com/in/15368?s=64&v=4) ](https://github.com/apps/github-actions)
  * [ ![@AndyZe](https://avatars.githubusercontent.com/u/11284393?s=64&v=4) ](https://github.com/AndyZe)
  * [ ![@saikishor](https://avatars.githubusercontent.com/u/10082428?s=64&v=4) ](https://github.com/saikishor)
  * [ ![@bailaC](https://avatars.githubusercontent.com/u/14002410?s=64&v=4) ](https://github.com/bailaC)
  * [ ![@jordan-palacios](https://avatars.githubusercontent.com/u/26386634?s=64&v=4) ](https://github.com/jordan-palacios)
  * [ ![@aprotyas](https://avatars.githubusercontent.com/u/34530011?s=64&v=4) ](https://github.com/aprotyas)
  * [ ![@liushuya7](https://avatars.githubusercontent.com/u/6867028?s=64&v=4) ](https://github.com/liushuya7)


Toggle navigation


[ .pre-commit-config.yaml ](/ros-controls/ros2_control_demos/blob/humble/.pre-
commit-config.yaml ".pre-commit-config.yaml")


[ Custom properties  ](/ros-controls/ros2_control_demos/custom-properties)


  What you can find in this repository  

This repository demonstrates the following ` ros2_control  ` concepts:

>   * Creating a ` HardwareInterface  ` for a System, Sensor, and Actuator.
>
>   * Creating a robot description in the form of URDF files.
>
>   * Loading the configuration and starting a robot using launch files.
>
>   * Control of a differential mobile base _DiffBot_ .
>
>   * Control of two joints of _RRBot_ .
>
>   * Control of a 6-degrees-of-freedom robot.
>
>   * Implementing a controller switching strategy for a robot.
>
>   * Using joint limits and transmission concepts in ` ros2_control  ` .
>
>


It also does not react in any special way to ` stdin ` , but processes
containing ROS nodes do tend to have a signal handler for ` SIGINT ` which
does a more graceful shutdown, but that is not enforced. Sending the ` SIGINT
` signal typically causes most nodes to shutdown if they are using one of the
“spin” functions in ` rclcpp ` or are polling ` rclcpp::ok() ` , as is
recommended.


Disadvantages:


The goal of the system description is to capture the intentions of the user
describing the system to be launched, with as few side effects as possible.
The reason for doing this is so that a launch description can be visualized
and statically analyzed without actually launching the described system.
Having a tool that can allow a developer to visualize and modify the launch
description in a WYSIWYG (what you see is what you get) editor is an important
use case for the system description.


A full tutorial for a 6 DOF robot for intermediate ROS 2 users.


####  Locating Files


By separating the declaration of an action from the execution of an action,
tools may use the launch descriptions to do things like visualize what a
launch description will do without actually doing it. The launch system will
simply use the interpreted actions in the launch descriptions to actually
execute the actions.


The “modify the launch system configurations at the current scope” action
mentioned above is able to mutate a local scope of configurations which can
affect other actions which come after the modification. Actions may use this
local state to uniformly apply certain settings to themselves.


[ example_9 ](/ros-controls/ros2_control_demos/tree/humble/example_9
"example_9")


    * [ Actions  Automate any workflow  ](/features/actions)
    * [ Packages  Host and manage packages  ](/features/packages)
    * [ Security  Find and fix vulnerabilities  ](/features/security)
    * [ Codespaces  Instant dev environments  ](/features/codespaces)
    * [ Copilot  Write better code with AI  ](/features/copilot)
    * [ Code review  Manage code changes  ](/features/code-review)
    * [ Issues  Plan and track work  ](/features/issues)
    * [ Discussions  Collaborate outside of code  ](/features/discussions)


By default, the launch system will:


2. unload_node


####  Execution


Like the Qt event system, it will be possible to create event filters, which
emulate the ability to accept events and prevent them from being sent
“downstream”.  6


####  Substitutions


####  Runtime


If the container process is asked to shutdown due to normal [Termination],
then the exit code must be 0. If it exits due to an error then exit code must
be any other number.


_RRBot_ \- or ''Revolute-Revolute Manipulator Robot'' - a simple position
controlled robot with one hardware interface. This example also demonstrates
the switching between different controllers.


The specific syntax of these extra environment variables and command line
arguments are defined in other documents  5  1  .


This description lays out the main roles of ` roslaunch ` from ROS 1 as:


Readme


[ control.ros.org ](https://control.ros.org "https://control.ros.org")


Again, like many other event systems, the events should have a type (either as
an attribute or as a child class) which can be used to filter events to
particular handlers.


[ robotics ](/topics/robotics "Topic: robotics") [ ros ](/topics/ros "Topic:
ros") [ rrbot ](/topics/rrbot "Topic: rrbot") [ ros2-control
](/topics/ros2-control "Topic: ros2-control") [ ros2-controllers
](/topics/ros2-controllers "Topic: ros2-controllers")


##  Structure


    [docking_server-2] [INFO] [1711034253.663142482] [docking_server]: [DockingServer] Docking Server Initialized
    [agent_node-1] [INFO] [1711034254.326381135] [agent_node]: [SetUp] Reading initialization parameters
    [agent_node-1] [INFO] [1711034254.328050682] [agent_node]: [SetUp] Ros distro is : humble
    [agent_node-1] [INFO] [1711034254.328925869] [agent_node]: [SetUp] Ros version is :2
    [agent_node-1] [INFO] [1711034254.329785937] [agent_node]: [SetUp] COMPLETED Initial ROS Parameter configuration


From this, there are a few more design goals and roles for ` roslaunch ` from
ROS 1:


    * True: Meili FMS will send a set of waypoints shown in the path on the map editor page.
    * False: Default value →Meili FMS will only send points configured on the map editor page.
  5. **traffic_control** : Indicates if real-time paths calculated by AMRs are streamed to the cloud, and traffic control algorithms will be applied.


#  Search code, repositories, users, issues, pull requests...


Authors: [ William Woodall ](https://github.com/wjwwood)


The concepts in this package are demonstrated on the examples of _RRBot_ and
_DiffBot_ . Those two world-known imaginary robots are trivial simulations to
demonstrate and test ` ros2_control ` concepts.


7. [ https://docs.python.org/3.6/library/subprocess.html#subprocess.run ](https://docs.python.org/3.6/library/subprocess.html#subprocess.run) ↩


[ ros2_control_demos.foxy.repos ](/ros-
controls/ros2_control_demos/blob/humble/ros2_control_demos.foxy.repos
"ros2_control_demos.foxy.repos")


#####  Execute a Process


  * respawn a process if it died
  * shutdown the whole launch system if a required process died


> roslaunch was designed to fit the ROS architecture of complexity via
> composition: write a simple system first, then combine it with other simple
> systems to make more complex systems. In roslaunch, this is expressed
> through several mechanisms:


[ Sign up
](/signup?ref_cta=Sign+up&ref_loc=header+logged+out&ref_page=%2F%3Cuser-
name%3E%2F%3Crepo-name%3E%2Ffiles%2Fdisambiguate&source=header-
repo&source_repo=ros-controls%2Fros2_control_demos)


_RRBot_ with multiple interfaces.


##  History


[ example_11 ](/ros-controls/ros2_control_demos/tree/humble/example_11
"example_11")


######  API using STDIN


3. list_nodes


#  Provide feedback


The mechanism for how Managed ROS Nodes transition to the Finalized state (or
any other state) will not be decided in this document. Instead, the
implementations or some other lifecycle specific documentation will cover
that. However, you could imagine this transition could be handled by the Node
itself automatically, or by launch sending a state transition request, or by
launch sending a specific signal.


__ [ ROS2_Control: Rolling ](../../../index.html)

  * [ ](../../../index.html)
  * Demos
  * [ Edit on GitHub ](https://github.com/ros-controls/ros2_control_demos/blob/master/doc/index.rst)

* * *

**You're reading the documentation for a development version. For the latest
released version, please have a look at[ Iron
](../../../../iron/doc/ros2_control_demos/doc/index.html) . **


Uses repos file: ` src/$NAME$/$NAME$.repos `


How events are defined is up to the implementation, but it should be possible
to model the events so they can be emitted and then handled by registered
event handlers.


Disadvantages:


####  ROS Specific Events


* Product


#  Saved searches


* Example 7: [ "6-DOF robot" ](/ros-controls/ros2_control_demos/blob/humble/example_7)


_DiffBot_ , or ''Differential Mobile Robot'', is a simple mobile base with
differential drive. The robot is basically a box moving according to
differential drive kinematics.


5. [ https://github.com/ros2/ros2/wiki/Logging#console-output-configuration ](https://github.com/ros2/ros2/wiki/Logging#console-output-configuration) ↩


Name  |  Name  |


  Installation  

You can install the demos locally or use the provided docker file.


One of the simplest actions is to include another launch description. This
launch description is processed in its entirety, including parsing of any
launch descriptions it includes recursively. Therefore processing of launch
descriptions is in order, and depth first.


If the launch system itself receives the ` SIGTERM ` signal it will send the `
SIGKILL ` signal to all child processes and exit immediately.


Lastly, a container process API may be defined by ROS services or topics.


Date Written: 2019-09


In ROS 2, Windows has been added to the list of targeted platforms, and as of
the writing of this document it does not support SSH natively. So unless that
changes (more possible than it sounds), a different, more portable mechanism
might be required to support this feature everywhere. At the very least, an
alternative solution would need to be used on Windows even if SSH was still
used on Unix-like operating systems.


####  Termination


In ROS 1, ` rostest ` is an important extension of ` roslaunch ` , and so far
in ROS 2 we’re already using the foundation of launching (executing processes
and reacting to their exit, return codes, and stdout/stderr), called `
ros2/launch_testing ` right now, to implement some tests. This section will
cover how that happens and how it integrates with the static description files
as well as the programmatic API, adding ROS specific concepts to what we’re
already doing with ` ros2/launch_testing ` .


##  Folders and files


Even though there is only one node in the process, that node does not need to
start when the process starts, nor does the process need to end when the node
is shutdown and/or destroyed. If it is a managed node, the lifecycle of the
node is best tracked using the lifecycle events. In fact, a process with a
single node could start a node, run for a while, later destroy it, and then
create it again.


It should be possible for users of the launch system send events, in addition
to the system being able to do so itself.


>   1. ` <include> ` s: you can easily include other .launch files and also
> assign them a namespace so that their names do not confict with yours.
>


  Using Docker  

First, build the dockerfile with

    mkdir -p ~/ros2_ws/src
    cd ~/ros2_ws/src
    git clone https://github.com/ros-controls/ros2_control_demos
    cd ros2_control_demos
    docker build . -t ros2_control_demos -f Dockerfile/Dockerfile


  Build from debian packages  

Download the ` ros2_control_demos  ` repository and install its dependencies
with

    mkdir -p ~/ros2_ws/src
    cd ~/ros2_ws/src
    git clone https://github.com/ros-controls/ros2_control_demos -b master
    cd ~/ros2_ws/
    rosdep update --rosdistro=$ROS_DISTRO
    sudo apt-get update
    sudo rosdep install --from-paths ./ -i -y --rosdistro ${ROS_DISTRO}

Now you can build the repository (source your ROS 2 installation first)

    cd ~/ros2_ws/
    . /opt/ros/${ROS_DISTRO}/setup.sh
    colcon build --merge-install


[ ros2_control_demos-not-released.humble.repos ](/ros-
controls/ros2_control_demos/blob/humble/ros2_control_demos-not-
released.humble.repos "ros2_control_demos-not-released.humble.repos")


#  ros-controls/ros2_control_demos


The system is described in parts which we’ll refer to here as “Launch
Descriptions”. Launch descriptions are made of up of an ordered list of
actions and groups of actions. It may also contain substitutions throughout
the description, which are used to add some flexibility and configuration to
the descriptions in a structured way.


The following examples are part of this demo repository:


While there will be standard container processes, custom container processes
would allow using custom executors or client libraries. Therefore, there must
be a container process API for the launch system to communicate which nodes
should be loaded.


[ example_7 ](/ros-controls/ros2_control_demos/tree/humble/example_7
"example_7")


For ROS2 Humble:


Another way to categorize events is by their source.


    source /opt/ros/foxy/setup.bash
    cd ~/ros2_ws
    source install/setup.bash
    ros2 launch meili_agent meili_agent.launch.py


4. [ https://en.wikipedia.org/wiki/Calling_convention ](https://en.wikipedia.org/wiki/Calling_convention) ↩


###  Process with Multiple Nodes


However, as an example of a process with multiple nodes, consider a program
that instantiates two camera driver nodes called “camera1” and “camera2” by
default. You could configure their namespaces separately by doing something
like ` camera1:__ns:=left camera2:__ns:=right ` .


[ Activity  ](/ros-controls/ros2_control_demos/activity)


How Composable nodes are registered is not defined by this document. Instead,
the container process is responsible for knowing how to find nodes it is asked
to load. For example, a container process might use pluginlib for rclcpp
nodes, or python entry points for rclpy nodes.


#####  Registration of Composable Nodes


This section of the article covers the event subsystem within the launch
system, which is responsible for generating events and reporting them to users
and itself so that those events can be handled.


If it is possible to load multiple nodes in parallel, then it needs to be
decided how to load the nodes. The container process should load nodes as soon
as it is asked. It should be up to the launch system to decide whether to load
nodes in parallel or sequentially. If multiple nodes of the same type are to
be launched, then the launch system should load the nodes sequentially so each
is able to remap it’s name before the next is loaded. If they are of different
types then the launch system may choose to try to load them in parallel, where
the exact order they get loaded is determined by chance or the container
process.


By Solution


In Development

     [ Master ](index.html)


  To view the robot  

Docker now allows us to run the demo without the GUI if configured properly.
Now we can view the robot by the following procedure:

After having [ ROS 2 installed
](https://docs.ros.org/en/rolling/Installation.html) on your local system (not
inside the docker), we can use ` rviz2  ` to visualize the robot state and `
joint_state_publisher_gui  ` package to give manual joint values to the robot.
To install the package you can run:

    sudo apt-get install -y ros-${ROS_DISTRO}-joint-state-publisher-gui ros-${ROS_DISTRO}-rviz2

Then we are ready to bring up all the components to view the robot. Let’s
start with the docker container by running the following command:

    docker run -it --rm --name ros2_control_demos --net host ros2_control_demos ros2 launch ros2_control_demo_example_1 view_robot.launch.py gui:=false

Note

Depending on your machine settings, it might be possible that you have to omit
` --net  host  ` .

Now, we need to start ` rviz2  ` to view the robot as well as `
joint_state_publisher_gui  ` , each in their own terminals after sourcing our
ROS 2 installation.

Terminal 1:

    source /opt/ros/${ROS_DISTRO}/setup.bash
    ros2 run joint_state_publisher_gui joint_state_publisher_gui


Events produced by the event subsystem of the launch system can fall broadly
into two categories: events that only the launch system can directly observe
and events that the launch system may relay for convenience but is directly
observable by other systems too. Therefore, the events that only the launch
system can observe must be exposed via the event system if we want them to be
used by other applications or users.


For these, the launch system needs to know how to execute them, and to do that
it needs:


###  Footer navigation


##  About


* Example 3: [ "RRBot with multiple interfaces" ](/ros-controls/ros2_control_demos/blob/humble/example_3)


Termination of a ROS Node (the node, not the process) is not externally
observable beyond what is observed with an  operating system process  (the
return code).


  * README
  * License


* Example 14: [ "Modular robots with actuators not providing states and with additional sensors" ](/ros-controls/ros2_control_demos/blob/humble/example_14)


[ Please Login to View Contributors
](https://github.com/login/oauth/authorize?client_id=efa6dd8eae9106381720)


The important files to check in each example are:


[ doc ](/ros-controls/ros2_control_demos/tree/humble/doc "doc")


Basic actions include being able to:


This is the only option discussed which can communicate the success or failure
of dynamically launched nodes. It is also the only option that allows
introspection. However, this option has the highest potential delay from when
the container process is spawned to when nodes may be loaded.


TODO:


The previous subsection dealt with what may be different for the launch system
in ROS 2, but in this subsection the similarities will be enumerated (not
necessarily exhaustively). The launch system in ROS 2 will:


Managed ROS Nodes have some additional observable effects when terminating
(the node, not necessarily the process containing it). A managed node enters
the ` Finalized ` state after passing through the ` ShuttingDown ` transition
state on termination. Since these are state transitions, they are observable
via the lifecycle event system, at least through the ROS topic `
lifecycle_state ` (subject to change, always reference the managed nodes
design document  3  ).


* [ Pricing ](/pricing)


##  Separation of Concern


  * [ Notifications ](/login?return_to=%2Fros-controls%2Fros2_control_demos)
  * [ Fork  165  ](/login?return_to=%2Fros-controls%2Fros2_control_demos)
  * [ Star  330  ](/login?return_to=%2Fros-controls%2Fros2_control_demos)


[ .github ](/ros-controls/ros2_control_demos/tree/humble/.github ".github")


  * include another launch description
  * modify the launch system configurations at the current scope
  * execute a process
  * register/unregister an event handler
  * emit an event
  * additional actions defined by extensions to the launch system


This API could have very low latency to launch nodes since it does not require
waiting for discovery. However, there is no way to get feedback about the
success or failure of loaded nodes. There is also no way to tell a container
process to unload a composable node.


Any of the entities based on an  operating system process  can be made into a
remote  operating system process  by simply adding the requirement information
needed to gain access to the other machine and execute it. This is a feature
that ROS 1’s ` roslaunch ` has, and is useful in multi machine robots.


RFC:


These parameters have the default values that are shown below but can be
modified by the user using the corresponding command line( if you want to
modify more than one parameter, just add all of them when launching a Meili
Agent). It is also possible to open the meili_agent.launch file and modify the
values inside the file so that the modified values will be saved for the next
time.


  * ` bringup/launch/<example_name>.launch.py ` \- launch file for the example
  * ` bringup/config/<example_name>_controllers.yaml ` \- parameters with controllers' setup for the example.
  * ` description/<example_name>.ros2_control.xacro ` \- XACRO file with ` ros2_control ` -URDF-tag with hardware setup and parameters.
  * ` description/<example_name>.urdf.xacro ` \- the main description for for the example used to generate URDF on the fly that is published on the ` /robot_description ` topic.
  * ` hardware/<example_name>.hpp ` \- header file of the example hardware component implementation.
  * ` hardware/<example_name>.cpp ` \- source file with the example hardware component implementation.
  * ` controllers/<example_name>.hpp ` \- header file of the example controller implementation.
  * ` controllers/<example_name>.cpp ` \- source file with the example controller implementation.


Other kinds of event handlers could be supported by building on a locally
defined function. They could be something like a user-defined “lambda” defined
in the description of the launch file, or even a built-in event handler
function which just publishes the events as ROS messages. In the latter case,
it could be either be a subscription to a topic (which needs no a priori
registration with the launch system) or a service call (which was registered
with the launch system a priori). So if it is a topic, the subscription
object, with its callback, could be considered an event handler. In the case
of a service, which would be called by the launch system and handled by a user
defined service server, the service server (and it’s response) would be
considered the event handler.


Changes to the local state by included launch descriptions persist, as they
should be thought of as truly included in the same file, as if you had copied
the contents of the included launch description in place of the include
action. To avoid this, a group without a namespace could be used to produce a
push-pop effect on the launch configurations.


[ example_12 ](/ros-controls/ros2_control_demos/tree/humble/example_12
"example_12")


Any event handler can be added to an event filter, but “pure event sinks” are
unable to accept an event, e.g. things like a ROS topic. This is because there
is no feedback mechanism, i.e. a subscription to a topic has no way of
indicating if an event has been accepted or rejected as it does not have a
return type. Whereas, other event handlers which are functions or lambda’s
withing the launch system itself or ROS service calls can have a return type
and therefore can accept or reject an event.


Most users of ` roslaunch ` from ROS 1 used it by defining a static XML
description of what they wanted executed and which parameters they wanted to
set. There is an API for ` roslaunch ` in ROS 1, but in our experience few
people use this interface. We can only speculate as to why, but the API is not
very well documented and is not prevalent in the tutorials and examples.
Sticking strictly to the XML description has caused two different approaches
to dynamic behavior/configuration to become more popular:


This commit does not belong to any branch on this repository, and may belong
to a fork outside of the repository.


###  Categories of Events by Source


####  Dynamically loading Nodes


  * can be broken into:
    * “namespace” (like roslaunch),
    * conditionals ( ` if ` and ` unless ` ) (see: https://wiki.ros.org/roslaunch/XML#if_and_unless_attributes), and
    * scope (push-pop for configurations)
    * should consider what we’re discussing to do in https://github.com/ros2/launch/issues/313


This repository provides examples for functionalities and capabilities of `
ros2_control ` framework. It consists of simple implementations that
demonstrate different concepts. Choose the right branch of this repository
matching you ROS 2 distribution as well as the full documentation on [
control.ros.org ](https://control.ros.org) , see  this table  .


##  Calling Conventions


TODO: figure out what we need to do here in terms of portability and
configuration


Contributors


This is a proposal for an API a launch system will use to interact with
container processes.


    * True: Traffic control algorithms will be applied when more than one task is on.
    * False: Default value. No path will be streamed and no traffic control algorithms.
  6. **offline** : Indicates if offline mode is activated in the agent.


In ` roslaunch ` from ROS 1 there were only a few ways that it could react to
changes in the system, and they were both related to a process “dieing”
(either a clean or unclean exit):


Resources


####  Termination


##  Parameters  #


While event handlers have no comparison operators between one another (so no
sorting), the order of delivery of events to event handlers should be
deterministic and should be in the reverse order of registration, i.e. “first
registered, last delivered”. Note that delivery to asynchronous event handlers
(e.g. a subscription to a ROS topic for events, sent via a ROS publisher),
will be sent in order, but not necessarily delivered in order.


Code


[ example_8 ](/ros-controls/ros2_control_demos/tree/humble/example_8
"example_8")


Actions may be one of several things, and each action has a type (associated
with the action’s function) and may also contain arbitrary configurations.
Actions represent an intention to do something, but a launch description is
parsed first, then actions are taken in order of definition later. This allows
actions to be interpreted and then statically introspected without actually
executing any of them unless desired.


* Example 12: [ "Controller chaining" ](/ros-controls/ros2_control_demos/blob/humble/example_12)


  * Requires parsing a config
  * Cannot tell from the outside if a container process supports this interface
  * Cannot tell if and when nodes are loaded or unloaded
  * Cannot stop dynamically loaded nodes from reading STDIN


In all cases, the desired behavior may be achieved though selective use of
optionally scoped group actions.


[ example_10 ](/ros-controls/ros2_control_demos/tree/humble/example_10
"example_10")


####  Static Description and Programmatic API


  * Open
  * Closed


[ .clang-format ](/ros-controls/ros2_control_demos/blob/humble/.clang-format
".clang-format")


[ Search syntax tips ](https://docs.github.com/search-github/github-code-
search/understanding-github-code-search-syntax)


##  References


  * launch nodes
  * launching nodes remotely via SSH
  * setting parameters on the parameter server
  * automatic respawning of processes that die
  * static, XML based description of the nodes to launch, parameters to set, and where to run them


Temporary summary:


|

View all files

##  Repository files navigation


####  Execution


Since there is only one ROS node, the command line arguments do not need to be
explicit about to which node they apply. For example, changing the namespace
of the single node could be expressed with the command line argument `
__ns:=new_namespace ` .


1. Binary builds - against released packages (main and testing) in ROS distributions. Shows that direct local build is possible.


**NOTE** \- The structure of packages, folders and files given in this
repository is not recommended to be used for your robot. Usually you should
have all of the above folders defined as separate packages with naming
convention ` <robot_name_or_type>/[bringup|description|hardware|controllers] `
. More standard structure can be found in [ ros_control_boilerplate
](https://github.com/PickNikRobotics/ros_control_boilerplate) repository from
Dave Coleman or documentation on [ ros_team_workspace
](https://rtw.stoglrobotics.de/master/guidelines/robot_package_structure.html)
from Stogl Robotics.


Missing from this list is the user which should be used to execute the
process. It’s possible that it would be necessary or at least useful to change
the user based on the launch description. However, it can always be done in a
user written script and supporting it in our Python implementation in a
portable way looks to be difficult.


* Example 4: [ "Industrial robot with integrated sensor" ](/ros-controls/ros2_control_demos/blob/humble/example_4)


Explore


[ example_12 ](/ros-controls/ros2_control_demos/tree/humble/example_12
"example_12")


####  Runtime


##  [ Contributors  48  ](/ros-
controls/ros2_control_demos/graphs/contributors)


Code
Issues
19
Pull requests
4
Actions
Projects
Security
Insights
Files
Go to file
t
.github
Dockerfile
doc
example_1
bringup
description
doc
hardware
test
CMakeLists.txt
README.md
package.xml
ros2_control_demo_example_1.xml
example_10
example_11
example_12
example_14
example_2
example_3
example_4
example_5
example_6
example_7
example_8
example_9
ros2_control_demo_description
ros2_control_demos
.clang-format


[ \+ 34 contributors ](/ros-controls/ros2_control_demos/graphs/contributors)


The example shows a simple chainable controller and its integration to form a
controller chain to control the joints of _RRBot_ .


This action will take a few required arguments, a few optional requirements,
and also take settings from the launch system configurations if they’re not
explicitly given. The signature of this action should be similar to the API of
Python’s ` subprocess.run ` function  7  . Basically taking things like the
executable file, arguments, working directory, environment, etc. as input and
reporting the return code, stdout and stderr, and any errors as emitted
events.


* Example 11: [ "Car-like robot using steering controller library" ](/ros-controls/ros2_control_demos/blob/humble/example_11)


######  API using Command Line Configuration File


####  Relationship Between Nodes and Processes


[ control.ros.org ](https://control.ros.org "https://control.ros.org")


It’s often the case that you need to express the location of a file when
describing your system to the launch system, whether it be an executable to
run, a file to be passed as an argument, or a file from which to load
parameters. In the launch system for ROS 2, like the launch system for ROS 1
the concept of packages is used to group related resources and programs
together to make this easier, but it will also support some other kinds of
relative paths (other than just package share folders). But where ROS 1 and
ROS 2 differ in this topic is how the packages will be found, which folders a
package can be associated with, and therefore probably also the syntax for how
to get that relative path.


The launch system may initiate the termination of an  operating system process
. This starts with the signaling of ` SIGINT ` on the child process. If this
does not result in the termination of the process, then one of a few things
can happen based on the configuration of the launch system:


* Example 9: [ "Gazebo classic simulation" ](/ros-controls/ros2_control_demos/blob/humble/example_9)


Included launch descriptions inherit all configurations of the current launch
description, and any changes to the launch system configurations made in the
included launch description will affect actions after the include action.


The launch system in ROS is responsible for helping the user describe the
configuration of their system and then execute it as described. The
configuration of the system includes what programs to run, where to run them,
what arguments to pass them, and ROS specific conventions which make it easy
to reuse components throughout the system by giving them each different
configurations. Also, because the launch system is the process (or the set of
processes) which executes the user’s processes, it is responsible for
monitoring the state of the processes it launched, as well as reporting and/or
reacting to changes in the state of those processes.


[ ros2_control_demos ](/ros-
controls/ros2_control_demos/tree/humble/ros2_control_demos
"ros2_control_demos")


[ .gitignore ](/ros-controls/ros2_control_demos/blob/humble/.gitignore
".gitignore")


Temporary summary:


  To run the ros2_control demos  

The following command runs the demo without the GUI:

    docker run -it --rm --name ros2_control_demos --net host ros2_control_demos

Note

Depending on your machine settings, it might be possible that you have to omit
` --net  host  ` .

Then on your local machine, you can run rviz2 with the config file specified:

    cd ~/ros2_ws
    source /opt/ros/${ROS_DISTRO}/setup.sh
    rviz2 -d src/ros2_control_demos/example_1/description/rviz/rrbot.rviz

You can also run other commands or launch files from the docker, e.g.

    docker run -it --rm --name ros2_control_demos --net host ros2_control_demos ros2 launch ros2_control_demo_example_2 diffbot.launch.py


Also, every executed process will automatically setup a few event handlers, so
that the user can emit events to ask the launch system to terminate the
process (following the signal escalation described in previous sections),
signal the process explicitly, or write to the ` stdin ` of the process. More
sophisticated calling conventions which are based on the “  operating system
process  ” may include other default event handlers.


[ 233 Commits  ](/ros-controls/ros2_control_demos/commits/humble/)


However, these events can be more specific to the launch system, like when a
launch description is included, or when the launch system needs to shutdown.
These events might also contain pertinent information like why a launch
description was included, e.g. given as an argument to the launch system,
included by another launch file, requested to be included by asynchronous
request (maybe via a ROS service call), or in the case of a shutting down
event, maybe why the launch system is shutting down, e.g. a required process
exited, or it received the SIGINT signal.


    * [ Enterprise ](/enterprise)
    * [ Teams ](/team)
    * [ Startups ](/enterprise/startups)
    * [ Education  ](https://education.github.com)


[ Apache-2.0 license ](/ros-controls/ros2_control_demos/blob/master/LICENSE)


The purpose of the following sections is to enumerate what the launch system
could do and the things with which it could interact, but is not the
requirements list for the launch system in ROS 2. The requirements for the
launch system will be enumerated in section below based on what’s possible in
these sections.


Since you can have many nodes per process in ROS 2, it is no longer necessary
to conflate nodes and processes. Due to this, the design and documentation for
the launch system in ROS 2 will need to be clearer when talking about
processes and nodes. Additionally, the way that configuration (e.g. parameters
and remappings) get passed to nodes by the launch system needs to be adapted,
though this part overlaps with the design documents for static remapping  1
and for parameters  2  .


  *[
       operating system processes
      ]: Operating System Processes
  *[
       operating system process
      ]: Operating System Process


[ aruco_visual_marker_5
](/joselusl/aruco_gazebo/tree/master/aruco_visual_marker_5
"aruco_visual_marker_5")


|  virtual ~ [ Marker ](classignition_1_1rendering_1_1Marker.html) |  (  |  |
)  |
---|---|---|---|---
virtual

Destructor.


called for each object in a scene just before rendering, which can be achieved
by a single call to [ Scene::PreRender
](classignition_1_1rendering_1_1Scene.html#adffb56e0e545fefebf96b36f295396e9
"Prepare scene for rendering. The scene will flushing any scene changes by
traversing scene-graph...") . [ More...
](classignition_1_1rendering_1_1Object.html#adffb56e0e545fefebf96b36f295396e9)

virtual [ ScenePtr
](namespaceignition_1_1rendering.html#aa53c2652ba6a30e89d915fc8847dcc47) |  [
Scene
](classignition_1_1rendering_1_1Object.html#a7483c1d44b5981eacd31fe5ac8332e10)
() const =0
|  Get the [ Scene ](classignition_1_1rendering_1_1Scene.html "Manages a
single scene-graph. This class updates scene-wide properties and holds the
root scene node...") that created this object. [ More...
](classignition_1_1rendering_1_1Object.html#a7483c1d44b5981eacd31fe5ac8332e10)

##  Protected Member Functions

---
|  [ Marker
](classignition_1_1rendering_1_1Marker.html#a98e5d6711036ca1c99d0294ecbd2be43)
()

##  Detailed Description


A marker geometry class. The marker's visual appearance is based on the marker
type specified.


[ Dronecode ](https://www.dronecode.org/)


[ none ](/questions/scope:all/sort:activity-desc/tags:none/page:1/) ×


Thanks, that would be an idea for the camera problem, I’ll give that a try.
Unfortunately, it still leaves one problem.
The Typhoon has a gimbal camera that corrects any swaying of the drone, but
most downward cameras for object recognition are fixed (so is mine). When the
drone tilts or rolls, the camera center moves and the detected distance to the
marker changes, though the drone hasn’t moved. You can correct that by getting
the roll and tilt angles of the drone, turning them into rotation matrices and
rotate the camera frame back into the drone body frame, which points straight
towards earth. However, this important effect cannot be simulated here.


Thanks.


For


[ Docs ](https://www.dronecode.org/documentation/)


Seen: **1,631 times**


Aruco Visual Markers for Gazebo Simulator


[ Powered by Askbot version 0.7.58 ](http://askbot.com)


Implemented in [ OgreMarker
](classignition_1_1rendering_1_1OgreMarker.html#a3e30032650ac7ec55afbd3e74978ad48)
, [ Ogre2Marker
](classignition_1_1rendering_1_1Ogre2Marker.html#a3e30032650ac7ec55afbd3e74978ad48)
, [ BaseMarker< T >
](classignition_1_1rendering_1_1BaseMarker.html#adbdf8a4bc5454664ee09c0e21113d97d)
, [ BaseMarker< Ogre2Geometry >
](classignition_1_1rendering_1_1BaseMarker.html#adbdf8a4bc5454664ee09c0e21113d97d)
, and [ BaseMarker< OgreGeometry >
](classignition_1_1rendering_1_1BaseMarker.html#adbdf8a4bc5454664ee09c0e21113d97d)
.


##  ◆  SetPoint()


|  [ Ask Your Question ](/questions/ask/)
---|---|---|---

1


add a comment


[ MAVLink ](https://mavlink.io/en/)


Hey,
You can use Typhoon H480 which already has a camera and add your aruco marker
intro your Gazebo world. But you may need to play around a bit to make the
world changes in Gazebo.


     [in]  |  _index  |  The index of the point
---|---|---
[in]  |  _value  |  The new positional vector of the point

Implemented in [ BaseMarker< T >
](classignition_1_1rendering_1_1BaseMarker.html#ae1638b8733af1e2bca74028b083b246c)
, [ BaseMarker< Ogre2Geometry >
](classignition_1_1rendering_1_1BaseMarker.html#ae1638b8733af1e2bca74028b083b246c)
, [ BaseMarker< OgreGeometry >
](classignition_1_1rendering_1_1BaseMarker.html#ae1638b8733af1e2bca74028b083b246c)
, [ OgreMarker
](classignition_1_1rendering_1_1OgreMarker.html#a540c2bad49688568489ca361c7fbd485)
, and [ Ogre2Marker
](classignition_1_1rendering_1_1Ogre2Marker.html#a540c2bad49688568489ca361c7fbd485)
.


Marker-like functionality in Gazebo


](classignition_1_1rendering_1_1Geometry.html#a66d129c0b38f7dee5d094834ffc8c116)

virtual void  |  [ RemoveParent
](classignition_1_1rendering_1_1Geometry.html#af5090c35413cf7de0900aee61624dd36)
()=0
|  Detach this [ Geometry ](classignition_1_1rendering_1_1Geometry.html
"Represents a geometric shape to be rendered. ") from its parent [ Visual
](classignition_1_1rendering_1_1Visual.html "Represents a visual node in a
scene graph. A Visual is the only node that can have Geometry and other...") .
If this [ Geometry ](classignition_1_1rendering_1_1Geometry.html "Represents a
geometric shape to be rendered. ") does not have a parent, no work will be
done. [ More...
](classignition_1_1rendering_1_1Geometry.html#af5090c35413cf7de0900aee61624dd36)

virtual void  |  [ SetMaterial
](classignition_1_1rendering_1_1Geometry.html#afd79acea6227187a9da38b3196bd7aef)
(const [ std::string
](http://en.cppreference.com/w/cpp/string/basic_string.html) &_name, bool
unique=true)=0
|  Set the materials of this [ Geometry
](classignition_1_1rendering_1_1Geometry.html "Represents a geometric shape to
be rendered. ") . The specified material will be retrieved from the parent [
Scene ](classignition_1_1rendering_1_1Scene.html "Manages a single scene-
graph. This class updates scene-wide properties and holds the root scene
node...") . If no material is registered by the given name, no work will be
done. [ More...
](classignition_1_1rendering_1_1Geometry.html#afd79acea6227187a9da38b3196bd7aef)

virtual void  |  [ SetMaterial
](classignition_1_1rendering_1_1Geometry.html#adb4793f0896c89c61a7927bb60ea9955)
( [ MaterialPtr
](namespaceignition_1_1rendering.html#a0a1c61d9d22ae1ff35852e769030b0e4)
_material, bool unique=true)=0
|  Set the materials of this [ Geometry
](classignition_1_1rendering_1_1Geometry.html "Represents a geometric shape to
be rendered. ") . [ More...
](classignition_1_1rendering_1_1Geometry.html#adb4793f0896c89c61a7927bb60ea9955)

![-](closed.png) Public Member Functions inherited from [ Object
](classignition_1_1rendering_1_1Object.html)


##  Footer


{{ message }}


##  Member Function Documentation


##  [ Packages  0  ](/users/joselusl/packages?repo_name=aruco_gazebo)


  * [ Home ](/)
  * [ Categories ](/categories)
  * [ FAQ/Guidelines ](/guidelines)
  * [ Terms of Service ](/tos)
  * [ Privacy Policy ](/privacy)


[ ffurrer ](/users/28/ffurrer/)
349  ●  6  ●  12  ●  18


* README


[ blank-supportgis  ](https://discuss.px4.io/u/blank-supportgis) September 23,
2022, 1:16pm  3


[ Peter Mitrano ](/users/1068/peter-mitrano/) ![flag of United States of
America](/m/default/media/images/flags/us.gif?v=2)
768  ●  12  ●  21  ●  31  [ http://petermitrano.gi...
](http://petermitrano.github.io/ "Peter Mitrano's website is
http://petermitrano.github.io/")


##  ◆  Marker()


[ Search syntax tips ](https://docs.github.com/search-github/github-code-
search/understanding-github-code-search-syntax)


##  ◆  Type()


  * [ Terms ](https://docs.github.com/site-policy/github-terms/github-terms-of-service)
  * [ Privacy ](https://docs.github.com/site-policy/privacy-policies/github-privacy-statement)
  * [ Security ](/security)
  * [ Status ](https://www.githubstatus.com/)
  * [ Docs ](https://docs.github.com/)
  * [ Contact ](https://support.github.com?tags=dotcom-footer)
  * Manage cookies
  * Do not share my personal information


##  ◆  AddPoint()  [2/2]


[ Activity  ](/joselusl/aruco_gazebo/activity)


     [in]  |  _lifetime  |  The time at which the marker will be removed
---|---|---

Implemented in [ BaseMarker< T >
](classignition_1_1rendering_1_1BaseMarker.html#a80f6398e2697a75863596c190090cb4d)
, [ BaseMarker< Ogre2Geometry >
](classignition_1_1rendering_1_1BaseMarker.html#a80f6398e2697a75863596c190090cb4d)
, and [ BaseMarker< OgreGeometry >
](classignition_1_1rendering_1_1BaseMarker.html#a80f6398e2697a75863596c190090cb4d)
.


Include my email address so I can be contacted


The layer of the marker


Cancel  Create saved search


* [ Pricing ](/pricing)


() const =0
|  Get the render type of this [ Marker
](classignition_1_1rendering_1_1Marker.html "A marker geometry class. The
marker's visual appearance is based on the marker type specified...") .
More...

![-](closed.png) Public Member Functions inherited from [ Geometry
](classignition_1_1rendering_1_1Geometry.html)
virtual  |  [ ~Geometry
](classignition_1_1rendering_1_1Geometry.html#af23026f6b196240a471f6e7a33581e4d)
()
|  Destructor. [ More...
](classignition_1_1rendering_1_1Geometry.html#af23026f6b196240a471f6e7a33581e4d)

virtual bool  |  [ HasParent
](classignition_1_1rendering_1_1Geometry.html#a678e6abd59399644e7ea9d662e3be598)
() const =0
|  Determine if this [ Geometry ](classignition_1_1rendering_1_1Geometry.html
"Represents a geometric shape to be rendered. ") is attached to a [ Visual
](classignition_1_1rendering_1_1Visual.html "Represents a visual node in a
scene graph. A Visual is the only node that can have Geometry and other...") .
[ More...
](classignition_1_1rendering_1_1Geometry.html#a678e6abd59399644e7ea9d662e3be598)

virtual [ MaterialPtr
](namespaceignition_1_1rendering.html#a0a1c61d9d22ae1ff35852e769030b0e4) |  [
Material
](classignition_1_1rendering_1_1Geometry.html#ae2ed76cde5778787639fe85041dee5ce)
() const =0
|  Get the material of this geometry. [ More...
](classignition_1_1rendering_1_1Geometry.html#ae2ed76cde5778787639fe85041dee5ce)

virtual [ VisualPtr
](namespaceignition_1_1rendering.html#ad78e0f29088d161daa274afdee08ade0) |  [
Parent
](classignition_1_1rendering_1_1Geometry.html#a66d129c0b38f7dee5d094834ffc8c116)
() const =0
|  Get the parent [ Visual ](classignition_1_1rendering_1_1Visual.html
"Represents a visual node in a scene graph. A Visual is the only node that can
have Geometry and other...") . [ More...


  Textures

* * *

We are jumping now to a different topic. We are going to create a model for
the visual marker that our robot will later follow. If we were to do such a
thing in reality, we would probably look for a surface where we would stick
the marker on. We’ll do something similar in gazebo.

Technically, we are going to apply a texture to an object. We have seen this
before in our example world. This is how the tile pattern was put on the
walls.

![textures](https://nlamprian.me/assets/img/blog/2020-01-27-visual-servoing-
in-gazebo/textures.png)

A texture, in its simplest form, is an image which is applied on each face of
a geometry. The image is streched in order to cover an entire face. This is
why, in the figure above, we see that the longer a wall gets, the longer and
blurrier the tiles become.

Let’s now look into the marker itself. We’ll use an ArUco marker. For the
purpose of this tutorial, we only need to know that this is a marker which can
be observed with a 2D camera, and have its 3D pose within the world extracted
from the image.

![marker](https://nlamprian.me/assets/img/blog/2020-01-27-visual-servoing-in-
gazebo/marker.png)

If we visit _[ chev.me/arucogen ](http://chev.me/arucogen/) _ , we can get an
image by specifying a marker id and size. The shape of the image will dictate
the shape of the geometry in the SDF model. The model is just a link with the
usual visual and collision descriptions. The new addition here is the material
section within the visual. A material is defined by a script and an image. The
script is read by the rendering engine in order to configure and apply the
texture.

This is what the visual description with the material looks like:


##  Use saved searches to filter your results more quickly


[ aruco_visual_marker_1_pad
](/joselusl/aruco_gazebo/tree/master/aruco_visual_marker_1_pad
"aruco_visual_marker_1_pad")


Search or jump to...


Additional navigation options


|  virtual void SetLifetime  |  (  |  const
std::chrono::steady_clock::duration & |  __lifetime_ |  )  |
---|---|---|---|---|---
pure virtual

Set the lifetime of this [ Marker ](classignition_1_1rendering_1_1Marker.html
"A marker geometry class. The marker's visual appearance is based on the
marker type specified...") .


[ ![Gazebo logo](/upfiles/gazebo_logo_1.png) ](/questions/)


` #include < [ ignition/rendering/Marker ](Marker_8hh_source.html) > `


##  History


[ mwbb  ](https://discuss.px4.io/u/mwbb) September 22, 2022, 5:32am  2


I’d like to use Gazebo to simulate this, e.g. by adding a simple camera to the
Iris drone and a marker at the bottom. However, there are 2 problems:


[ Sign up
](/signup?ref_cta=Sign+up&ref_loc=header+logged+out&ref_page=%2F%3Cuser-
name%3E%2F%3Crepo-name%3E&source=header-
repo&source_repo=joselusl%2Faruco_gazebo)


[ ![](https://github.com/Dronecode/dronecode-wordpress-
theme/raw/master/dronecode-salient-
child/images/dronecode_top_bar_logo_small.png) ](https://www.dronecode.org/)


Returns


add a comment


Last commit message


1 follower


The render type of the marker


[ Star  ](/login?return_to=%2Fjoselusl%2Faruco_gazebo)


###  Watchers


[ PX4 ](http://px4.io/)


The site is read-only. Please transition to use Robotics Stack Exchange


Is there a simple description or tutorial on how to extend the [ Gazebo
simulations ](https://docs.px4.io/main/en/simulation/gazebo.html) with a
simple downward facing camera that externally acts as a USB camera.


|  virtual void AddPoint  |  (  |  const [ ignition::math::Vector3d
](https://ignitionrobotics.org/api/math/6.8/namespaceignition_1_1math.html#a1f05093f5ee1a9ecdd54476792e4c206)
& |  __pt_ ,
---|---|---|---
|  |  const [ ignition::math::Color
](https://ignitionrobotics.org/api/math/6.8/classignition_1_1math_1_1Color.html)
& |  __color_
|  )  |  |
pure virtual

Add a point with its respective color to the marker.


[ aruco_visual_marker_2
](/joselusl/aruco_gazebo/tree/master/aruco_visual_marker_2
"aruco_visual_marker_2")


[ subscribe to rss feed ](/feeds/question/14518/ "subscribe to the rss feed")


Implemented in [ BaseMarker< T >
](classignition_1_1rendering_1_1BaseMarker.html#aef350bbc86c74fd1903d570d2270d2a3)
, [ BaseMarker< Ogre2Geometry >
](classignition_1_1rendering_1_1BaseMarker.html#aef350bbc86c74fd1903d570d2270d2a3)
, and [ BaseMarker< OgreGeometry >
](classignition_1_1rendering_1_1BaseMarker.html#aef350bbc86c74fd1903d570d2270d2a3)
.


* Open Source


[ ALL ](/questions/scope:all/sort:activity-desc/page:1/) [ UNANSWERED
](/questions/scope:unanswered/sort:answers-asc/page:1/)


[ ![nkoenig gravatar
image](//www.gravatar.com/avatar/7d7b669912eaa47178b36acdee3c72ad?s=32&d=identicon&r=PG)
](/users/5/nkoenig/)


Toggle navigation


#  Search code, repositories, users, issues, pull requests...


[ sandytf ](/users/2847/sandytf/)
11  ●  1  ●  1  ●  2


###  [ GitHub - mzahana/mavros_apriltag_tracking: This package implements
methods to... ](https://github.com/mzahana/mavros_apriltag_tracking)


  * [ List ](namespaces.html)
  * [ Members ](namespacemembers.html)
  * [ Functions ](namespacemembers_func.html)
  * [ Typedefs ](namespacemembers_type.html)
  * [ Variables ](namespacemembers_vars.html)
  * [ Enumerations ](namespacemembers_enum.html)
  * [ Enumerator ](namespacemembers_eval.html)


![](https://github.githubassets.com/favicons/favicon.svg) [ GitHub
](https://github.com/mzahana/mavros_apriltag_tracking)


* Product


[ **3** watching ](/joselusl/aruco_gazebo/watchers)


[ _insert_drive_file_ Tutorials ](tutorials.html) _library_books_ Classes
_toc_ Namespaces  [ _insert_drive_file_ Files ](files.html) [ _launch_
Ignition Website ](http://ignitionrobotics.org)


[ Report repository ](/contact/report-
content?content_url=https%3A%2F%2Fgithub.com%2Fjoselusl%2Faruco_gazebo&report=joselusl+%28user%29)


##  Stats


    * [ Learning Pathways  ](https://resources.github.com/learn/pathways/)
    * [ White papers, Ebooks, Webinars  ](https://resources.github.com/)
    * [ Customer Stories ](/customer-stories)
    * [ Partners  ](https://partner.github.com/)


[ aruco_visual_marker_0_pad
](/joselusl/aruco_gazebo/tree/master/aruco_visual_marker_0_pad
"aruco_visual_marker_0_pad")


[ aruco_visual_marker_1
](/joselusl/aruco_gazebo/tree/master/aruco_visual_marker_1
"aruco_visual_marker_1")


###  Stars


[ **asked 2016-09-28 08:43:37 -0500  ** ](/questions/14518/revisions/)


[ Sign in
](/login?return_to=https%3A%2F%2Fgithub.com%2Fjoselusl%2Faruco_gazebo)


[ aruco_visual_marker_2
](/joselusl/aruco_gazebo/tree/master/aruco_visual_marker_2
"aruco_visual_marker_2")


[ aruco_visual_marker_3
](/joselusl/aruco_gazebo/tree/master/aruco_visual_marker_3
"aruco_visual_marker_3")


[ blank-supportgis  ](https://discuss.px4.io/u/blank-supportgis) September 21,
2022, 4:22pm  1


[ **answered 2016-09-29 02:16:11 -0500  ** ](/answers/14522/revisions/)


[ joselusl ](/joselusl) /  **[ aruco_gazebo ](/joselusl/aruco_gazebo) **
Public


edit


##  ◆  Lifetime()


###  Forks


[ aruco_visual_marker_5_pad
](/joselusl/aruco_gazebo/tree/master/aruco_visual_marker_5_pad
"aruco_visual_marker_5_pad")


[ __ ](/questions/) |


|  virtual void ClearPoints  |  (  |  |  )  |
---|---|---|---|---
pure virtual

Clear the points of the marker, if applicable.


Nope, but you could add a model that has no physical properties.


  * [ Code  ](/joselusl/aruco_gazebo)
  * [ Issues  ](/joselusl/aruco_gazebo/issues)
  * [ Pull requests  ](/joselusl/aruco_gazebo/pulls)
  * [ Actions  ](/joselusl/aruco_gazebo/actions)
  * [ Projects  ](/joselusl/aruco_gazebo/projects)
  * [ Security  ](/joselusl/aruco_gazebo/security)
  * [ Insights  ](/joselusl/aruco_gazebo/pulse)


[ Support ](http://discuss.px4.io/)


  * [ Code  ](/joselusl/aruco_gazebo)
  * [ Issues  1  ](/joselusl/aruco_gazebo/issues)
  * [ Pull requests  1  ](/joselusl/aruco_gazebo/pulls)
  * [ Actions  ](/joselusl/aruco_gazebo/actions)
  * [ Projects  0  ](/joselusl/aruco_gazebo/projects)
  * [ Security  ](/joselusl/aruco_gazebo/security)
  * [ Insights  ](/joselusl/aruco_gazebo/pulse)


  Visual Servoing

* * *

We are done with the gazebo topics for today. It’s now time for a fun
application. We will make a waffle robot follow a burger robot with a marker.
The waffle version of turtlebot3 has a depth camera which also publishes RGB
images. If we start ` navigation.launch ` and give a goal to the robot, we can
observe the live stream from the camera in the bottom left corner of rviz. We
will use this camera to perceive the burger robot in the environment, and then
try to follow it. Let’s consider what needs to go into this experiment. We
have to:

  * spawn a waffle robot
  * spawn a burger robot, with a marker, that patrols an area
  * be able to detect an ArUco marker in an image and get its transformation
  * have a controller which implements a closed loop system that uses marker transformations as feedback in order to make the robot behave as described

We have already dealt with the first two points. What about detecting ArUco
markers? For this, we will use the [ ` aruco_detect `
](http://wiki.ros.org/aruco_detect) package. aruco_detect subscribes to a
camera topic, and looks for markers in the images it receives. If a marker is
detected, the node publishes its 3D transformation. All we have to do is
provide the right parameter values for our own setup, and then the node will
do the rest. Beware that the node is quite resource-intensive, and combined
with gazebo, they will starve your computer.

    <node name="aruco_detect" pkg="aruco_detect" type="aruco_detect">
      <param name="image_transport" value="compressed" />
      <param name="publish_images" value="true" />
      <param name="fiducial_len" value="0.15" />
      <param name="dictionary" value="0" />
      <param name="do_pose_estimation" value="true" />
      <param name="ignore_fiducials" value="" />
      <param name="fiducial_len_override" value="" />
      <remap from="/camera/compressed" to="/camera/rgb/image_raw/compressed" />
      <remap from="/camera_info" to="/camera/rgb/camera_info" />
    </node>


     [in]  |  _layer  |  Layer at which the marker will reside
---|---|---

Implemented in [ BaseMarker< T >
](classignition_1_1rendering_1_1BaseMarker.html#a8f016341c17389fdcfb0a73804ca8707)
, [ BaseMarker< Ogre2Geometry >
](classignition_1_1rendering_1_1BaseMarker.html#a8f016341c17389fdcfb0a73804ca8707)
, and [ BaseMarker< OgreGeometry >
](classignition_1_1rendering_1_1BaseMarker.html#a8f016341c17389fdcfb0a73804ca8707)
.


[ Notifications ](/login?return_to=%2Fjoselusl%2Faruco_gazebo)


[ __ tags ](/tags/) [ __ users ](/users/) [ __ badges ](/badges/)


Resources


  * [ Index ](classes.html)
  * [ List ](annotated.html)
  * [ Hierarchy ](hierarchy.html)
  * [ Members: All ](functions.html)
  * [ Members: Functions ](functions_func.html)
  * [ Members: Variables ](functions_vars.html)
  * [ Members: Typedefs ](functions_type.html)
  * [ Members: Enumerations ](functions_enum.html)
  * [ Members: Enumerator ](functions_eval.html)


[ ![sandytf gravatar
image](//www.gravatar.com/avatar/373ed81f77dc72643390cb4e7e05198d?s=32&d=identicon&r=PG)
](/users/2847/sandytf/)


Go to file


##  Constructor & Destructor Documentation


[ aruco_visual_marker_4_pad
](/joselusl/aruco_gazebo/tree/master/aruco_visual_marker_4_pad
"aruco_visual_marker_4_pad")


|

View all files

##  Repository files navigation


To see all available qualifiers, see our [ documentation
](https://docs.github.com/search-github/github-code-search/understanding-
github-code-search-syntax) .


[ Documentation ](https://www.dronecode.org/documentation/)


Skip to content


Code


1 Like


##  About


  Multi-Robot Simulation

* * *

In gazebo, we can spawn as many models as we want, and even multiples of each
one. We’ve seen this already in our example world, where we happened to have
two instances of a couple of models. So, we should be able, in the same way,
to spawn a second robot in the world, right? Not so quickly. Gazebo wouldn’t
complain if we did that, but the resulting configuration would be broken.
Let’s consider what would happen:

  * **cmd_vel topic** : both robots would listen to the same command topic and execute the same commands. A message aimed for one robot would get received by the other robot too
  * **sensor topics** : both robots would publish their sensor data to the same topics, thus creating sequences of conflicting information
  * **tf** : both robots would define the same base_footprint frame in tf, which would keep jumping between the two robot poses
  * **nodes** : any ROS nodes that rely on sensor data wouldn’t function properly, because of all of the above

Fortunately, this is easily fixable. We can configure our resources with
namespaces, and use a different namespace for each robot, such that there are
no conflicts anymore. Inside the robot launch files, we need to:

  * define everything within ` <group> ` tags with the name of the robot, ` <name> ` , as a namespace. This means any parameters we upload to the parameter server, and any nodes we run, will be under this namespace. E.g., ` /<name>/robot_description `
  * set the ` tf_prefix ` parameter with the name of the robot, ` <name> ` , as a value. This parameter will be picked up by some nodes and be prepended to any tf frames they are broadcasting. E.g., ` base_footprint ` becomes ` <name>/base_footprint `

There might be some nuances in the way we have to launch some of the nodes,
but the above two steps, in the most basic form, is all we have to do. Having
configured a robot bringup with namespaces, we can get a simulation with more
than one robot like so:

    <launch>
      <include file="$(find gazebo_ros)/launch/empty_world.launch">
        <arg name="world_name" value="$(find grobot_gazebo)/worlds/example.world" />
      </include>

      <include file="$(find grobot_bringup)/launch/<robot-bringup>.launch">
        <arg name="name" value="karl" />
      </include>

      <include file="$(find grobot_bringup)/launch/<robot-bringup>.launch">


  Model Constraints

* * *

Now that we have a model for the marker, we need to attach it to a robot so
that we get a moving target. It’s going to be pretty straightforward.

When we send an SDF description to gazebo and ask it to spawn a model, gazebo
creates all the necessary links and joints in order to reconstruct the model.
We have the possibility to do the same ourselves. That is, we can create a
joint between two links, and those links can even belong to two different
models. We can take advantage of this to create a fixed joint between the
robot and the marker, thus constraining the marker and having it move with the
robot.

We’ll keep it simple here and use an existing plugin to create the joint. We
haven’t talked about plugins yet, and we might revisit them in the future, but
basically, plugins are how we add functionality to gazebo. Plugins have a type
that affects their initialization and lifetime, but ultimately, they all
behave the same way. They wait for internal (gazebo) or external (ROS) events,
and they respond, for example, by actuating a joint in the world or publishing
a sensor message. If you are interested to know a bit more, you can have a
look at the [ Plugins 101
](http://gazebosim.org/tutorials/?tut=plugins_hello_world) tutorial.

The plugin we are going to use is the [ gazebo_ros_link_attacher
](https://github.com/mehditlili/gazebo_ros_link_attacher) . What the plugin
does is offer ROS services we can call to attach or detach a fixed joint to
two existing links. gazebo_ros_link_attacher is a world plugin. This means we
enable the plugin by adding its configuration in the description of a world.

    <world name='default'>
      ...
      <plugin name="ros_link_attacher_plugin" filename="libgazebo_ros_link_attacher.so" />
      ...
    </world>


Last updated: **Jan 31 '17**


You should really really just use RViz. I know it's annoying to have two
things running, but gazebo is really not meant to do visualization. It's going
to be far more painful to try to display it in gazebo.


Are there any plugins for Gazebo that provide functionality similar to the
Marker plugin for rviz? If not, I'll look into creating a visual plugin that
wraps the DynamicLines class to support ROS nodes creating dynamic and generic
geometric visualizations.


#  aruco_gazebo


[ aruco_visual_marker_6_pad
](/joselusl/aruco_gazebo/tree/master/aruco_visual_marker_6_pad
"aruco_visual_marker_6_pad")


This is a project I did in the past, and it might be useful in your case.


[ QGroundControl ](http://qgroundcontrol.com/)


* [ GitHub Sponsors  Fund open source developers  ](/sponsors)


  * [ ignition ](namespaceignition.html)
  * [ rendering ](namespaceignition_1_1rendering.html)
  * [ Marker ](classignition_1_1rendering_1_1Marker.html)


[ ![](https://ignitionrobotics.org/assets/doxygen/ignition_logo.svg)
](index.html)


Powered by [ Discourse ](https://www.discourse.org) , best viewed with
JavaScript enabled


This package implements methods to enable a PX4-powered multi-rotor to track a
moving vehicle. - GitHub - mzahana/mavros_apriltag_tracking: This package
implements methods to enable a PX4-powered m...


    <visual name="visual">
      <pose>0 0 0 0 0 0</pose>
      <geometry>
        <box>
          <size>0.0001 0.15 0.15</size>
        </box>
      </geometry>
      <material>
        <script>
          <uri>model://aruco_marker/materials/scripts</uri>
          <uri>model://aruco_marker/materials/textures</uri>
          <name>Marker</name>
        </script>
      </material>
    </visual>

And this is the file structure of the model:

    aruco_marker
    ├── materials
    │   ├── scripts
    │   │   └── marker.material
    │   └── textures
    │       └── marker.png
    ├── model.config
    └── model.sdf

You can examine the complete model in the ` grobot_gazebo ` package. Having
this model, we can finally spawn the marker in the world.

![marker-model](https://nlamprian.me/assets/img/blog/2020-01-27-visual-
servoing-in-gazebo/marker-model.png)


[ ![cc-by-sa](/m/default/media/images/cc-by-sa.png?v=2)
](http://creativecommons.org/licenses/by-sa/3.0/legalcode) Copyright Askbot,
2010-2011. Content on this site is licensed under a [ Creative Commons
Attribution Share Alike 3.0 ](http://creativecommons.org/licenses/by-
sa/3.0/legalcode) license.


Please note: Gazebo requires javascript to work properly, please enable
javascript in your browser, [ here is how
](https://www.google.com/support/bin/answer.py?answer=23852)


Implemented in [ OgreMarker
](classignition_1_1rendering_1_1OgreMarker.html#ad3b1567f005c06a0770409dfc3ba203a)
, [ Ogre2Marker
](classignition_1_1rendering_1_1Ogre2Marker.html#ad3b1567f005c06a0770409dfc3ba203a)
, [ BaseMarker< T >
](classignition_1_1rendering_1_1BaseMarker.html#a75dcfaf0d84ecfd1e001aaf27fd2984b)
, [ BaseMarker< Ogre2Geometry >
](classignition_1_1rendering_1_1BaseMarker.html#a75dcfaf0d84ecfd1e001aaf27fd2984b)
, and [ BaseMarker< OgreGeometry >
](classignition_1_1rendering_1_1BaseMarker.html#a75dcfaf0d84ecfd1e001aaf27fd2984b)
.


  * I have no experience in Gazebo or ROS.
  * I’m not developing in ROS at all, I’m developing in Python, using OpenCV to read the images and MavSDK to talk to the drone.


[ about ](/about/) |  [ faq ](/faq/) |  [ help ](/help/ "help") |  [ privacy
policy ](/privacy/) |  [ terms of service ](/terms/)


Asked: ** 2016-09-28 08:43:37 -0500  **


###  Resources


[ **29** stars ](/joselusl/aruco_gazebo/stargazers)


        <arg name="name" value="hank" />
      </include>
    </launch>

You can examine such a multi-robot simulation example by running

    > roslaunch grobot_bringup patrols.launch

This will launch gazebo and spawn two turtlebot3 burger models with the names
**karl** and **hank** . If we do a ` rostopic list ` , we will notice that
there are two instances of each topic, that was available before for one
robot. For example, **karl** listens to the ` karl/cmd_vel ` topic for
commands, and **hank** listens to the ` hank/cmd_vel ` topic. And if we do a `
rosrun tf view_frames ` , we’ll see that each robot has its own unique tf
tree.

![multi-robot](https://nlamprian.me/assets/img/blog/2020-01-27-visual-
servoing-in-gazebo/multi-robot.gif)


     [in]  |  The  |  desired render type
---|---|---

Implemented in [ OgreMarker
](classignition_1_1rendering_1_1OgreMarker.html#af8720431f57fcaf3fdc71e5a5f9c9848)
, [ Ogre2Marker
](classignition_1_1rendering_1_1Ogre2Marker.html#af8720431f57fcaf3fdc71e5a5f9c9848)
, [ BaseMarker< T >
](classignition_1_1rendering_1_1BaseMarker.html#a47ace2ab83de948a828c993cd8d7c5e3)
, [ BaseMarker< Ogre2Geometry >
](classignition_1_1rendering_1_1BaseMarker.html#a47ace2ab83de948a828c993cd8d7c5e3)
, and [ BaseMarker< OgreGeometry >
](classignition_1_1rendering_1_1BaseMarker.html#a47ace2ab83de948a828c993cd8d7c5e3)
.


Or as you suggested you could add a visual plugin, you can also take a look at
this: [ http://answers.gazebosim.org/question...
](http://answers.gazebosim.org/question/3383/how-to-add-a-dynamic-visual-
marker-in-gazebo/#3394)


Toggle navigation  [ nlamprian ](/)

  * [ Blog ](/)
  * [ Portfolio ](/portfolio)
  * [ About ](/about)

#  Visual Servoing in Gazebo


[ ![ffurrer gravatar image](/m/default/media/images/nophoto.png?v=2)
](/users/28/ffurrer/)


##  Question Tools


[ aruco_visual_marker_0_pad
](/joselusl/aruco_gazebo/tree/master/aruco_visual_marker_0_pad
"aruco_visual_marker_0_pad")


#  [ Simulate aruco markers in gazebo with MavSDK ](/t/simulate-aruco-markers-
in-gazebo-with-mavsdk/29106)


Search


[ .gitignore ](/joselusl/aruco_gazebo/blob/master/.gitignore ".gitignore")


Name


Cancel  Submit feedback


if you are using ros, just use rviz


[ aruco_visual_marker_7_pad
](/joselusl/aruco_gazebo/tree/master/aruco_visual_marker_7_pad
"aruco_visual_marker_7_pad")


  Preparation

* * *

We will continue working on the same [ grobot
](https://github.com/nlamprian/grobot) repository we introduced in the last
post. It has been updated to include the new material we will go through this
time. Either **git pull** grobot and **rosdep install** to get the additional
dependencies, or delete the ` grobot_ws ` workspace all together and repeat
the steps from the beginning.

    > source /opt/ros/$ROS_DISTRO/setup.bash
    > mkdir ~/grobot_ws
    > cd ~/grobot_ws
    > wstool init src https://github.com/nlamprian/grobot/raw/master/.grobot.rosinstall
    > rosdep install --from-paths src --ignore-src --rosdistro=$ROS_DISTRO
    > catkin build
    > source devel/setup.bash


[ ![ gravatar image]() ]() [ ]() (  2024-04-18 00:56:04 -0500  )  edit


[ QGC ](http://qgroundcontrol.com/)


No releases published


[ aruco_visual_marker_6
](/joselusl/aruco_gazebo/tree/master/aruco_visual_marker_6
"aruco_visual_marker_6")


[ aruco_visual_marker_3
](/joselusl/aruco_gazebo/tree/master/aruco_visual_marker_3
"aruco_visual_marker_3")


Returns


    * [ Actions  Automate any workflow  ](/features/actions)
    * [ Packages  Host and manage packages  ](/features/packages)
    * [ Security  Find and fix vulnerabilities  ](/features/security)
    * [ Codespaces  Instant dev environments  ](/features/codespaces)
    * [ Copilot  Write better code with AI  ](/features/copilot)
    * [ Code review  Manage code changes  ](/features/code-review)
    * [ Issues  Plan and track work  ](/features/issues)
    * [ Discussions  Collaborate outside of code  ](/features/discussions)


Parameters


    * [ CI/CD & Automation ](/solutions/ci-cd/)
    * [ DevOps ](/solutions/devops/)
    * [ DevSecOps  ](https://resources.github.com/devops/fundamentals/devsecops/)


[ aruco_visual_marker_2_pad
](/joselusl/aruco_gazebo/tree/master/aruco_visual_marker_2_pad
"aruco_visual_marker_2_pad")


[ README.md ](/joselusl/aruco_gazebo/blob/master/README.md "README.md")


[ MAVSDK ](http://mavsdk.mavlink.io)


[ aruco_visual_marker_0
](/joselusl/aruco_gazebo/tree/master/aruco_visual_marker_0
"aruco_visual_marker_0")


|  virtual void SetPoint  |  (  |  unsigned int  |  __index_ ,
---|---|---|---
|  |  const [ ignition::math::Vector3d
](https://ignitionrobotics.org/api/math/6.8/namespaceignition_1_1math.html#a1f05093f5ee1a9ecdd54476792e4c206)
& |  __value_
|  )  |  |
pure virtual

Set an existing point's vector.


[ **23** forks ](/joselusl/aruco_gazebo/forks)


|  virtual std::chrono::steady_clock::duration Lifetime  |  (  |  |  )  |
const
---|---|---|---|---
pure virtual

Get the lifetime of this [ Marker ](classignition_1_1rendering_1_1Marker.html
"A marker geometry class. The marker's visual appearance is based on the
marker type specified...") .


|  virtual int32_t Layer  |  (  |  |  )  |  const
---|---|---|---|---
pure virtual

Get the layer of this [ Marker ](classignition_1_1rendering_1_1Marker.html "A
marker geometry class. The marker's visual appearance is based on the marker
type specified...") .


  *[
              2016-09-28 08:43:37 -0500
             ]: 2016-09-28 08:43:37 -0500
  *[
              2017-01-31 10:31:44 -0500
             ]: 2017-01-31 10:31:44 -0500
  *[
              2016-09-29 02:16:11 -0500
             ]: 2016-09-29 02:16:11 -0500
  *[
              2016-09-29 23:57:04 -0500
             ]: 2016-09-29 23:57:04 -0500
  *[
        2016-09-28 08:43:37 -0500
       ]: 2016-09-28 08:43:37 -0500
  *[
        2024-04-18 00:56:04 -0500
       ]: 2024-04-18 00:56:04 -0500


[ Branches  ](/joselusl/aruco_gazebo/branches) [ Tags
](/joselusl/aruco_gazebo/tags)


No packages published


[ aruco_visual_marker_5
](/joselusl/aruco_gazebo/tree/master/aruco_visual_marker_5
"aruco_visual_marker_5")


[ aruco_visual_marker_4
](/joselusl/aruco_gazebo/tree/master/aruco_visual_marker_4
"aruco_visual_marker_4")


Cheers


Follow


[ **answered 2017-01-31 10:31:44 -0500  ** ](/answers/15354/revisions/)


##  ◆  AddPoint()  [1/2]


Visual markers have been added to gazebo8. Use ` gz marker -h ` for help.


  Follow dynamic targets with a camera

Posted by Nick Lamprianidis on January 27, 2020

Last time, we worked on creating a [ basic gazebo simulation
](https://nlamprian.me/blog/software/ros/2019/12/26/navigate-gazebo-worlds/) .
We arranged our gazebo resources, created a map for our world, and configured
the launch of a robot model and the navigation stack, such that we are able to
send a goal and have the robot autonomously navigate to it. This time, we
build upon that simulation by spawning a second robot in the world with a
target on its back, which our robot will try to follow. More specifically, we
are going to work on an application of visual servoing, and in the meantime,
we’ll have the chance to explore how to configure a multi-robot simulation,
apply textures to models, enforce constraints between models, and have a robot
follow a visual marker that is constantly moving in the world.

![visual-servoing](https://nlamprian.me/assets/img/blog/2020-01-27-visual-
servoing-in-gazebo/visual-servoing.png)


* [ Marker.hh ](Marker_8hh_source.html)


You signed in with another tab or window. [ Reload ]() to refresh your
session.  You signed out in another tab or window. [ Reload ]() to refresh
your session.  You switched accounts on another tab or window. [ Reload ]() to
refresh your session.  Dismiss alert


* [ The ReadME Project  GitHub community articles  ](/readme)


[ .gitignore ](/joselusl/aruco_gazebo/blob/master/.gitignore ".gitignore")


[ ![Peter Mitrano gravatar
image](/upfiles/avatars/Peter%20Mitrano/resized/32/proffessional_pic.jpg)
](/users/1068/peter-mitrano/)


Parameters


  * [ Notifications ](/login?return_to=%2Fjoselusl%2Faruco_gazebo)
  * [ Fork  23  ](/login?return_to=%2Fjoselusl%2Faruco_gazebo)
  * [ Star  29  ](/login?return_to=%2Fjoselusl%2Faruco_gazebo)


[ edit ](/s/answers/14528/edit/) flag offensive  delete  [ link
](/question/14518/marker-like-functionality-in-gazebo/?answer=14528#post-
id-14528 "permanent link") more


The time at which the marker will be removed


This commit does not belong to any branch on this repository, and may belong
to a fork outside of the repository.


Readme


Aruco Visual Markers for Gazebo Simulator


##  [ Releases ](/joselusl/aruco_gazebo/releases)


I’m trying to do precision landing using a downward facing camera and aruco
markers.
I’m currently doing my simulations in SITL (according to [ this tutorial
](https://docs.px4.io/main/en/simulation/gazebo.html) ) by manually holding
the copter over the marker and trying to follow the movements of the simulated
drone. It looks about as silly as it sounds…


[ edit ](/s/answers/14522/edit/) flag offensive  delete  [ link
](/question/14518/marker-like-functionality-in-gazebo/?answer=14522#post-
id-14522 "permanent link") more


[ aruco_visual_marker_6_pad
](/joselusl/aruco_gazebo/tree/master/aruco_visual_marker_6_pad
"aruco_visual_marker_6_pad")


##  3  Answers


     [in]  |  _pt  |  A vector containing the position of the point
---|---|---
[in]  |  _color  |  The color the point is set to

Implemented in [ BaseMarker< T >
](classignition_1_1rendering_1_1BaseMarker.html#a23ad75a631d7d3e6ad8143b8a346c950)
, [ BaseMarker< Ogre2Geometry >
](classignition_1_1rendering_1_1BaseMarker.html#a23ad75a631d7d3e6ad8143b8a346c950)
, [ BaseMarker< OgreGeometry >
](classignition_1_1rendering_1_1BaseMarker.html#a23ad75a631d7d3e6ad8143b8a346c950)
, [ OgreMarker
](classignition_1_1rendering_1_1OgreMarker.html#a5a70195978056aad793e9da61ce2974a)
, and [ Ogre2Marker
](classignition_1_1rendering_1_1Ogre2Marker.html#a5a70195978056aad793e9da61ce2974a)
.


[ ![](https://github.com/Dronecode/dronecode-wordpress-
theme/raw/master/dronecode-salient-
child/images/dronecode_top_bar_logo_full.png) ](https://www.dronecode.org/)


[ aruco_visual_marker_5_pad
](/joselusl/aruco_gazebo/tree/master/aruco_visual_marker_5_pad
"aruco_visual_marker_5_pad")


[ aruco_visual_marker_1
](/joselusl/aruco_gazebo/tree/master/aruco_visual_marker_1
"aruco_visual_marker_1")


[ Gazebo ](http://gazebosim.org) | [ Ignition ](https://ignitionrobotics.org)
| [ Community ](https://community.gazebosim.org/)


|  virtual void SetLayer  |  (  |  int32_t  |  __layer_ |  )  |
---|---|---|---|---|---
pure virtual

Set the layer of this [ Marker ](classignition_1_1rendering_1_1Marker.html "A
marker geometry class. The marker's visual appearance is based on the marker
type specified...") .


###  Footer navigation


virtual  |  [ ~Object
](classignition_1_1rendering_1_1Object.html#ab5cc4f9ba1ea5c2f25bc4b1f0dac5dc5)
()
|  Destructor. [ More...
](classignition_1_1rendering_1_1Object.html#ab5cc4f9ba1ea5c2f25bc4b1f0dac5dc5)

virtual void  |  [ Destroy
](classignition_1_1rendering_1_1Object.html#a84693792fa8cba90b312c0b1caf53716)
()=0
|  Destroy any resources associated with this object. Invoking any other
functions after destroying an object will result in undefined behavior. [
More...
](classignition_1_1rendering_1_1Object.html#a84693792fa8cba90b312c0b1caf53716)

virtual unsigned int  |  [ Id
](classignition_1_1rendering_1_1Object.html#af440fd9edb16553775262ac2c5fcd315)
() const =0
|  Get the object ID. This ID will be unique across all objects inside a given
scene, but necessarily true for objects across different scenes. [ More...
](classignition_1_1rendering_1_1Object.html#af440fd9edb16553775262ac2c5fcd315)

virtual [ std::string
](http://en.cppreference.com/w/cpp/string/basic_string.html) |  [ Name
](classignition_1_1rendering_1_1Object.html#a70ee001ce76c53aebb215a9f51653ab3)
() const =0
|  Get the object name. This name will be unique across all objects inside a
given scene, but necessarily true for objects across different scenes. [
More...
](classignition_1_1rendering_1_1Object.html#a70ee001ce76c53aebb215a9f51653ab3)

virtual void  |  [ PostRender
](classignition_1_1rendering_1_1Object.html#aee73a4d9fd3bca2a941038e4a5a3879d)
()=0
|  Post process this object and any of its children after rendering. [ More...
](classignition_1_1rendering_1_1Object.html#aee73a4d9fd3bca2a941038e4a5a3879d)

virtual void  |  [ PreRender
](classignition_1_1rendering_1_1Object.html#adffb56e0e545fefebf96b36f295396e9)
()=0
|  Prepare this object and any of its children for rendering. This should be


add a comment


[ Help ](http://discuss.px4.io/)


[ README.md ](/joselusl/aruco_gazebo/blob/master/README.md "README.md")


[ aruco_visual_marker_4_pad
](/joselusl/aruco_gazebo/tree/master/aruco_visual_marker_4_pad
"aruco_visual_marker_4_pad")


Name  |  Name  |


|  [ Marker ](classignition_1_1rendering_1_1Marker.html) |  (  |  |  )  |
---|---|---|---|---
protected

##  ◆  ~Marker()


](classignition_1_1rendering_1_1Marker.html "A marker geometry class. The
marker's visual appearance is based on the marker type specified...") .
More...

virtual void  |  [ SetLayer
](classignition_1_1rendering_1_1Marker.html#a6ab41a4f71c62f8d5f14d436a166e089)
(int32_t _layer)=0
|  Set the layer of this [ Marker ](classignition_1_1rendering_1_1Marker.html
"A marker geometry class. The marker's visual appearance is based on the
marker type specified...") .  More...

virtual void  |  [ SetLifetime
](classignition_1_1rendering_1_1Marker.html#acf50acc3346a7651de6c54679723914d)
(const std::chrono::steady_clock::duration &_lifetime)=0
|  Set the lifetime of this [ Marker
](classignition_1_1rendering_1_1Marker.html "A marker geometry class. The
marker's visual appearance is based on the marker type specified...") .
More...

virtual void  |  [ SetPoint
](classignition_1_1rendering_1_1Marker.html#a6497fc79fd2f028ca890b4b23038b195)
(unsigned int _index, const [ ignition::math::Vector3d
](https://ignitionrobotics.org/api/math/6.8/namespaceignition_1_1math.html#a1f05093f5ee1a9ecdd54476792e4c206)
&_value)=0
|  Set an existing point's vector.  More...

virtual void  |  [ SetType
](classignition_1_1rendering_1_1Marker.html#a0848a2e5d0939beb566b8473e7fec72d)
(const [ MarkerType
](namespaceignition_1_1rendering.html#ade22213fff69cfb37d8238e8fd3073df)
_markerType)=0
|  Set the render type of this [ Marker
](classignition_1_1rendering_1_1Marker.html "A marker geometry class. The
marker's visual appearance is based on the marker type specified...") .
More...

virtual [ MarkerType
](namespaceignition_1_1rendering.html#ade22213fff69cfb37d8238e8fd3073df) |  [
Type
](classignition_1_1rendering_1_1Marker.html#a687d8763c93d1aefd281c4f64d8a97ec)


  Conclusion

* * *

We’ve seen how we can create and configure multiple resources in a simulation.
We’ve worked on an application where we controlled a robot with input from a
camera and had it follow a marker. The result was inadequate, but it showcases
that by combining gazebo and ROS, we get a platform where we have all the
freedom we need to experiment. So, what are you going to try next?

* * *


![transformations](https://nlamprian.me/assets/img/blog/2020-01-27-visual-
servoing-in-gazebo/transformations.png)

\\[T_{mt} = T_{mr} T_{rc} T_{cf} T_{ft}\\]

move_base has two interfaces for sending navigation goals. One is a topic, `
move_base_simple/goal ` , and the other is an action, ` move_base ` . We use
the topic to continuously send goals as we receive marker transformations. But
we use the action when doing exploration so that we have some feedback. In the
case of the ‘rotate’ exploration, for example, we want to keep going as long
as we don’t see the marker. For that, we need to know when the robot has
reached the commanded orientation so that we send the next one.

What was discussed is implemented in the ` follow_marker ` node in `
grobot_navigation ` . To see it all in action, you can run the `
visual_servoing.launch ` with your preferred exploration strategy.

    > roslaunch grobot_bringup visual_servoing.launch exploration_strategy:=move_to_target
    > # or
    > roslaunch grobot_bringup visual_servoing.launch exploration_strategy:=rotate

![visual-servoing](https://nlamprian.me/assets/img/blog/2020-01-27-visual-
servoing-in-gazebo/visual-servoing.gif)

It doesn’t take long to notice that the approach is unreliable. The robot
frequently loses track of the marker. The problem is that we are giving a goal
to the robot and letting it freely navigate. In this example, we implemented
our algorithm as an application on top of move_base. In a real scenario, we
would have to integrate our additional requirements into the navigation
planner. The goal would be to make sure that the robot keeps track of the
marker and to optimize its trajectories by anticipating where the marker is
going to be.


    * [ Topics ](/topics)
    * [ Trending ](/trending)
    * [ Collections ](/collections)


[ ](https://github.com "GitHub") © 2024 GitHub, Inc.


|  virtual void SetType  |  (  |  const [ MarkerType
](namespaceignition_1_1rendering.html#ade22213fff69cfb37d8238e8fd3073df) |
__markerType_ |  )  |
---|---|---|---|---|---
pure virtual

Set the render type of this [ Marker
](classignition_1_1rendering_1_1Marker.html "A marker geometry class. The
marker's visual appearance is based on the marker type specified...") .


##  ◆  SetType()


_Attention:_ answers.gazebosim.org is deprecated as of August the 11th, 2023.
Please visit [ robotics.stackexchange.com ](http://robotics.stackexchange.com)
to ask a new question. This site will remain online in read-only mode during
the transition and into the foreseeable future. Selected questions and answers
have been migrated, and redirects have been put in place to direct users to
the corresponding questions on Robotics Stack Exchange. Additional details are
[ available here ](https://community.gazebosim.org/t/important-final-ros-
gazebo-answers-migration-schedule/2185) .


  **Share:** [ __
](https://www.facebook.com/sharer/sharer.php?u=https://nlamprian.me/blog/software/ros/2020/01/27/visual-
servoing-in-gazebo/) [ __ ](https://twitter.com/intent/tweet?text=Visual
Servoing in Gazebo https://nlamprian.me/blog/software/ros/2020/01/27/visual-
servoing-in-gazebo/) [ __
](https://plus.google.com/share?url=https://nlamprian.me/blog/software/ros/2020/01/27/visual-
servoing-in-gazebo/) [ __
](https://www.linkedin.com/shareArticle?mini=true&url=https://nlamprian.me/blog/software/ros/2020/01/27/visual-
servoing-in-gazebo/&title=Visual Servoing in Gazebo&summary=&source=)

* * *

  * [ __ Previous Post ](/blog/software/ros/2019/12/26/navigate-gazebo-worlds/ "Navigate Gazebo Worlds")
  * [ Next Post __ ](/blog/hardware/cnc/2021/02/27/cnc-milling-with-the-snapmaker-a350/ "CNC Milling with the Snapmaker A350")

* * *

Please enable JavaScript to view the [ comments powered by Disqus.
](https://disqus.com/?ref_noscript)

* * *

  * [ __ __ ](https://www.facebook.com/nick.lamprianidis)
  * [ __ __ ](https://twitter.com/nlamprian)
  * [ __ __ ](https://plus.google.com/u/1/109379247151771147954)
  * [ __ __ ](https://www.youtube.com/channel/UCD9sOb1yxhIjk2UQsFeTqzw)
  * [ __ __ ](https://www.linkedin.com/in/nlamprian/)
  * [ __ __ ](https://github.com/nlamprian)
  * [ __ _![](/assets/img/site/social/codebender.png) _ ](https://codebender.cc/user/pAIgn10)
  * [ __ _![](/assets/img/site/social/google-play.png) _ ](https://play.google.com/store/apps/developer?id=Nick%20Lamprianidis&hl=en)
  * [ __ _![](/assets/img/site/social/thingiverse.png) _ ](http://www.thingiverse.com/nlamprian/designs)
  * [ __ __ ](/feed.xml)

* * *

__ 2014 - 2023 Nick Lamprianidis. Some Rights Reserved.


    * [ All features ](/features)
    * [ Documentation  ](https://docs.github.com)
    * [ GitHub Skills  ](https://skills.github.com/)
    * [ Blog  ](https://github.blog)


##  ◆  Layer()


[ aruco_visual_marker_3_pad
](/joselusl/aruco_gazebo/tree/master/aruco_visual_marker_3_pad
"aruco_visual_marker_3_pad")


[ List of all members ](classignition_1_1rendering_1_1Marker-members.html) |
Public Member Functions  |  Protected Member Functions


* Solutions


##  ◆  SetLifetime()


[ **answered 2016-09-29 23:57:04 -0500  ** ](/answers/14528/revisions/)


master


[ 5 Commits  ](/joselusl/aruco_gazebo/commits/master/)


Marker Class Reference  abstract


Query


A marker geometry class. The marker's visual appearance is based on the marker
type specified. [ More... ](classignition_1_1rendering_1_1Marker.html#details)


[ edit ](/s/answers/15354/edit/) flag offensive  delete  [ link
](/question/14518/marker-like-functionality-in-gazebo/?answer=15354#post-
id-15354 "permanent link") more


##  ◆  SetLayer()


Explore


[ Discussion Forum for PX4, Pixhawk, QGroundControl, MAVSDK, MAVLink ](/)


##  API Reference


[ ](/joselusl/aruco_gazebo/commits/master/)

###


Clear


Sort by »  [ oldest  ](/question/14518/marker-like-functionality-in-
gazebo/?sort=oldest#sort-top) [ newest  ](/question/14518/marker-like-
functionality-in-gazebo/?sort=latest#sort-top) [ most voted
](/question/14518/marker-like-functionality-in-gazebo/?sort=votes#sort-top)


You can’t perform that action at this time.


[ edit ](/questions/14518/edit/) [ retag ](/s/questions/14518/retag/) flag
offensive  [ close ](/questions/14518/close/) merge  delete


By Solution


Aruco Visual Markers for Gazebo Simulator


|  virtual void AddPoint  |  (  |  double  |  __x_ ,
---|---|---|---
|  |  double  |  __y_ ,
|  |  double  |  __z_ ,
|  |  const [ ignition::math::Color
](https://ignitionrobotics.org/api/math/6.8/classignition_1_1math_1_1Color.html)
& |  __color_
|  )  |  |
pure virtual

Add a point with its respective color to the marker.


[ MAVSDK  ](/c/mavsdk/19)


Repositories


[ ](https://github.com/)


[ aruco_visual_marker_0
](/joselusl/aruco_gazebo/tree/master/aruco_visual_marker_0
"aruco_visual_marker_0")


Returns


##  ◆  ClearPoints()


|  virtual [ MarkerType
](namespaceignition_1_1rendering.html#ade22213fff69cfb37d8238e8fd3073df) Type
|  (  |  |  )  |  const
---|---|---|---|---
pure virtual

Get the render type of this [ Marker
](classignition_1_1rendering_1_1Marker.html "A marker geometry class. The
marker's visual appearance is based on the marker type specified...") .


     [in]  |  _x  |  X coordinate
---|---|---
[in]  |  _y  |  Y coordinate
[in]  |  _z  |  Z coordinate
[in]  |  _color  |  The color the point is set to

Implemented in [ BaseMarker< T >
](classignition_1_1rendering_1_1BaseMarker.html#aaf7f5b19c45fc71ebad36db6afa8c48a)
, [ BaseMarker< Ogre2Geometry >
](classignition_1_1rendering_1_1BaseMarker.html#aaf7f5b19c45fc71ebad36db6afa8c48a)
, and [ BaseMarker< OgreGeometry >
](classignition_1_1rendering_1_1BaseMarker.html#aaf7f5b19c45fc71ebad36db6afa8c48a)
.


[ Sign in
](/login?return_to=https%3A%2F%2Fgithub.com%2Fjoselusl%2Faruco_gazebo)


Last commit date

---|---|---|---

##  Latest commit


[ aruco_visual_marker_2_pad
](/joselusl/aruco_gazebo/tree/master/aruco_visual_marker_2_pad
"aruco_visual_marker_2_pad")


Implemented in [ BaseMarker< T >
](classignition_1_1rendering_1_1BaseMarker.html#ab79616842db1c2c1f3019c4980771eeb)
, [ BaseMarker< Ogre2Geometry >
](classignition_1_1rendering_1_1BaseMarker.html#ab79616842db1c2c1f3019c4980771eeb)
, and [ BaseMarker< OgreGeometry >
](classignition_1_1rendering_1_1BaseMarker.html#ab79616842db1c2c1f3019c4980771eeb)
.


[ ](/joselusl/aruco_gazebo/branches) [ ](/joselusl/aruco_gazebo/tags)


[ Mzahana  ](https://discuss.px4.io/u/Mzahana) September 24, 2022, 2:00pm  4


##  Public Member Functions

---
virtual  |  [ ~Marker
](classignition_1_1rendering_1_1Marker.html#a462b444c50a147538ca59c701d7316ae)
()
|  Destructor.  More...

virtual void  |  [ AddPoint
](classignition_1_1rendering_1_1Marker.html#a545137f216690c8bd74a579f5e1debcc)
(double _x, double _y, double _z, const [ ignition::math::Color
](https://ignitionrobotics.org/api/math/6.8/classignition_1_1math_1_1Color.html)
&_color)=0
|  Add a point with its respective color to the marker.  More...

virtual void  |  [ AddPoint
](classignition_1_1rendering_1_1Marker.html#abcf5675394e7739ba5cf8bf97fe03f2c)
(const [ ignition::math::Vector3d
](https://ignitionrobotics.org/api/math/6.8/namespaceignition_1_1math.html#a1f05093f5ee1a9ecdd54476792e4c206)
&_pt, const [ ignition::math::Color
](https://ignitionrobotics.org/api/math/6.8/classignition_1_1math_1_1Color.html)
&_color)=0
|  Add a point with its respective color to the marker.  More...

virtual void  |  [ ClearPoints
](classignition_1_1rendering_1_1Marker.html#a3bcbd6d459e5218ff756dbf196c2d43d)
()=0
|  Clear the points of the marker, if applicable.  More...

virtual int32_t  |  [ Layer
](classignition_1_1rendering_1_1Marker.html#aad6f195adf89a46d28a85337e84babd3)
() const =0
|  Get the layer of this [ Marker ](classignition_1_1rendering_1_1Marker.html
"A marker geometry class. The marker's visual appearance is based on the
marker type specified...") .  More...

virtual std::chrono::steady_clock::duration  |  [ Lifetime
](classignition_1_1rendering_1_1Marker.html#ae4925fdc7832b45df96554a191d31f97)
() const =0
|  Get the lifetime of this [ Marker


This has already been done in our example world. If we start ` world.launch `
and list the available services, we are also going to see those offered by the
plugin.

    > rosservice list
    /link_attacher_node/attach
    /link_attacher_node/detach
    ...

How the plugin works is, given two links in a certain configuration, a joint
is created that locks the two together. In other words, the initial poses of
the links matter. This means we need to control the relative pose between the
two links (and by extension, models), before we call the attach service.

Here is the plan for attaching the marker to the robot. We’ll use a script to
make a few service calls. The script will pause the simulation, get the
current pose of the robot, compute the pose of the marker based on the robot
pose, spawn the marker in that pose, attach the marker to the robot, and
finally resume the simulation. We are pausing the simulation, so that we know
that nothing moves while we are in the process of attaching the marker to the
robot. You can find this script in ` spawn_marker_on_robot ` in the `
grobot_utilities ` package.

We are implementing this process in a node so that we can launch the node
along with the rest of the robot bringup. The node will wait for the robot to
show up, spawn and attach the marker, and then exit. To see this in action,
you can run the ` patrols.launch ` once again, but this time with the `
has_marker ` parameter enabled. It will launch the same two turtlebot3 burger
robots, but with two markers on top of them.

    > roslaunch grobot_bringup patrols.launch has_marker:=true

![robot-marker](https://nlamprian.me/assets/img/blog/2020-01-27-visual-
servoing-in-gazebo/robot-marker.gif)


First time here? Check out the FAQ!


[ aruco_visual_marker_3_pad
](/joselusl/aruco_gazebo/tree/master/aruco_visual_marker_3_pad
"aruco_visual_marker_3_pad")


[ nkoenig ](/users/5/nkoenig/)
7676  ●  8  ●  44  ●  71  [ http://gazebosim.org/ ](http://gazebosim.org/
"nkoenig's website is http://gazebosim.org/")


We read every piece of feedback, and take your input very seriously.


#  Ignition Rendering


[ aruco_visual_marker_7_pad
](/joselusl/aruco_gazebo/tree/master/aruco_visual_marker_7_pad
"aruco_visual_marker_7_pad")


The documentation for this class was generated from the following file:


In our case, aruco_detect has been configured to listen to `
/camera/rgb/image_raw ` for ` sensor_msgs/Image ` messages and publish `
fiducial_msgs/FiducialTransformArray ` to ` /fiducial_transforms ` . A
fiducial transform message contains a marker id and a 3D transformation that
tells the position and orientation of the marker with respect to the camera.

Last but not least, we need to figure out how we are going to control the
robot. The goal of our control algorithm is to maintain a certain pose
relative to a given target. The idea of vision-based control is about driving
a robot with visual feedback. We will use the extracted information from the
camera images to control the robot. So, for every fiducial transformations
message, our control loop will act as follows:

  * if marker is not detected
    * if enough time has passed, start exploration
  * if marker is detected
    * if exploration is in progress, cancel exploration
    * compute global navigation goal
    * send navigation goal

To follow a target, we need to first see the target. If the target is not in
the camera’s field of view, we cannot just stay idle, as it might never show
up. So we need to start exploring the space. We will consider two simple
approaches:

  * move to a vantage point where we can expect the target to appear
  * rotate in place 360 degrees to observe the space all around

Given that we see the marker, and we have its transformation, \\(T_{cf}\\), we
need to compute the navigation goal, \\(T_{mt}\\), for the robot. The marker
transformation is in the camera frame. We need to first express it in the
robot frame, and then the map frame. The robot to camera transformation,
\\(T_{rc}\\), is defined by the URDF of the robot. The map to robot
transformation, \\(T_{mr}\\), is estimated by localization. ` tf ` can do all
these calculations, and give us the marker in the map frame, \\(T_{mf} =
T_{mr} T_{rc} T_{cf}\\). Then, we only need to apply the marker to target
transformation, which is defined by us, to get the desired pose of the robot.


#  joselusl/aruco_gazebo


PX4 is the Professional Autopilot. Developed by world-class developers from
industry and academia, and supported by an active world wide community, it
powers all kinds of vehicles from racing and cargo drones through to ground
vehicles and...


[ 29  stars ](/joselusl/aruco_gazebo/stargazers) [ 23  forks
](/joselusl/aruco_gazebo/forks) [ Branches  ](/joselusl/aruco_gazebo/branches)
[ Tags  ](/joselusl/aruco_gazebo/tags) [ Activity
](/joselusl/aruco_gazebo/activity)


[ aruco_visual_marker_4
](/joselusl/aruco_gazebo/tree/master/aruco_visual_marker_4
"aruco_visual_marker_4")


[ Hi there! Please sign in ](/account/signin/?next=/question/14518/marker-
like-functionality-in-gazebo/) [ help ](/help/ "help")


[ docs.px4.io ](https://docs.px4.io/main/en/simulation/gazebo.html#running-
the-simulation)


[ aruco_visual_marker_7
](/joselusl/aruco_gazebo/tree/master/aruco_visual_marker_7
"aruco_visual_marker_7")


##  Folders and files


Parameters


#  Saved searches


#  Provide feedback


###  [ Gazebo Simulation | PX4 User Guide
](https://docs.px4.io/main/en/simulation/gazebo.html#running-the-simulation)


_No additional authors._


##  5.3.1 (2022-04-26)


###  [ rcl_lifecycle ](/p/rcl_lifecycle) package from [ rcl ](/r/rcl/github-
ros2-rcl) repo


  * Jacob Perron
  * Karsten Knese