    // Enable/Disable sensor
    const bool shouldBeEnabled =
      mImagePublisher->get_subscription_count() > 0 || mPointCloudPublisher->get_subscription_count() > 0;
    if (shouldBeEnabled != mIsEnabled) {
      if (shouldBeEnabled)
        wb_range_finder_enable(mRangeFinder, mPublishTimestepSyncedMs);
      else
        wb_range_finder_disable(mRangeFinder);
      mIsEnabled = shouldBeEnabled;
    }
  }


From a terminal in your ROS2 workspace run:


  2. The second is an implementation of the ` __cmd_vel_callback(self, twist) ` callback private method that will be called for each Twist message received on the ` /cmd_vel ` topic and will save it in the ` self.__target_twist ` member variable.
  3. Finally, the ` step(self) ` method is called at every time step of the simulation. The call to ` rclpy.spin_once() ` is needed to keep the ROS node running smoothly. At each time step, the method will retrieve the desired ` forward_speed ` and ` angular_speed ` from ` self.__target_twist ` . As the motors are controlled with angular velocities, the method will then convert the forward_speed and angular_speed into individual commands for each wheel. This conversion depends on the structure of the robot, more specifically on the radius of the wheel and the distance between them.


If installed from sources, source your ROS 2 workspace, if not done already.


source /opt/ros/rolling/setup.bash


  * [ Blog ](/blog)
  * [ GitHub  ](https://github.com/mpolinowski)


    nano hello_webots/resources/my_robot.urdf

    <?xml version="1.0" ?>
    <robot name="My robot">
        <webots>
            <device reference="ds0" type="DistanceSensor">
                <ros>
                    <topicName>/left_sensor</topicName>
                    <alwaysOn>true</alwaysOn>
                </ros>
            </device>
            <device reference="ds1" type="DistanceSensor">
                <ros>
                    <topicName>/right_sensor</topicName>
                    <alwaysOn>true</alwaysOn>
                </ros>
            </device>
            <plugin type="hello_webots.my_webot_driver.MyRobotDriver" />
        </webots>
    </robot>


Retrieve the sources from Github.


**Tags:**


On this page


You can either install the official released package, or install it from the
latest up-to-date sources from [ Github
](https://github.com/cyberbotics/webots_ros2) .


  * [ Notebook ](/docs/intro)
  * [ Tags ](/docs/tags)
  * [ CV ](/Curriculum-Vitae)


* Multiple Installations of Webots


**Goal:** Install the ` webots_ros2  ` package and run simulation examples on
Ubuntu.


![ROS2 Webots Robot
Simulation](/assets/images/ROS2_Webots_02-b4739c707364368438aa36ef8db9de87.webp)


This will launch the simulation:


1. If the ` ROS2_WEBOTS_HOME  ` environment variable is set, ROS 2 will use the Webots in this folder, regardless of its version.


![ROS2 Webots Robot
Simulation](/assets/images/ROS2_Webots_03-6445656e56b908117193e77ba7298b26.webp)


Edit ` setup.py ` and add the new entry point to ` console_scripts ` with:


The ` webots_ros2  ` package provides an interface between ROS 2 and Webots.
It includes several sub-packages, including ` webots_ros2_driver  ` , which
allows you to start Webots and communicate with it. This interface is used in
most of the following tutorials, so it is required to install it beforehand.
Other sub-packages are mainly examples that show multiple possible
implementations using the interface. In this tutorial, you are going to
install the package and learn how to run one of these examples.


##  Background  


Adding the Cyberbotics repository:


###  1 Install ` webots_ros2  ` 


Source the ROS 2 environment.


Install the ` webots ` , ` webots_ros2 ` package and run simulation examples
on Ubuntu.


Install the package dependencies.


This tutorial is compatible with version ` 2023.1.0 ` of ` webots_ros2 ` and `
Webots ` ` R2023b ` , as well as upcoming versions.


ROS 2 TSC Contribution Report 2023-07-20
Monthly contribution self-reporting
Guidelines
● Each TSC representative: Please fill in your organization’s section with the engineering
activities and other contributions that your organisation has made to ROS 2.
● Please fill your section prior to our next meeting on 2023-07-20
● This report covers work done since the previous TSC meeting: 2023-06-15 - 2023-07-20.
Don't include work done earlier or planned for the future.
● Contributions may come from you, your colleagues, and/or external collaborators that
you're funding to do the work that's reported.
● Each package to which you're contributing should be included on the list of ROS 2
Common Packages.
● When possible, provide links to your contributions (e.g., pull requests).
● Provide enough detail for everyone to understand what was done.
●
● These reports will be included in the published meeting minutes.
● Example:
○ foo_org/bar_pkg
■ Implemented the whizbang feature (PR)
■ Investigated and reported on the superbad bug (comment)
Reports
● Amazon: Aaron Blasdel
○
● Apex.AI: Lyle Johnson
○ ros-tooling/action-ros-ci
■ Use console_direct event handler for colcon test - Christophe Bedard
(merged 2023-07-18)
■ Update distros in tests - Christophe Bedard (merged 2023-07-18)
○ ros-tooling/setup-ros
■ Prefer system packages over pip packages for Linux - Christophe Bedard
(merged 2023-07-18)
■ bDrop support for EOL distros and Ubuntu Bionic - Christophe Bedard
(merged 2023-07-10)
○ ros-tracing/tracetools_analysis
■ Update path to ros2_tracing in notebooks - Christophe Bedard (merged
2023-06-27)
○ ros2/ros2_tracing
■ Create start/pause/resume/stop sub-commands for 'ros2 trace' -
Christophe Bedard (merged 2023-07-10)
○ ros2/rosbag2


More


self.__right_motor.setVelocity(command_motor_right)


At this point, the robot is able to blindly follow your motor commands. But it
will eventually bump into the wall as you order it to move forwards.


    nano hello_webots/launch/robot_launch.py

    from rclpy.node import Node

    ...

    def generate_launch_description():

        ...

        obstacle_avoider = Node(
            package='hello_webots',
            executable='obstacle_avoider',
        )

        return LaunchDescription([
            webots,
            my_robot_driver,
            obstacle_avoider,
            launch.actions.RegisterEventHandler(
                event_handler=launch.event_handlers.OnProcessExit(
                    target_action=webots,
                    on_exit=[launch.actions.EmitEvent(event=launch.events.Shutdown())],
                )
            )
        ])


#include <webots_ros2_driver/plugins/static/Ros2RangeFinder.hpp>


    nano hello_webots/launch/robot_launch.py

    import os
    import launch
    from launch import LaunchDescription
    from ament_index_python.packages import get_package_share_directory
    from webots_ros2_driver.webots_launcher import WebotsLauncher
    from webots_ros2_driver.webots_controller import WebotsController

    def generate_launch_description():
        package_dir = get_package_share_directory('hello_webots')
        robot_description_path = os.path.join(package_dir, 'resource', 'my_robot.urdf')

        webots = WebotsLauncher(
            world=os.path.join(package_dir, 'worlds', 'my_world.wbt')
        )

        my_webot_driver = WebotsController(
            robot_name='my_robot',
            parameters=[
                {'robot_description': robot_description_path},
            ]
        )

        return LaunchDescription([
            webots,
            my_webot_driver,
            launch.actions.RegisterEventHandler(
                # shutdown when webots terminates
                event_handler=launch.event_handlers.OnProcessExit(
                    target_action=webots,
                    on_exit=[launch.actions.EmitEvent(event=launch.events.Shutdown())],
                )
            )
        ])


* [ Home Automation ](/docs/category/home-automation)


From a terminal in your ROS2 workspace run:


    sudo mkdir -p /etc/apt/keyrings
    cd /etc/apt/keyrings
    sudo wget -q https://cyberbotics.com/Cyberbotics.asc


  void Ros2RangeFinder::step() {
    if (!preStep())
      return;


* Tasks


Then proceed to the installation of Webots using:


1. The first method, named ` init(self, ...) ` , is actually the ROS node counterpart of the Python ` __init__(self, ...) ` constructor.


This sets-up the package and adds in the data_files variable the newly added
files: ` my_world.wbt ` , ` my_robot.urdf ` and ` robot_launch.py ` .


Start by importing the `Cyberbotics.asc`` signature file using these commands:


__ [ ROS 2 文档 ](../../../../index.html)


2. If the ` WEBOTS_HOME  ` environment variable is set, ROS 2 will use the Webots in this folder, regardless of its version.


###  Updating the Plugin Declaration


Extend a robot simulation with a reset handler to restart nodes when the reset
button of Webots is pressed.


        * [ Managing large projects ](../../../Intermediate/Launch/Using-ROS2-Launch-For-Large-Projects.html)
      * [ ` tf2  ` ](../../../Intermediate/Tf2/Tf2-Main.html)
        * [ Introducing ` tf2  ` ](../../../Intermediate/Tf2/Introduction-To-Tf2.html)
        * [ Writing a static broadcaster (Python) ](../../../Intermediate/Tf2/Writing-A-Tf2-Static-Broadcaster-Py.html)
        * [ Writing a static broadcaster (C++) ](../../../Intermediate/Tf2/Writing-A-Tf2-Static-Broadcaster-Cpp.html)
        * [ Writing a broadcaster (Python) ](../../../Intermediate/Tf2/Writing-A-Tf2-Broadcaster-Py.html)
        * [ Writing a broadcaster (C++) ](../../../Intermediate/Tf2/Writing-A-Tf2-Broadcaster-Cpp.html)
        * [ Writing a listener (Python) ](../../../Intermediate/Tf2/Writing-A-Tf2-Listener-Py.html)
        * [ Writing a listener (C++) ](../../../Intermediate/Tf2/Writing-A-Tf2-Listener-Cpp.html)
        * [ Adding a frame (Python) ](../../../Intermediate/Tf2/Adding-A-Frame-Py.html)
        * [ Adding a frame (C++) ](../../../Intermediate/Tf2/Adding-A-Frame-Cpp.html)
        * [ Using time (Python) ](../../../Intermediate/Tf2/Learning-About-Tf2-And-Time-Py.html)
        * [ Using time (C++) ](../../../Intermediate/Tf2/Learning-About-Tf2-And-Time-Cpp.html)
        * [ Traveling in time (Python) ](../../../Intermediate/Tf2/Time-Travel-With-Tf2-Py.html)
        * [ Traveling in time (C++) ](../../../Intermediate/Tf2/Time-Travel-With-Tf2-Cpp.html)
        * [ Debugging ](../../../Intermediate/Tf2/Debugging-Tf2-Problems.html)
        * [ Quaternion fundamentals ](../../../Intermediate/Tf2/Quaternion-Fundamentals.html)
        * [ Using stamped datatypes with ` tf2_ros::MessageFilter  ` ](../../../Intermediate/Tf2/Using-Stamped-Datatypes-With-Tf2-Ros-MessageFilter.html)
      * [ Testing ](../../../Intermediate/Testing/Testing-Main.html)
        * [ Running Tests in ROS 2 from the Command Line ](../../../Intermediate/Testing/CLI.html)
        * [ Writing Basic Tests with C++ with GTest ](../../../Intermediate/Testing/Cpp.html)
        * [ Writing Basic Tests with Python ](../../../Intermediate/Testing/Python.html)
      * [ URDF ](../../../Intermediate/URDF/URDF-Main.html)
        * [ Building a visual robot model from scratch ](../../../Intermediate/URDF/Building-a-Visual-Robot-Model-with-URDF-from-Scratch.html)
        * [ Building a movable robot model ](../../../Intermediate/URDF/Building-a-Movable-Robot-Model-with-URDF.html)
        * [ Adding physical and collision properties ](../../../Intermediate/URDF/Adding-Physical-and-Collision-Properties-to-a-URDF-Model.html)
        * [ Using Xacro to clean up your code ](../../../Intermediate/URDF/Using-Xacro-to-Clean-Up-a-URDF-File.html)
        * [ Using URDF with ` robot_state_publisher  ` ](../../../Intermediate/URDF/Using-URDF-with-Robot-State-Publisher.html)
    * [ Advanced ](../../../Advanced.html)
      * [ Enabling topic statistics (C++) ](../../Topic-Statistics-Tutorial/Topic-Statistics-Tutorial.html)
      * [ Using Fast DDS Discovery Server as discovery protocol [community-contributed] ](../../Discovery-Server/Discovery-Server.html)
      * [ Implementing a custom memory allocator ](../../Allocator-Template-Tutorial.html)
      * [ Unlocking the potential of Fast DDS middleware [community-contributed] ](../../FastDDS-Configuration.html)
      * [ Recording a bag from a node (C++) ](../../Recording-A-Bag-From-Your-Own-Node-CPP.html)
      * [ Recording a bag from a node (Python) ](../../Recording-A-Bag-From-Your-Own-Node-Py.html)
      * [ Simulators ](../Simulation-Main.html)
        * [ Webots ](Simulation-Webots.html)
          * Installation (Ubuntu)
          * [ Installation (Windows) ](Installation-Windows.html)
          * [ Installation (macOS) ](Installation-MacOS.html)


Before you can start the launch file, you have to modify the setup.py file to
include the extra files you added:


###  2 Launch the ` webots_ros2_universal_robot  ` example  


source install/local_setup.bash


#include <webots/robot.h>


The ` --dependencies rclpy geometry_msgs webots_ros2_driver ` option specifies
the packages needed by the ` my_webot_driver.py ` plugin in the ` package.xml
` file.


[ Previous  Tello Drone - Getting Started
](/docs/Automation_and_Robotics/Robotics_Simulation/2023-12-16--tellopy-drone-
api/2023-12-16) [ Next  ROS2 Gazebo Robot Simulation
](/docs/Automation_and_Robotics/Robotics_Simulation/2023-11-26--ros2-gazebo-
simulation/2023-11-26)


###  Test Run


#include <sensor_msgs/image_encodings.hpp>
#include <std_msgs/msg/color_rgba.hpp>


[ ![Mike Polinowski :: Dev Notebook](/img/angular_momentum.png) ![Mike
Polinowski :: Dev Notebook](/img/angular_momentum.png) **Mike Polinowski**
](/) [ Docs ](/docs/intro) [ Blog ](/blog) [ Tags ](/docs/tags) [ Search
](/Search) [ About  ](https://mpolinowski.github.io/Personal)


Source this workspace.


Install ` webots_ros2 ` :


      int idx;
      float x, y, z;


You now have to create a **URDF** file to declare the ` MyRobotDriver `
plugin. This will allow the ` webots_ros2_driver ` ROS node to launch the
plugin and connect it to the target robot.


Your robot should go forward and before hitting the wall it should turn
clockwise. You can press Ctrl+F10 in Webots or go to the View menu, Optional
Rendering and Show DistanceSensor Rays to display the range of the distance
sensors of the robot.


namespace webots_ros2_driver {
  void Ros2RangeFinder::init(webots_ros2_driver::WebotsNode *node, std::unordered_map<std::string, std::string> &parameters) {
    Ros2SensorPlugin::init(node, parameters);
    mIsEnabled = false;
    mRangeFinder = wb_robot_get_device(parameters["name"].c_str());


source /opt/ros/rolling/setup.bash


ros2 launch webots_ros2_universal_robot multirobot_launch.py


If you have installed different versions of Webots on your computer, `
webots_ros2  ` will look for Webots at the following locations (in this
order):


Let’s create the launch file to easily launch the simulation and the ROS
controller with a single command:


<?xml version="1.0" ?>
<robot name="TurtleBot3 Burger Webots">
    <webots>
        <device reference="LDS-01" type="Lidar">
            <ros>
                <enabled>true</enabled>
                <updateRate>5</updateRate>
                <topicName>/scan</topicName>
                <alwaysOn>false</alwaysOn>
                <frameName>LDS-01</frameName>
            </ros>
        </device>
        <plugin type="webots_ros2_driver::Ros2IMU">
            <enabled>true</enabled>
            <updateRate>20</updateRate>
            <topicName>/imu</topicName>
            <alwaysOn>false</alwaysOn>
            <frameName>imu_link</frameName>
            <inertialUnitName>inertial_unit</inertialUnitName>
            <gyroName>gyro</gyroName>
            <accelerometerName>accelerometer</accelerometerName>
        </plugin>
        <plugin type="webots_ros2_control::Ros2Control" />
        <!-- type="package_name.file_name.class_name" -->
        <plugin type="webots_ros2_turtlebot.plugin_example.PluginExample">
            <parameterExample>someValue</parameterExample>
        </plugin>
    </webots>
    <ros2_control name="WebotsControl" type="system">
        <hardware>
            <plugin>webots_ros2_control::Ros2ControlSystem</plugin>
        </hardware>
        <joint name="right wheel motor">
            <state_interface name="position"/>
            <command_interface name="velocity"/>
        </joint>
        <joint name="left wheel motor">
            <state_interface name="position"/>
            <command_interface name="velocity"/>
        </joint>
            </ros2_control>
</robot>


  * [ ](../../../../index.html)
  * [ 教程 ](../../../../Tutorials.html)
  * [ Advanced ](../../../Advanced.html)
  * [ Simulators ](../Simulation-Main.html)
  * [ Webots ](Simulation-Webots.html)
  * Installation (Ubuntu)
  * [ Edit on GitHub ](https://github.com/ros2/ros2_documentation/blob/rolling/source/Tutorials/Advanced/Simulators/Webots/Installation-Ubuntu.rst)


The following instructions explain how to start a provided example.


sudo apt install webots


* 2 Launch the ` webots_ros2_universal_robot  ` example


In the ` hello_webots/resource ` folder create a text file named `
my_robot.urdf ` with this content:


Setting the ` WEBOTS_HOME  ` environment variable allows you to start a
specific Webots installation.


sudo apt install ros-iron-webots-ros2


    const int width = wb_range_finder_get_width(mRangeFinder);
    const int height = wb_range_finder_get_height(mRangeFinder);


Run the following command in a terminal.


3. If none of these variables is set, ` webots_ros2  ` will look for Webots in the default installation paths for a compatible version: ` /usr/local/webots  ` and ` /snap/webots/current/usr/share/webots  ` .


**Time:** 10 minutes


    nano hello_webots/setup.py

    from setuptools import find_packages, setup

    package_name = 'hello_webots'
    data_files = []
    data_files.append(('share/ament_index/resource_index/packages', ['resource/' + package_name]))
    data_files.append(('share/' + package_name + '/launch', ['launch/robot_launch.py']))
    data_files.append(('share/' + package_name + '/worlds', ['worlds/my_world.wbt']))
    data_files.append(('share/' + package_name + '/resource', ['resource/my_robot.urdf']))
    data_files.append(('share/' + package_name, ['package.xml']))

    setup(
        name=package_name,
        version='0.0.0',
        packages=find_packages(exclude=['test']),
        data_files=data_files,
        install_requires=['setuptools'],
        zip_safe=True,
        maintainer='user',
        maintainer_email='user.name@mail.com',
        description='TODO: Package description',
        license='TODO: License declaration',
        tests_require=['pytest'],
        entry_points={
            'console_scripts': [
                'my_robot_driver = hello_webots.my_robot_driver:main',
            ],
        },
    )


Implementing a ROS 2 node that avoids obstacles using the robot’s distance
sensors with the ` webots_ros2_driver ` interface.


■ Update CDR dependency for XCDR2 support - Sam Nosenzo (merged
2023-07-13)
■ - use yarn auth token - Sam Nosenzo (merged 2023-07-13)
■ Rename omgidl-support to omgidl - Sam
Nosenzo (merged 2023-07-13)
■ Fix CI - Sam Nosenzo (merged 2023-07-13)
■ Clean up jest output - Sam Nosenzo (merged 2023-07-13)
■ Fix publish - Sam Nosenzo (merged 2023-07-13)
■ Update CI for deployment - Sam Nosenzo (merged 2023-07-13)
■ Merge parser and grammar packages into
single omgidl-parser - Sam Nosenzo (merged
2023-07-12)
■ Update README.md's - Sam Nosenzo (merged 2023-07-12)
■ Move mapping of idl numeric primitives to cdr serialization types from idl
grammar - Sam Nosenzo (merged 2023-07-12)
■ Better support for OMGIDL schemas - Sam Nosenzo (merged
2023-07-11)
■ Support for Enums - Sam Nosenzo (merged 2023-06-26)
■ Update Rosmsg2 deserializer to be used for omgidl schema - Sam
Nosenzo (merged 2023-06-26)
○ foxglove/ros-foxglove-bridge
■ Fix segfault due to invalid iterator - Hans-Joachim Krauch (merged
2023-07-17)
■ Server code improvements - Hans-Joachim Krauch (merged 2023-07-14)
■ Release/0.7.0 - Hans-Joachim Krauch (merged 2023-07-12)
■ Support building with boost asio - Hans-Joachim Krauch (merged
2023-07-11)
■ Avoid usage of tmpnam() for creating random filename - Hans-Joachim
Krauch (merged 2023-07-11)
■ Implement ws-protocol's fetchAsset specification -
Hans-Joachim Krauch (merged 2023-07-10)
■ Use --include-eol-distros for rosdep to fix
melodic builds - Hans-Joachim Krauch (merged 2023-07-07)
■ Reduce logging severity for parameter retrieval logs - Hans-Joachim
Krauch (merged 2023-07-06)
■ Release/0.6.4 - Hans-Joachim Krauch (merged 2023-07-05)
■ Assume publisher qos depth of 1 if the middleware reports the qos history
as unknown - Hans-Joachim Krauch (merged 2023-07-05)
■ devcontainer: Use --include-eol-distros for rosdep
update - Hans-Joachim Krauch (merged 2023-06-30)


##  Tasks  


Create a new package named ` hello_webots ` from the ` src ` folder of your
ROS2 workspace. Change the current directory of your terminal to ` ros2_ws/src
` and run:


    nano hello_webots/hello_webots/obstacle_avoider.py

    import rclpy
    from rclpy.node import Node
    from sensor_msgs.msg import Range
    from geometry_msgs.msg import Twist

    MAX_RANGE = 0.15

    class ObstacleAvoider(Node):
        def __init__(self):
            super().__init__('obstacle_avoider')

            self.__publisher = self.create_publisher(Twist, 'cmd_vel', 1)

            self.create_subscription(Range, 'left_sensor', self.__left_sensor_callback, 1)
            self.create_subscription(Range, 'right_sensor', self.__right_sensor_callback, 1)

        def __left_sensor_callback(self, message):
            self.__left_sensor_value = message.range

        def __right_sensor_callback(self, message):
            self.__right_sensor_value = message.range

            command_message = Twist()

            command_message.linear.x = 0.1

            if self.__left_sensor_value < 0.9 * MAX_RANGE or self.__right_sensor_value < 0.9 * MAX_RANGE:
                command_message.angular.z = -2.0

            self.__publisher.publish(command_message)


It is recommended to understand basic ROS principles covered in the beginner [
教程  ](../../../../Tutorials.html) . In particular, [ Creating a workspace
](../../../Beginner-Client-Libraries/Creating-A-Workspace/Creating-A-
Workspace.html) and [ Creating a package  ](../../../Beginner-Client-
Libraries/Creating-Your-First-ROS2-Package.html) are useful prerequisites.


Open a second terminal and send a command with:


##  Robot Simulation and Control


Build the package using ` colcon  ` .


    * [ Releasing a Package ](../../../../How-To-Guides/Releasing/Releasing-a-Package.html)
      * [ First Time Release ](../../../../How-To-Guides/Releasing/First-Time-Release.html)
      * [ Subsequent Releases ](../../../../How-To-Guides/Releasing/Subsequent-Releases.html)
      * [ Release Team / Repository ](../../../../How-To-Guides/Releasing/Release-Team-Repository.html)
      * [ Release Track ](../../../../How-To-Guides/Releasing/Release-Track.html)
    * [ Using Python Packages with ROS 2 ](../../../../How-To-Guides/Using-Python-Packages.html)
    * [ Porting RQt plugins to Windows ](../../../../How-To-Guides/RQt-Port-Plugin-Windows.html)
    * [ Running ROS 2 nodes in Docker [community-contributed] ](../../../../How-To-Guides/Run-2-nodes-in-single-or-separate-docker-containers.html)
    * [ Visualizing ROS 2 data with Foxglove Studio ](../../../../How-To-Guides/Visualizing-ROS-2-Data-With-Foxglove-Studio.html)
    * [ ROS 2 Package Maintainer Guide ](../../../../How-To-Guides/Package-maintainer-guide.html)
    * [ Building a custom Debian package ](../../../../How-To-Guides/Building-a-Custom-Debian-Package.html)
    * [ Building ROS 2 with tracing ](../../../../How-To-Guides/Building-ROS-2-with-Tracing.html)
    * [ Topics vs Services vs Actions ](../../../../How-To-Guides/Topics-Services-Actions.html)
    * [ Using variants ](../../../../How-To-Guides/Using-Variants.html)
    * [ Using the ` ros2  param  ` command-line tool ](../../../../How-To-Guides/Using-ros2-param.html)
    * [ Using ` ros1_bridge  ` with upstream ROS on Ubuntu 22.04 ](../../../../How-To-Guides/Using-ros1_bridge-Jammy-upstream.html)
    * [ Disabling Zero Copy Loaned Messages ](../../../../How-To-Guides/Disabling-ZeroCopy-loaned-messages.html)
    * [ ROS 2 on Raspberry Pi ](../../../../How-To-Guides/Installing-on-Raspberry-Pi.html)
    * [ Using Callback Groups ](../../../../How-To-Guides/Using-callback-groups.html)
    * [ Setup ROS 2 with VSCode and Docker [community-contributed] ](../../../../How-To-Guides/Setup-ROS-2-with-VSCode-and-Docker-Container.html)
    * [ Building RQt from source ](../../../../How-To-Guides/RQt-Source-Install.html)
      * [ Building RQt from source on macOS ](../../../../How-To-Guides/RQt-Source-Install-MacOS.html)
      * [ Building RQt from source on Windows 10 ](../../../../How-To-Guides/RQt-Source-Install-Windows10.html)
  * [ 概念 ](../../../../Concepts.html)
    * [ The ROS_DOMAIN_ID ](../../../../Concepts/About-Domain-ID.html)
    * [ 关于不同的ROS2 DDS/RTPS供应商 ](../../../../Concepts/About-Different-Middleware-Vendors.html)
    * [ About logging and logger configuration ](../../../../Concepts/About-Logging.html)
    * [ About Quality of Service settings ](../../../../Concepts/About-Quality-of-Service-Settings.html)
    * [ About ROS 2 client libraries ](../../../../Concepts/About-ROS-2-Client-Libraries.html)
    * [ About ROS 2 interfaces ](../../../../Concepts/About-ROS-Interfaces.html)
    * [ About parameters in ROS 2 ](../../../../Concepts/About-ROS-2-Parameters.html)
    * [ 执行器 ](../../../../Concepts/About-Executors.html)
    * [ About topic statistics ](../../../../Concepts/About-Topic-Statistics.html)
    * [ 使用命令行工具进行内省 ](../../../../Concepts/About-Command-Line-Tools.html)
    * [ Overview and usage of RQt ](../../../../Concepts/About-RQt.html)
    * [ 关于组合 ](../../../../Concepts/About-Composition.html)
    * [ 对于ament和catkin的混合（catment） ](../../../../Concepts/About-Catment.html)
    * [ 关于交叉编译 ](../../../../Concepts/About-Cross-Compilation.html)
    * [ About ROS 2 Security ](../../../../Concepts/About-Security.html)
    * [ About tf2 ](../../../../Concepts/About-Tf2.html)


[ Edit this page
](https://github.com/facebook/docusaurus/tree/main/packages/create-
docusaurus/templates/shared/docs/Automation_and_Robotics/Robotics_Simulation/2023-11-26
--ros2-webots/index.md)


In addition to your custom plugin, the webots_ros2_driver will parse the `
<device> ` tags referring to the DistanceSensor nodes and use the standard
parameters in the ` <ros> ` tags to enable the sensors and name their topics.


    nano hello_webots/setup.py

    'console_scripts': [
        'my_robot_driver = hello_webots.my_robot_driver:main',
        'obstacle_avoider = hello_webots.obstacle_avoider:main'
    ],


#  ROS2 Webots Robot Simulation


Copyright © 2024 Mike Polinowski, INSTAR Deutschland GmbH, Shenzhen - China.


  * [ 安装 ](../../../../Installation.html)
    * [ Ubuntu (Debian) ](../../../../Installation/Ubuntu-Install-Debians.html)
    * [ Windows（二进制） ](../../../../Installation/Windows-Install-Binary.html)
    * [ RHEL (RPM) ](../../../../Installation/RHEL-Install-RPMs.html)
    * [ 替代方案 ](../../../../Installation/Alternatives.html)
      * [ Ubuntu (source) ](../../../../Installation/Alternatives/Ubuntu-Development-Setup.html)
      * [ Ubuntu (binary) ](../../../../Installation/Alternatives/Ubuntu-Install-Binary.html)
      * [ Windows (source) ](../../../../Installation/Alternatives/Windows-Development-Setup.html)
      * [ RHEL (source) ](../../../../Installation/Alternatives/RHEL-Development-Setup.html)
      * [ RHEL (binary) ](../../../../Installation/Alternatives/RHEL-Install-Binary.html)
      * [ macOS (source) ](../../../../Installation/Alternatives/macOS-Development-Setup.html)
      * [ Latest development (source) ](../../../../Installation/Alternatives/Latest-Development-Setup.html)
    * [ 维护源代码检出 ](../../../../Installation/Maintaining-a-Source-Checkout.html)
    * [ 使用预发布的二进制文件进行测试 ](../../../../Installation/Testing.html)
    * [ DDS实现 ](../../../../Installation/DDS-Implementations.html)
      * [ Connext security plugins ](../../../../Installation/DDS-Implementations/Install-Connext-Security-Plugins.html)
      * [ RTI Connext DDS ](../../../../Installation/DDS-Implementations/Install-Connext-University-Eval.html)
      * [ Eclipse Cyclone DDS ](../../../../Installation/DDS-Implementations/Working-with-Eclipse-CycloneDDS.html)
      * [ GurumNetworks GurumDDS ](../../../../Installation/DDS-Implementations/Working-with-GurumNetworks-GurumDDS.html)
      * [ eProsima Fast DDS ](../../../../Installation/DDS-Implementations/Working-with-eProsima-Fast-DDS.html)
  * [ 发行版 ](../../../../Releases.html)
    * [ Iron Irwini ( ` iron  ` ) ](../../../../Releases/Release-Iron-Irwini.html)
      * [ Iron Irwini Changelog ](../../../../Releases/Iron-Irwini-Complete-Changelog.html)
    * [ Humble Hawksbill ( ` humble  ` ) ](../../../../Releases/Release-Humble-Hawksbill.html)
      * [ Humble Hawksbill changelog ](../../../../Releases/Humble-Hawksbill-Complete-Changelog.html)
    * [ Foxy Fitzroy ( ` foxy  ` ) ](../../../../Releases/Release-Foxy-Fitzroy.html)
    * [ Rolling Ridley ( ` rolling  ` ) ](../../../../Releases/Release-Rolling-Ridley.html)
    * [ Development Distribution ](../../../../Releases/Development.html)
      * [ Jazzy Jalisco (codename ‘jazzy’; May, 2024) ](../../../../Releases/Release-Jazzy-Jalisco.html)
    * [ End-of-Life Distributions ](../../../../Releases/End-of-Life.html)
      * [ Galactic Geochelone ( ` galactic  ` ) ](../../../../Releases/Release-Galactic-Geochelone.html)
        * [ Galactic Geochelone changelog ](../../../../Releases/Galactic-Geochelone-Complete-Changelog.html)
      * [ Eloquent Elusor ( ` eloquent  ` ) ](../../../../Releases/Release-Eloquent-Elusor.html)
      * [ Dashing Diademata ( ` dashing  ` ) ](../../../../Releases/Release-Dashing-Diademata.html)
      * [ Crystal Clemmys ( ` crystal  ` ) ](../../../../Releases/Release-Crystal-Clemmys.html)
      * [ Bouncy Bolson ( ` bouncy  ` ) ](../../../../Releases/Release-Bouncy-Bolson.html)
      * [ Ardent Apalone ( ` ardent  ` ) ](../../../../Releases/Release-Ardent-Apalone.html)
      * [ Beta 3 ( ` r2b3  ` ) ](../../../../Releases/Beta3-Overview.html)
      * [ Beta 2 ( ` r2b2  ` ) ](../../../../Releases/Beta2-Overview.html)
      * [ Beta 1 ( ` Asphalt  ` ) ](../../../../Releases/Beta1-Overview.html)


    sudo apt install python3-pip python3-rosdep python3-colcon-common-extensions
    sudo rosdep init && rosdep update
    rosdep install --from-paths src --ignore-src --rosdistro rolling


The robot will use a standard ROS node to detect the wall and send motor
commands to avoid it. In the ` hello_webots/hello_webots/ ` folder, create a
file named `obstacle_avoider.py`` with this code:


The Webots reset button reverts the world to the initial state and restarts
controllers. It is convenient as it quickly resets the simulation, but in the
context of ROS 2, robot controllers are not started again making the
simulation stop. The reset handler allows you to restart specific nodes or
perform additional actions when the reset button in Webots is pressed.


    cd ~/ros2_ws
    colcon build
    source install/local_setup.bash
    ros2 launch hello_webots robot_launch.py


    if (mAlwaysOn)
      return;


##  Installation


The ` webots_ros2_driver ` sub-package automatically creates a ROS2 interface
for most sensors. We can create custom plugin as a ROS node to access the
Webots robot API and create custom topics and services to control your robot.


      float *data = (float *)mPointCloudMessage.data.data();
      for (int j = 0; j < height; j++) {
        for (int i = 0; i < width; i++) {
          idx = i + j * width;
          x = image[idx];
          y = -(i - cx) * x / fx;
          z = -(j - cy) * x / fy;
          memcpy(data + idx * 3, &x, sizeof(float));
          memcpy(data + idx * 3 + 1, &y, sizeof(float));
          memcpy(data + idx * 3 + 2, &z, sizeof(float));
        }
      }
      mPointCloudPublisher->publish(mPointCloudMessage);
    }
  }
}  // namespace webots_ros2_driver


    if (mAlwaysOn) {
      wb_range_finder_enable(mRangeFinder, mPublishTimestepSyncedMs);
      mIsEnabled = true;
    }
  }


> Excerpt from [ ROS 2 Documentation (IRON)
> ](https://docs.ros.org/en/iron/index.html) : The Robot Operating System
> (ROS) is a set of software libraries and tools for building robot
> applications. From drivers and state-of-the-art algorithms to powerful
> developer tools, ROS has the open source tools you need for your next
> robotics project.


      * [ Tello Drone - Getting Started ](/docs/Automation_and_Robotics/Robotics_Simulation/2023-12-16--tellopy-drone-api/2023-12-16)
      * [ ROS2 Webots Robot Simulation ](/docs/Automation_and_Robotics/Robotics_Simulation/2023-11-26--ros2-webots/2023-11-26)
      * [ ROS2 Gazebo Robot Simulation ](/docs/Automation_and_Robotics/Robotics_Simulation/2023-11-26--ros2-gazebo-simulation/2023-11-26)
      * [ ROS2 Graph Concepts ](/docs/Automation_and_Robotics/Robotics_Simulation/2023-11-24--ros2-graph/2023-11-24)
      * [ Gazebo & ROS2 Basic Installation ](/docs/Automation_and_Robotics/Robotics_Simulation/2023-11-19--ros2-gazebo-installation/2023-11-19)


On reset, Webots kills all driver nodes. Therefore, to start them again after
reset, you should set the `respawn`` property of the driver node in the launch
file to True. It will ensure driver nodes are up and running after the reset:


(https://github.com/cyberbotics/webots_ros2/pull/810).
■ Added deprecation message when declaring driver node in launch file
(https://github.com/cyberbotics/webots_ros2/pull/815).
○ Version 2023.1.2 of webots_ros2 (to be released soon):
■ Fixed Ros2Supervisor import and remove Webots node
(https://github.com/cyberbotics/webots_ros2/pull/824).
■ Added new package webots_ros2_husarion with ROSbot and ROSbot XL
demos (https://github.com/cyberbotics/webots_ros2/pull/770).
○ Other small fixes on the webots_ros2 repository:
■ Fixed world warnings for R2023b
(https://github.com/cyberbotics/webots_ros2/pull/794).
■ Fixed default Webots version on repository
(https://github.com/cyberbotics/webots_ros2/pull/812 &
https://github.com/cyberbotics/webots_ros2/pull/813).
○ Documentation:
■ Added new Reset handler tutorial
(https://github.com/cyberbotics/ros2_documentation/pull/12).
■ Updated main tutorials to new Webots version
(https://github.com/cyberbotics/ros2_documentation/pull/11).
■ Added new Ros2Supervisor tutorial (currently in review process
https://github.com/cyberbotics/ros2_documentation/pull/18)
● Community: Francisco Martín
○ Push ROSCon Madrid 2023
○ Spanish Local Users Group 20/07/023


[ ROS 2 文档 ](../../../../index.html)


* [ Robotics & Simulation ](/docs/category/robotics--simulation)


**Tutorial level:** Advanced


This node will create a publisher for the command and subscribe to the sensors
topics here:


© Copyright 2023, GrantLi.


  * [ Camera ](https://github.com/cyberbotics/webots_ros2/wiki/References-Devices#camera-device)
  * [ Compass ](https://github.com/cyberbotics/webots_ros2/wiki/References-Devices#compass-device)
  * [ DistanceSensor ](https://github.com/cyberbotics/webots_ros2/wiki/References-Devices#distance-sensor-device)
  * [ GPS ](https://github.com/cyberbotics/webots_ros2/wiki/References-Devices#gps-device)
  * [ Lidar ](https://github.com/cyberbotics/webots_ros2/wiki/References-Devices#lidar-device)
  * [ LightSensor ](https://github.com/cyberbotics/webots_ros2/wiki/References-Devices#light-sensor-device)
  * [ RangeFinder ](https://github.com/cyberbotics/webots_ros2/wiki/References-Devices#range-finder-device)
  * [ Receiver ](https://github.com/cyberbotics/webots_ros2/wiki/References-Devices#receiver-device)
  * [ IMU ](https://github.com/cyberbotics/webots_ros2/wiki/References-Devices#imu-device)


  * [ Robotics ](/docs/tags/robotics)
  * [ Simulation ](/docs/tags/simulation)
  * [ ROS ](/docs/tags/ros)
  * [ Webots ](/docs/tags/webots)


* [ Machine Learning, AI and Computer Vision ](/docs/category/machine-learning-ai-and-computer-vision)


> The purpose of this tutorial is to show a basic example with a minimum
> number of dependencies. However, you could avoid the use of this plugin by
> using another webots_ros2 sub-package named webots_ros2_control, introducing
> a new dependency. This other sub-package creates an interface with the
> ros2_control package that facilitates the control of a differential wheeled
> robot.


    cd ~/ros2_ws
    source install/local_setup.bash


    mkdir hello_webots/{launch,worlds}
    wget https://docs.ros.org/en/iron/_downloads/5ad123fc6a8f1ea79553d5039728084a/my_world.wbt -P hello_webots/worlds

    hello_webots/
    ├── hello_webots
    │   ├── __init__.py
    │   └── my_webot_driver.py
    ├── launch
    ├── LICENSE
    ├── package.xml
    ├── resource
    │   └── hello_webots
    ├── setup.cfg
    ├── setup.py
    ├── test
    │   ├── test_copyright.py
    │   ├── test_flake8.py
    │   └── test_pep257.py
    └── worlds
    │   └── my_world.wbt


sudo apt-get install ros-rolling-webots-ros2


The Webots software should be installed in order to use the ` webots_ros2  `
interface. You can follow the [ installation procedure
](https://cyberbotics.com/doc/guide/installation-procedure) or [ build it from
sources ](https://github.com/cyberbotics/webots/wiki/Linux-installation/) .


    nano ~/ros2_ws/src/hello_webots/launch/robot_launch.py

    def generate_launch_description():
        robot_driver = WebotsController(
            robot_name='my_robot',
            parameters=[
                {'robot_description': robot_description_path}
            ],

            # Every time one resets the simulation the controller is automatically respawned
            respawn=True
        )


mkdir -p ~/ros2_ws/src


    import rclpy
    from geometry_msgs.msg import Twist

    HALF_DISTANCE_BETWEEN_WHEELS = 0.045
    WHEEL_RADIUS = 0.025

    class MyRobotDriver:
        def init(self, webots_node, properties):
            self.__robot = webots_node.robot

            self.__left_motor = self.__robot.getDevice('left wheel motor')
            self.__right_motor = self.__robot.getDevice('right wheel motor')

            self.__left_motor.setPosition(float('inf'))
            self.__left_motor.setVelocity(0)

            self.__right_motor.setPosition(float('inf'))
            self.__right_motor.setVelocity(0)

            self.__target_twist = Twist()

            rclpy.init(args=None)
            self.__node = rclpy.create_node('my_webot_driver')
            self.__node.create_subscription(Twist, 'cmd_vel', self.__cmd_vel_callback, 1)

        def __cmd_vel_callback(self, twist):
            self.__target_twist = twist

        def step(self):
            rclpy.spin_once(self.__node, timeout_sec=0)

            forward_speed = self.__target_twist.linear.x
            angular_speed = self.__target_twist.angular.z

            command_motor_left = (forward_speed - angular_speed * HALF_DISTANCE_BETWEEN_WHEELS) / WHEEL_RADIUS
            command_motor_right = (forward_speed + angular_speed * HALF_DISTANCE_BETWEEN_WHEELS) / WHEEL_RADIUS

            self.__left_motor.setVelocity(command_motor_left)


This will launch the simulation:


■ Fix for rosbag2_transport::Recorder failures due to the unhandled
exceptions - Michael Orlov (merged 2023-06-17)
○
● Bosch: Christian Henkel
○ rosdistro
■ Adding libbdd
○ rclc
■ rclc_executor: improve enum type names
● Canonical: Jeremie Deray
○
● eProsima: Jaime Martin Losa
○ Fast DDS 2.11.0
■ Some new minor features and improvements
○ Visual ROS
■ Video demonstrating the tool.
○ New Micro-ROS release
■ ROS 2 Iron Support
● Foxglove: Adrian Macneil
○ foxglove/cdr
■ Minor version update for XCDR2 support - Sam Nosenzo (merged
2023-07-10)
○ foxglove/mcap
■ cpp: re-use allocations for message indexes in writer - james-rms
(merged 2023-07-19)
■ specification: add omgidl to appendix - james-rms (merged 2023-07-12)
■ mcap filter: don't die on schema id 0 - Jacob Bandes-Storch (merged
2023-07-07)
■ Bump mcap-protobuf-support to 0.4.0 - Jacob Bandes-Storch (merged
2023-07-06)
■ Tighten python protobuf dependency to <=4.21.11 to fix
potential segfault - Hans-Joachim Krauch (merged 2023-07-06)
■ Add header to logos section; link each logo to website - Esther S. Weon
(merged 2023-06-29)
■ Add company logos to MCAP homepage - Esther S. Weon (merged
2023-06-20)
○ foxglove/omgidl
■ Document known limitations of IDL - Sam Nosenzo (merged 2023-07-17)
■ Fail on mutable and appendable annotations - Sam Nosenzo (merged
2023-07-14)
■ Nits - Adrian Macneil (merged 2023-07-13)


Contents


  * The init method always takes two arguments:
    * The webots_node argument contains a reference on the Webots instance.
    * The properties argument is a dictionary created from the XML tags given in the URDF files ( ` my_robot.urdf ` file see below) and allows you to pass parameters to the controller.
  * The robot instance from the simulation ` self.__robot ` can be used to access the Webots robot API. Then, it gets the two motor instances and initializes them with a target position and a target velocity. Finally a ROS node is created and a callback method is registered for a ROS topic named ` /cmd_vel ` that will handle Twist messages.


##  Prerequisites  


    cd ~/ros2_ws
    colcon build
    source install/local_setup.bash
    ros2 launch hello_webots robot_launch.py


###  Creating a ROS Sensor Node


###  Create the Package Structure


    nano hello_webots/resource/my_robot.urdf

    <?xml version="1.0" ?>
    <robot name="My robot">
        <webots>
            <plugin type="hello_webots.my_webot_driver.MyRobotDriver" />
        </webots>
    </robot>


    if (mCameraInfoPublisher->get_subscription_count() > 0)
      mCameraInfoPublisher->publish(mCameraInfoMessage);


    if (mIsEnabled) {
      publishImage();
      publishPointCloud();
    }


    def main(args=None):
        rclpy.init(args=args)
        avoider = ObstacleAvoider()
        rclpy.spin(avoider)
        # Destroy the node explicitly
        # (optional - otherwise it will be done automatically
        # when the garbage collector destroys the node object)
        avoider.destroy_node()
        rclpy.shutdown()

    if __name__ == '__main__':
        main()


Alternatively, you can also let ` webots_ros2  ` download and install Webots
automatically. This option appears when you launch an example of the package
and no Webots installation is found.


In ` my_robot.urdf ` replace the whole contents with:


Install ` webots_ros2  ` distributed package  Install ` webots_ros2  ` from
sources


This will add an entry point for the ` obstacle_avoider ` node.


![ROS2 Webots Robot
Simulation](/assets/images/ROS2_Webots_01-f73ff01f788c47cf0979b3848ff6cfa7.webp)


The node sends a message to the ` /cmd_vel ` topic when a measurement from the
right sensor is received. The ` command_message ` will register at least a
forward speed in ` linear.x ` in order to make the robot move when no obstacle
is detected. If any of the two sensors detect an obstacle, ` command_message `
will also register a rotational speed in ` angular.z ` in order to make the
robot turn right:


* Background


###  Test Run


    cd ~/ros2_ws
    git clone --recurse-submodules https://github.com/cyberbotics/webots_ros2.git src/webots_ros2


Go to the file ` robot_launch.py ` and add the obstacle avoider to `
generate_launch_description() ` with:


Open ` hello_webots/hello_webots/my_webot_driver.py ` and replace its contents
with the following:


    // Point cloud publisher
    mPointCloudPublisher = mNode->create_publisher<sensor_msgs::msg::PointCloud2>(mTopicName + mPointCloudSuffix,
                                                                                rclcpp::SensorDataQoS().reliable());
    mPointCloudMessage.header.frame_id = mFrameName;
    mPointCloudMessage.fields.resize(3);
    mPointCloudMessage.fields[0].name = "x";
    mPointCloudMessage.fields[0].offset = 0;
    mPointCloudMessage.fields[0].datatype = sensor_msgs::msg::PointField::FLOAT32;
    mPointCloudMessage.fields[0].count = 1;
    mPointCloudMessage.fields[1].name = "y";
    mPointCloudMessage.fields[1].offset = 4;
    mPointCloudMessage.fields[1].datatype = sensor_msgs::msg::PointField::FLOAT32;
    mPointCloudMessage.fields[1].count = 1;
    mPointCloudMessage.fields[2].name = "z";
    mPointCloudMessage.fields[2].offset = 8;
    mPointCloudMessage.fields[2].datatype = sensor_msgs::msg::PointField::FLOAT32;
    mPointCloudMessage.fields[2].count = 1;
    mPointCloudMessage.is_bigendian = false;
    mPointCloudMessage.width = width;
    mPointCloudMessage.height = height;
    mPointCloudMessage.point_step = 12;
    mPointCloudMessage.row_step = width * 12;
    mPointCloudMessage.data.resize(width * 12 * height);


![TST, Hongkong](/assets/images/photo-
kt443t6d_64hdh43hfh6dgjdfhg4_d-252551beac0b36b4ba53ccd380897f8e.jpg)


The ` WebotsLauncher ` object is a custom action that allows you to start a
Webots simulation instance. You have to specify in the constructor which world
file the simulator will open.


    mCameraInfoSuffix = parameters.count("cameraInfoSuffix") ? parameters["cameraInfoSuffix"] : "/camera_info";
    mImageSuffix = parameters.count("imageSuffix") ? parameters["imageSuffix"] : "/image";
    mPointCloudSuffix = parameters.count("pointCloudSuffix") ? parameters["pointCloudSuffix"] : "/point_cloud";


          * [ Setting up a robot simulation (Basic) ](Setting-Up-Simulation-Webots-Basic.html)
          * [ Setting up a robot simulation (Advanced) ](Setting-Up-Simulation-Webots-Advanced.html)
        * [ Gazebo ](../Gazebo/Simulation-Gazebo.html)
          * [ Setting up a robot simulation (Gazebo) ](../Gazebo/Gazebo.html)
      * [ Security ](../../Security/Security-Main.html)
        * [ Setting up security ](../../Security/Introducing-ros2-security.html)
        * [ Understanding the security keystore ](../../Security/The-Keystore.html)
        * [ Ensuring security across machines ](../../Security/Security-on-Two.html)
        * [ Examining network traffic ](../../Security/Examine-Traffic.html)
        * [ Setting access controls ](../../Security/Access-Controls.html)
        * [ Deployment Guidelines ](../../Security/Deployment-Guidelines.html)
    * [ Demos ](../../../Demos.html)
      * [ Using quality-of-service settings for lossy networks ](../../../Demos/Quality-of-Service.html)
      * [ Managing nodes with managed lifecycles ](../../../Demos/Managed-Nodes.html)
      * [ Setting up efficient intra-process communication ](../../../Demos/Intra-Process-Communication.html)
      * [ Recording and playing back data with ` rosbag  ` using the ROS 1 bridge ](../../../Demos/Rosbag-with-ROS1-Bridge.html)
      * [ Understanding real-time programming ](../../../Demos/Real-Time-Programming.html)
      * [ Experimenting with a dummy robot ](../../../Demos/dummy-robot-demo.html)
      * [ Logging ](../../../Demos/Logging-and-logger-configuration.html)
      * [ Creating a content filtering subscription ](../../../Demos/Content-Filtering-Subscription.html)
    * [ Miscellaneous ](../../../Miscellaneous.html)
      * [ Deploying on IBM Cloud Kubernetes [community-contributed] ](../../../Miscellaneous/Deploying-ROS-2-on-IBM-Cloud.html)
      * [ Using Eclipse Oxygen with ` rviz2  ` [community-contributed] ](../../../Miscellaneous/Eclipse-Oxygen-with-ROS-2-and-rviz2.html)
      * [ Building a real-time Linux kernel [community-contributed] ](../../../Miscellaneous/Building-Realtime-rt_preempt-kernel-for-ROS-2.html)
      * [ Building a package with Eclipse 2021-06 ](../../../Miscellaneous/Building-ROS2-Package-with-eclipse-2021-06.html)
  * [ 操作指南 ](../../../../How-To-Guides.html)
    * [ Installation troubleshooting ](../../../../How-To-Guides/Installation-Troubleshooting.html)
    * [ Developing a ROS 2 package ](../../../../How-To-Guides/Developing-a-ROS-2-Package.html)
    * [ ament_cmake user documentation ](../../../../How-To-Guides/Ament-CMake-Documentation.html)
    * [ ament_cmake_python user documentation ](../../../../How-To-Guides/Ament-CMake-Python-Documentation.html)
    * [ Migrating launch files from ROS 1 to ROS 2 ](../../../../How-To-Guides/Launch-files-migration-guide.html)
    * [ Using Python, XML, and YAML for ROS 2 Launch Files ](../../../../How-To-Guides/Launch-file-different-formats.html)
    * [ Using ROS 2 launch to launch composable nodes ](../../../../How-To-Guides/Launching-composable-nodes.html)
    * [ Migrating YAML parameter files from ROS 1 to ROS 2 ](../../../../How-To-Guides/Parameters-YAML-files-migration-guide.html)
    * [ Passing ROS arguments to nodes via the command-line ](../../../../How-To-Guides/Node-arguments.html)
    * [ Synchronous vs. asynchronous service clients ](../../../../How-To-Guides/Sync-Vs-Async.html)
    * [ DDS tuning information ](../../../../How-To-Guides/DDS-tuning.html)
    * [ rosbag2: Overriding QoS Policies ](../../../../How-To-Guides/Overriding-QoS-Policies-For-Recording-And-Playback.html)
    * [ Working with multiple ROS 2 middleware implementations ](../../../../How-To-Guides/Working-with-multiple-RMW-implementations.html)
    * [ Cross-compilation ](../../../../How-To-Guides/Cross-compilation.html)


  * Installation
  * Robot Simulation and Control
    * Create the Package Structure
    * Edit the Driver Plugin
    * Declare the Plugin
    * Create the Launch File
    * Add added Files to Plugin Setup
    * Test Run
  * Integrating Sensors
    * Updating the Plugin Declaration
    * Creating a ROS Sensor Node
    * Add the new Node to Plugin Setup
    * Test Run
  * Adding Reset Handler


ros2 launch webots_ros2_universal_robot multirobot_launch.py


export WEBOTS_HOME=/usr/local/webots


    def __right_sensor_callback(self, message):
        self.__right_sensor_value = message.range

        command_message = Twist()

        command_message.linear.x = 0.1

        if self.__left_sensor_value < 0.9 * MAX_RANGE or self.__right_sensor_value < 0.9 * MAX_RANGE:
            command_message.angular.z = -2.0

        self.__publisher.publish(command_message)


// Copyright 1996-2023 Cyberbotics Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.


  RCLCPP_INFO(
    logger_,
    "Subscribing to the map topic (%s) with %s durability",
    map_topic_.c_str(),
    map_subscribe_transient_local_ ? "transient local" : "volatile");


7 tasks


Sorry, something went wrong.


edited


Member


This state will allow the node to process information and be fully setup to
run. The configuration stage, triggering the ` on_configure()  ` method, will
setup all parameters, ROS networking interfaces, and for safety systems, all
dynamically allocated memory. The activation stage, triggering the `
on_activate()  ` method, will active the ROS networking interfaces and set any
states in the program to start processing information.


[
![@SteveMacenski](https://avatars.githubusercontent.com/u/14944147?s=80&u=0925d37e9d3569c71d930114b66e6394c2efb3c6&v=4)
](/SteveMacenski)


        * [ Common Sensor Messages ](../setup_guides/sensors/setup_sensors.html#common-sensor-messages)
      * [ Simulating Sensors using Gazebo ](../setup_guides/sensors/setup_sensors.html#simulating-sensors-using-gazebo)
        * [ Adding Gazebo Plugins to a URDF ](../setup_guides/sensors/setup_sensors.html#adding-gazebo-plugins-to-a-urdf)
        * [ Launch and Build Files ](../setup_guides/sensors/setup_sensors.html#launch-and-build-files)
        * [ Build, Run and Verification ](../setup_guides/sensors/setup_sensors.html#build-run-and-verification)
      * [ Mapping and Localization ](../setup_guides/sensors/setup_sensors.html#mapping-and-localization)
      * [ Costmap 2D ](../setup_guides/sensors/setup_sensors.html#costmap-2d)
        * [ Configuring nav2_costmap_2d ](../setup_guides/sensors/setup_sensors.html#configuring-nav2-costmap-2d)
        * [ Build, Run and Verification ](../setup_guides/sensors/setup_sensors.html#id2)
      * [ Conclusion ](../setup_guides/sensors/setup_sensors.html#conclusion)
    * [ Setting Up the Robot’s Footprint ](../setup_guides/footprint/setup_footprint.html)
      * [ Footprint Introduction ](../setup_guides/footprint/setup_footprint.html#footprint-introduction)
      * [ Configuring the Robot’s Footprint ](../setup_guides/footprint/setup_footprint.html#configuring-the-robot-s-footprint)
      * [ Build, Run and Verification ](../setup_guides/footprint/setup_footprint.html#build-run-and-verification)
      * [ Visualizing Footprint in RViz ](../setup_guides/footprint/setup_footprint.html#visualizing-footprint-in-rviz)
      * [ Conclusion ](../setup_guides/footprint/setup_footprint.html#conclusion)
    * [ Setting Up Navigation Plugins ](../setup_guides/algorithm/select_algorithm.html)
      * [ Planner and Controller Servers ](../setup_guides/algorithm/select_algorithm.html#planner-and-controller-servers)
      * [ Selecting the Algorithm Plugins ](../setup_guides/algorithm/select_algorithm.html#selecting-the-algorithm-plugins)
        * [ Planner Server ](../setup_guides/algorithm/select_algorithm.html#planner-server)
        * [ Controller Server ](../setup_guides/algorithm/select_algorithm.html#controller-server)
      * [ Conclusion ](../setup_guides/algorithm/select_algorithm.html#conclusion)
  * [ General Tutorials ](../tutorials/index.html)
    * [ Navigating with a Physical Turtlebot 3 ](../tutorials/docs/navigation2_on_real_turtlebot3.html)
      * [ Overview ](../tutorials/docs/navigation2_on_real_turtlebot3.html#overview)
      * [ Requirements ](../tutorials/docs/navigation2_on_real_turtlebot3.html#requirements)
      * [ Tutorial Steps ](../tutorials/docs/navigation2_on_real_turtlebot3.html#tutorial-steps)
        * [ 0- Setup Your Enviroment Variables ](../tutorials/docs/navigation2_on_real_turtlebot3.html#setup-your-enviroment-variables)
        * [ 1- Launch Turtlebot 3 ](../tutorials/docs/navigation2_on_real_turtlebot3.html#launch-turtlebot-3)
        * [ 2- Launch Nav2 ](../tutorials/docs/navigation2_on_real_turtlebot3.html#launch-nav2)
        * [ 3- Launch RVIZ ](../tutorials/docs/navigation2_on_real_turtlebot3.html#launch-rviz)
        * [ 4- Initialize the Location of Turtlebot 3 ](../tutorials/docs/navigation2_on_real_turtlebot3.html#initialize-the-location-of-turtlebot-3)
        * [ 5- Send a Goal Pose ](../tutorials/docs/navigation2_on_real_turtlebot3.html#send-a-goal-pose)
    * [ (SLAM) Navigating While Mapping ](../tutorials/docs/navigation2_with_slam.html)
      * [ Overview ](../tutorials/docs/navigation2_with_slam.html#overview)
      * [ Requirements ](../tutorials/docs/navigation2_with_slam.html#requirements)
      * [ Tutorial Steps ](../tutorials/docs/navigation2_with_slam.html#tutorial-steps)
        * [ 0- Launch Robot Interfaces ](../tutorials/docs/navigation2_with_slam.html#launch-robot-interfaces)
        * [ 1- Launch Navigation2 ](../tutorials/docs/navigation2_with_slam.html#launch-navigation2)
        * [ 2- Launch SLAM ](../tutorials/docs/navigation2_with_slam.html#launch-slam)


  if (!layered_costmap_->isRolling()) {
    // if not rolling, the layered costmap (master_grid) has same coordinates as this layer
    if (!use_maximum_) {
      updateWithTrueOverwrite(master_grid, min_i, min_j, max_i, max_j);
    } else {
      updateWithMax(master_grid, min_i, min_j, max_i, max_j);
    }
  } else {
    // If rolling window, the master_grid is unlikely to have same coordinates as this layer
    unsigned int mx, my;
    double wx, wy;
    // Might even be in a different frame
    geometry_msgs::msg::TransformStamped transform;
    try {
      transform = tf_->lookupTransform(
        map_frame_, global_frame_, tf2::TimePointZero,
        transform_tolerance_);
    } catch (tf2::TransformException & ex) {
      RCLCPP_ERROR(logger_, "StaticLayer: %s", ex.what());
      return;
    }
    // Copy map data given proper transformations
    tf2::Transform tf2_transform;
    tf2::fromMsg(transform.transform, tf2_transform);


  1. some mostly static object, like an obstacle zone, which is set once and then stays. Here, the node that configures the obstacle zone wants a confirmation that it was actually set.
  2. moving objects, such as other robots, that constantly change. Here, we need to verify that the information about their footprint is always up-to-date, as it's received over network.


#  Saved searches


2 participants


[
![@AlexeyMerzlyakov](https://avatars.githubusercontent.com/u/60094858?s=80&u=bb82ce480f0854e3758a8c4f07129af932258cb1&v=4)
](/AlexeyMerzlyakov)


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


> I suppose we could support both services and topics, though not my ideal
> outcome. I would want clear warnings to users informing them that topics are
> not recommended, but may be useful in certain circumstances.


[ ros-planning ](/ros-planning) /  **[ navigation2 ](/ros-
planning/navigation2) ** Public


© Copyright 2020.


The task of a planner is to compute a path to complete some objective
function. The path can also be known as a route, depending on the nomenclature
and algorithm selected. Two canonical examples are computing a plan to a goal
(e.g. from current position to a goal) or complete coverage (e.g. plan to
cover all free space). The planner will have access to a global environmental
representation and sensor data buffered into it. Planners can be written to:


**[ SteveMacenski ](/SteveMacenski) ** commented  Jun 15, 2022  •


**[ SteveMacenski ](/SteveMacenski) ** commented  Oct 5, 2022  •


Various costmap layers are implemented as pluginlib plugins to buffer
information into the costmap. This includes information from LIDAR, RADAR,
sonar, depth, images, etc. It may be wise to process sensor data before
inputting it into the costmap layer, but that is up to the developer.


  * Proc1. Best performance for this kind of task
  * Proc2. Feature intention clarity and simplicity
  * Cons. Can not cover OccupancyGrid maps


Asked: ** 2023-04-10 14:45:27 -0500  **


Follow


> I think this was miscategorized. That's a con for D2. D1 is far more simple
> conceptually and enables re-use of existing costmap filters just with the
> input being from the vector object server, not the map file.


**[ dharanish-nh ](/dharanish-nh) ** commented  Jun 12, 2023


Sorry, something went wrong.


**Have a question about this project?** Sign up for a free GitHub account to
open an issue and contact its maintainers and the community.


Great to hear it and look forward to hearing about it!

---

👍  1  GMahmoud reacted with thumbs up emoji


    [planner_server-6] [INFO] [1686316127.923998800] [planner_server]: Planner Server has GridBased  planners available.
    [lifecycle_manager-11] [INFO] [1686316127.932865559] [lifecycle_manager_navigation]: Configuring behavior_server
    [behavior_server-7] [INFO] [1686316127.933067396] [behavior_server]: Configuring
    [behavior_server-7] [INFO] [1686316127.941144704] [behavior_server]: Creating behavior plugin assisted_teleop of type nav2_behaviors/AssistedTeleop
    [behavior_server-7] [INFO] [1686316127.944098107] [behavior_server]: Configuring assisted_teleop
    [behavior_server-7] [INFO] [1686316127.951943834] [behavior_server]: Creating behavior plugin spin of type nav2_behaviors/Spin
    [behavior_server-7] [INFO] [1686316127.953152718] [behavior_server]: Configuring spin
    [amcl-2] [INFO] [1686316127.959263510] [amcl]: createLaserObject
    [behavior_server-7] [INFO] [1686316127.961070637] [behavior_server]: Creating behavior plugin backup of type nav2_behaviors/BackUp
    [behavior_server-7] [INFO] [1686316127.962578649] [behavior_server]: Configuring backup
    [behavior_server-7] [INFO] [1686316127.969196486] [behavior_server]: Creating behavior plugin drive_on_heading of type nav2_behaviors/DriveOnHeading
    [behavior_server-7] [INFO] [1686316127.970485172] [behavior_server]: Configuring drive_on_heading
    [lifecycle_manager-3] [INFO] [1686316127.970678427] [lifecycle_manager_localization]: Server amcl connected with bond.
    [lifecycle_manager-3] [INFO] [1686316127.970712889] [lifecycle_manager_localization]: Managed nodes are active
    [lifecycle_manager-3] [INFO] [1686316127.970728190] [lifecycle_manager_localization]: Creating bond timer...
    [behavior_server-7] [INFO] [1686316127.977043744] [behavior_server]: Creating behavior plugin wait of type nav2_behaviors/Wait
    [behavior_server-7] [INFO] [1686316127.979361525] [behavior_server]: Configuring wait
    [lifecycle_manager-11] [INFO] [1686316127.989871230] [lifecycle_manager_navigation]: Configuring bt_navigator
    [bt_navigator-8] [INFO] [1686316127.990095357] [bt_navigator]: Configuring
    [lifecycle_manager-11] [INFO] [1686316128.073680392] [lifecycle_manager_navigation]: Configuring waypoint_follower
    [waypoint_follower-9] [INFO] [1686316128.073947211] [waypoint_follower]: Configuring
    [waypoint_follower-9] [INFO] [1686316128.078959909] [waypoint_follower]: Created waypoint_task_executor : wait_at_waypoint of type nav2_waypoint_follower::WaitAtWaypoint
    [waypoint_follower-9] [INFO] [1686316128.080383215] [waypoint_follower]: Waypoint pause duration is set to zero, disabling task executor plugin.
    [lifecycle_manager-11] [INFO] [1686316128.080976941] [lifecycle_manager_navigation]: Configuring velocity_smoother
    [velocity_smoother-10] [INFO] [1686316128.081297735] [velocity_smoother]: Configuring velocity smoother
    [lifecycle_manager-11] [INFO] [1686316128.084866838] [lifecycle_manager_navigation]: Activating controller_server
    [controller_server-4] [INFO] [1686316128.085170663] [controller_server]: Activating
    [controller_server-4] [INFO] [1686316128.085214888] [local_costmap.local_costmap]: Activating
    [controller_server-4] [INFO] [1686316128.085234231] [local_costmap.local_costmap]: Checking transform
    [controller_server-4] [INFO] [1686316128.085328015] [local_costmap.local_costmap]: start
    [planner_server-6] [INFO] [1686316128.085558190] [global_costmap.global_costmap]: StaticLayer: Resizing costmap to 1207 X 591 at 0.050000 m/pix
    [controller_server-4] [INFO] [1686316128.085705932] [local_costmap.local_costmap]: KeepoutFilter: Subscribing to "/keepout_filter_info" topic for filter info...
    [controller_server-4] [INFO] [1686316128.336655781] [controller_server]: Creating bond (controller_server) to lifecycle manager.
    [lifecycle_manager-11] [INFO] [1686316128.439727125] [lifecycle_manager_navigation]: Server controller_server connected with bond.
    [lifecycle_manager-11] [INFO] [1686316128.439774248] [lifecycle_manager_navigation]: Activating smoother_server
    [smoother_server-5] [INFO] [1686316128.440052405] [smoother_server]: Activating
    [smoother_server-5] [INFO] [1686316128.440088833] [smoother_server]: Creating bond (smoother_server) to lifecycle manager.
    [lifecycle_manager-11] [INFO] [1686316128.542868377] [lifecycle_manager_navigation]: Server smoother_server connected with bond.
    [lifecycle_manager-11] [INFO] [1686316128.542912639] [lifecycle_manager_navigation]: Activating planner_server
    [planner_server-6] [INFO] [1686316128.543226985] [planner_server]: Activating


###  Costmap Filters  ¶


In case 2), the sender (robot B) constantly produces new information. So, over
the (unstable) network I don't think there's a need for retransmitting, as new
information will be available soon anyway.
Now, the "up-to-date verification" needs to be on the receiver side (robot A).
I think it makes sense to do it in a separate node. The communication between
this verification node and the virtual costmap layer then needs to be
reliable.


How would you communicate to the client which shape should be used for which
application to interpret the costs?


I am using a custom costmap plugin for creating high costs around the
people(gazebo actor model). I am using the social layer [ github_repo
](https://github.com/robotics-upo/nav2_social_costmap_plugin) .
However, this code was built for ros2 foxy and I am using ros2 humble. I made
some changes to updatecosts and updatebounds by looking into the default
costmap plugin codes and tutorial code and now the costs are being updated
according to the position of humans in the simulation.


Member


In this case we to utilize only polygons, the design will be really simple,
and we do not need to have that universal ` Shape.msg ` . Pretty good option,
if nobody minds.


[ service call without blocking other callbacks ](/question/379465/service-
call-without-blocking-other-callbacks/)


* [ 1.ros2 ](/questions/scope:all/sort:activity-desc/tags:1.ros2/page:1/)


  unsigned int di = 0;
  for (unsigned int y = 0; y < update->height; y++) {
    unsigned int index_base = (update->y + y) * size_x_;
    for (unsigned int x = 0; x < update->width; x++) {
      unsigned int index = index_base + x + update->x;
      costmap_[index] = interpretValue(update->data[di++]);
    }
  }


Collaborator


[ @GMahmoud ](https://github.com/GMahmoud) FYI

---

The text was updated successfully, but these errors were encountered:


By Solution


For this, robot A would publish the received footprint of robot B on a topic,
and this new plugin would then add it to the costmap. I think services would
add too much latency here, in case robot B is moving.

---

All reactions


Copy link


##  Bug report


#include "pluginlib/class_list_macros.hpp"
#include "tf2/convert.h"
#include "tf2_geometry_msgs/tf2_geometry_msgs.hpp"


Labels


One more thing about the design.
Since one VO-server node is used to be launched per each filter (e.g. if we
are using ` KeepoutFilter ` and ` SpeedFilter ` , we need to have 2 instances
of VO-server running), all vector shapes could be described in one launch-
file, as ROS-parameters' array:


What do you think of having a ` stream ` from the client side for this case ?
We could make available a ` ros action ` for example in addition to ` request-
reply ` for addition and remove of elements.
This action will deal with dynamic elements and client could supervisor the
process by listening to the feedback topic.

---

All reactions


* Interface with a tool


[
![@AlexeyMerzlyakov](https://avatars.githubusercontent.com/u/60094858?s=40&u=bb82ce480f0854e3758a8c4f07129af932258cb1&v=4)
](/AlexeyMerzlyakov) [ AlexeyMerzlyakov ](/AlexeyMerzlyakov) mentioned this
issue  Nov 2, 2023


void
StaticLayer::activate()
{
}


**[ AlexeyMerzlyakov ](/AlexeyMerzlyakov) ** commented  Feb 7, 2023  •


All reactions


Moving forward, we need to have separate input topic, each one per each type
of shape: Polygon, BrokenLine and Circle. They e.g. could be automatically
generated by user-defined prefix. Something, if we have name of VO-server to
be equal to ` /vo_server ` , name of input topics could be:


  has_updated_data_ = true;
}


For circles, I think we'd need some special case for sure. Another question is
about pose of the shape. If we want to set a box of points making up a 1m box,
do I need to transform them to the pose already or can I have a pose of the
center of the shape. I think that's more relevent for the ` add shape `
service than the actual shape message stored in file for a particular map that
was semantically marked. Those marked in a map are probably already just at
the coordinates.


#  robot doesn't navigate in custom costmap layer.  #3613


I looked very briefly at the code, there's alot going on there. If you were to
define a ` Polygon ` as a series of connected line segments, I'm not entirely
sure why the difference between convex/concave is important (or using so many
external polygon libraries). Obviously I'm not in the middle of this
development, so I'm sure you have good reasons! Though, I suspect some of this
may be able to be simplified (hopefully?)


Sorry, something went wrong.


Closed


* 🎉  1 reaction


#  Feature Request: Custom/Virtual Obstacle Layer  #3017


> [planner_server-6] [INFO] [1686316129.043376579]
> [global_costmap.global_costmap]: Timed out waiting for transform from
> base_link to map to become available, tf error: Lookup would require
> extrapolation into the past. Requested time 5.979000 but the earliest data
> is at time 6.015000, when looking up transform from frame [base_link] to
> frame [map]
>  [amcl-2] [WARN] [1686316129.082419369] [amcl]: New subscription discovered
> on topic '/particle_cloud', requesting incompatible QoS. No messages will be
> sent to it. Last incompatible policy: RELIABILITY_QOS_POLICY


It would likely be stored either way (e.g. in the costmap), so its more about
the transport.


Collaborator


The other question - do we really need these abilities?


**[ GMahmoud ](/GMahmoud) ** commented  Jun 17, 2022


[
![@AlexeyMerzlyakov](https://avatars.githubusercontent.com/u/60094858?s=80&u=bb82ce480f0854e3758a8c4f07129af932258cb1&v=4)
](/AlexeyMerzlyakov)


  1. If its some static 1-time set zones, services make the most sense to make sure you know they were set or to retry since they're probably important semantic information about the environment and your robot's system behavior that would be unacceptable to just ignore (e.g. keepout zones)
  2. For time variant I can see the appeal of topics, but then especially if we're talking about communication between robots, you'd want to know what information is actually in each robot's costmap versus guessing based on the current state of the network. I'd actually argue that streaming internally to a single robot would be more appropriate since we could make a pretty solid assumption that messages published are probably processed. When we go off device, that assumption is no longer solid and I would think it would be very important that some thing somewhere has the logs about what robots have what other robot's information actually processed and represented in their environmental models (in case of issue) which you wouldn't get if you just published the messages. In retrospect after a collision you could tell that it was that way from the logs, but you couldn't at the time know that since Robot A has no awareness Robot B didn't get the message.


#  Navigation Concepts  ¶


In a nutshell, REP-105 says that you must, at minimum, build a TF tree that
contains a full ` map  ` -> ` odom  ` -> ` base_link  ` -> ` [sensor  frames]
` for your robot. TF2 are the time-variant transformation library in ROS 2 we
use to represent and obtain time synchronized transformations. It is the job
of the global positioning system (GPS, SLAM, Motion Capture) to, at minimum,
provide the ` map  ` -> ` odom  ` transformation. It is then the role of the
odometry system to provide the ` odom  ` -> ` base_link  ` transformation. The
remainder of the transformations relative to ` base_link  ` should be static
and defined in your [ URDF ](http://wiki.ros.org/urdf) .


Is there a way to add a subscriber to a custom costmap layer plugin? If so,
would anyone please tell me how?


I'd start with arbitrary polygons, lines, and circles. Honestly the most
common use here is going to be boxes drawn on screens for keepout zones or
speed zones or something by a non-trained user on a web GUI that's going to be
propagated down here during robot setup.


Open


edited


ROS Resources: [ Documentation ](http://wiki.ros.org/) | [ Support
](http://wiki.ros.org/Support) | [ Discussion Forum
](http://discourse.ros.org/) | [ Index ](http://index.ros.org/) | [ Service
Status ](http://status.ros.org/) | [ ros @ Robotics Stack Exchange
](https://robotics.stackexchange.com/questions/tagged/ros)
---

_Attention:_ Answers.ros.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://discourse.ros.org/t/ros-and-gazebo-answers-
migration-to-robotics-stack-exchange-process/31494) .


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


No one assigned


Indeed, ` use_max ` indicator is also needed, to define how two or more
objects would intersect in case of both of them are having equal priority. `
use_max ` in this case could be a global ROS-parameter, since one VO-server
instance is implied to be used per one selected filter.


void
StaticLayer::matchSize()
{
  // If we are using rolling costmap, the static map size is
  //   unrelated to the size of the layered costmap
  if (!layered_costmap_->isRolling()) {
    Costmap2D * master = layered_costmap_->getCostmap();
    resizeMap(
      master->getSizeInCellsX(), master->getSizeInCellsY(), master->getResolution(),
      master->getOriginX(), master->getOriginY());
  }
}


The design I would have in mind is a server to read the polygons from file, if
provided. That publishes to a topic that the costmap layer receives. The
costmap layer either stores the vectorized information to populate in the
costmap each cycle, or populates it immediately into a rastered map for use
(whatever's more efficient). Services are added to get/set/remove the polygons
from the costmap layer.


Hello !
Sorry it took me sometime to update the project but the work is still in
progress [ link
](https://github.com/GMahmoud/virtual_costmap_layer/tree/feature-big-
refactoring)


[
![@SteveMacenski](https://avatars.githubusercontent.com/u/14944147?s=80&u=0925d37e9d3569c71d930114b66e6394c2efb3c6&v=4)
](/SteveMacenski)


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


Cross post with ROS Answers [ https://answers.ros.org/question/416314/robot-
not-navigating-when-using-custom-costmap-layer/
](https://answers.ros.org/question/416314/robot-not-navigating-when-using-
custom-costmap-layer/)

---

All reactions


But I very look forward to this, this is a good compliment to the keepout
filters. Sometimes a mask makes sense, but often a polygon or vector shape
makes sense too! If we add the services to the Python3 Simple Commander, it'll
be stupidly easy to make testing demos with randomly generated obstacles in a
costmap, without having to manually create a map. Just open a blank costmap
and generate random stuff in random spots to insert.

---

All reactions


Jump to bottom


  // initialize the costmap with static data
  for (unsigned int i = 0; i < size_y; ++i) {
    for (unsigned int j = 0; j < size_x; ++j) {
      unsigned char value = new_map.data[index];
      costmap_[index] = interpretValue(value);
      ++index;
    }
  }


Search or jump to...


* Solutions


Recovery behaviors are a mainstay of fault-tolerant systems. The goal of
recoveries are to deal with unknown or failure conditions of the system and
autonomously handle them. Examples may include faults in the perception system
resulting in the environmental representation being full of fake obstacles.
The clear costmap recovery would then be triggered to allow the robot to move.


**[ SteveMacenski ](/SteveMacenski) ** commented  Jun 10, 2023


**[ GMahmoud ](/GMahmoud) ** commented  Oct 6, 2022  •


edited


> The whole map is being stored


Especially in the case of multi-robot networking where things could drop out,
it is very important you know what was successfully added and what wasn't.
Maybe for the long-range planning application it isn't critical, but we need
to act like any user of this work if in Nav2 has critical information that
could prevent a dangerous situation. Otherwise, you could stream topics that
are missed and never know that you're not going to avoid and obstacle / zone
until its too late. Also if a service call fails, you know as a fact that
Robot A didn't get Robot B's footprint, so you can try to retransmit. You'd
never know that if you didn't have a service.


The smooth output can be used then for dead-reckoning for precise motion and
updating the position of the robot accurately between global position updates.


  * If we have the costmap filters that are the speed / keepout zones, and then we have speed / keepout zones as vectorized options, we probably need some way either in 'branding' and documentation/communication to bin these ideas together if we don't call the vectorized things also "costmap filters" so we can clearly communicate the capabilities to use either rastered maps or vectorized representations
  * Ideally which would make our lives easier in technical communication and less redundant code would be to use the costmap filters themselves and have the polygon "stuff" happen in the separate server which publishes out a ` OccupancyGrid ` message that the costmap filter can ingest so we don't have to make any new costmap layers
  * To make that plausible though, we should see the latency and CPU usage of regular sending of fullsized costmaps at 1-5hz from a server (in the component container) to a costmap layer to make sure that its "reasonable". This is the best option for cleanliness, but maybe not the best technical solution possible for resource utilization. Everything in life is a trade off though.


[
![@GMahmoud](https://avatars.githubusercontent.com/u/29754310?s=80&u=1493f619be29310ca5f6e336f7f72f4d945ab80f&v=4)
](/GMahmoud)


Copy link


  x_ = y_ = 0;
  width_ = size_x_;
  height_ = size_y_;
  has_updated_data_ = true;


here is the code repo where I made all the changes according to [ Humble.
](https://github.com/dharanish-
nh/customcostmap/blob/main/nav2_social_costmap_plugin/src/social_layer.cpp)


  if (!layered_costmap_->isRolling() ) {
    if (!(has_updated_data_ || has_extra_bounds_)) {
      return;
    }
  }


[ JSLbotbuilder ](/users/145125/jslbotbuilder/)
1  ●  2  ●  3  ●  3


All reactions


Behavior trees (BT) are becoming increasingly common in complex robotics
tasks. They are a tree structure of tasks to be completed. It creates a more
scalable and human-understandable framework for defining multi-step or many
state applications. This is opposed to a finite state machine (FSM) which may
have dozens of states and hundreds of transitions. An example would be a
soccer playing robot. Embedding the logic of soccer game play into a FSM would
be challenging and error prone with many possible states and rules.
Additionally, modeling choices like to shoot at the goal from the left, right,
or center, is particularly unclear. With a BT, basic primitives like “kick”
“walk” “go to ball” can be created and reused for many behaviors. More
information can be found [ in this book ](https://arxiv.org/abs/1709.00084) .
I **strongly** recommend reading chapters 1-3 to get a good understanding of
the nomenclature and workflow. It should only take about 30 minutes.


[
![@SteveMacenski](https://avatars.githubusercontent.com/u/14944147?s=80&u=0925d37e9d3569c71d930114b66e6394c2efb3c6&v=4)
](/SteveMacenski)


Sorry, something went wrong.


So maybe there are two usecases here:


{{ message }}


Imagine, you’re annotating a map file (or any image file) in order to have a
specific action occur based on the location in the annotated map. Examples of
marking/annotating might be keep out zones to avoid planning inside, or have
pixels belong to maximum speeds in marked areas. This annotated map is called
“filter mask”. Just like a mask overlaid on a surface, it can or cannot be
same size, pose and scale as a main map. The main goal of filter mask - is to
provide an ability of marking areas on maps with some additional features or
behavioral changes.


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


Member


I think this was miscategorized. That's a con for D2. D1 is far more simple
conceptually and enables re-use of existing costmap filters just with the
input being from the vector object server, not the map file.

---

All reactions


Neither is better than the other, it highly depends on the tasks your robot(s)
are completing, in what type of environment, and with what cloud resources
available. Often this distinction is very clear for a given business case.


* “Vector space”, taking in sensor information and using machine learning to detect individual items and locations to track rather than buffering discrete points.


Use of a separate smoother over one that is included as a part of a planner is
advantageous when combining different planners with different smoothers or
when a specific control over smoothing is required, e.g. smoothing ony a
specific part of the path.


Cheers

---

❤  1  SteveMacenski reacted with heart emoji


[ **asked 2023-04-10 14:45:27 -0500  ** ](/questions/414211/revisions/)


* [ 2d_nav ](/questions/scope:all/sort:activity-desc/tags:2d_nav/page:1/)


Explore


New issue


The proposed initial feature design in attached as [ VO_design_20230131.pdf
](https://github.com/ros-
planning/navigation2/files/10546446/VO_design_20230131.pdf) . Any
comments/feedback are welcoming.

---

All reactions


> Not sure, why do we need to put each shape into separate file?


Alternatively, since the BT nodes are trivial plugins calling an action, new
BT nodes can be created to call other action servers with other action types.
It is advisable to use the provided servers if possible at all times. If, due
to the plugin or action interfaces, a new server is needed, that can be
sustained with the framework. The new server should use the new type and
plugin interface, similar to the provided servers. A new BT node plugin will
need to be created to call the new action server – however no forking or
modification is required in the Nav2 repo itself by making extensive use of
servers and plugins.


Next item to discuss - is shapes design.
Do we plan to support only polygons (+maybe circle), or have an ability of
expansion to other vector objects in the future (e.g. ellipse, arc, sector,
...)?


useExtraBounds(min_x, min_y, max_x, max_y);


As criteria for optimality of the path searched by a planner are usually
reduced compared to reality, additional path refinement is often beneficial.
Smoothers have been introduced for this purpose, typically responsible for
reducing path raggedness and smoothing abrupt rotations, but also for
increasing distance from obstacles and high-cost areas as the smoothers have
access to a global environmental representation.


Waypoint following is a basic feature of a navigation system. It tells our
system how to use navigation to get to multiple destinations.


**[ SteveMacenski ](/SteveMacenski) ** commented  Jun 17, 2022  •


Collaborator


Why? We should use a single interface for the shapes. Also I think you mean
services so that you can get a request/reply to know the update / removal /
addition was made. I'm not sure why messages for the polygons would need to
exist if the server is reading from file and populating the occupancy grid.


**[ GMahmoud ](/GMahmoud) ** commented  Jun 19, 2022


Sorry, something went wrong.


Search


Sorry for interjecting in the lovely design discussions, I would just like to
mention that we found another application of such a costmap layer: We have a [
pallet-picking forklift-looking AMR ](https://www.pixel-robotics.eu/) ; to be
able to pick up a pallet aka driving into a pallet, we need to clear the
region on the costmap (not centered at the robot) where the pallet is. I want
to point out that even if we were to add the functionality to clear any custom
region in nav2_costmap_2d, that would not be enough because the pallet is
still there so the occupied costs will reappear. Therefore we actually need an
extra layer to make the pallet disappear from the costmap.
We will workaround the issue for now and hope to re-implement the logic with
this layer once it's ready, so we could be your testers 😄


[
![@tonynajjar](https://avatars.githubusercontent.com/u/14879660?s=80&u=e29d50db1bac036eae32b30fec612615ccd3791a&v=4)
](/tonynajjar)


#  Provide feedback


[ Detection of subscriber queue overflow in ROS2?
](/question/414577/detection-of-subscriber-queue-overflow-in-ros2/)


void
StaticLayer::incomingMap(const nav_msgs::msg::OccupancyGrid::SharedPtr new_map)
{
  if (!map_received_) {
    processMap(*new_map);
    map_received_ = true;
    return;
  }
  std::lock_guard<Costmap2D::mutex_t> guard(*getMutex());
  map_buffer_ = new_map;
}


  declareParameter("enabled", rclcpp::ParameterValue(true));
  declareParameter("subscribe_to_updates", rclcpp::ParameterValue(false));
  declareParameter("map_subscribe_transient_local", rclcpp::ParameterValue(true));
  declareParameter("transform_tolerance", rclcpp::ParameterValue(0.0));
  declareParameter("map_topic", rclcpp::ParameterValue(""));


[ ![@SteveMacenski](https://avatars.githubusercontent.com/u/14944147?s=52&v=4)
](/SteveMacenski) [ ![@dharanish-
nh](https://avatars.githubusercontent.com/u/15521002?s=52&v=4) ](/dharanish-
nh)


edited


  * [ Code  ](/ros-planning/navigation2)
  * [ Issues  ](/ros-planning/navigation2/issues)
  * [ Pull requests  ](/ros-planning/navigation2/pulls)
  * [ Actions  ](/ros-planning/navigation2/actions)
  * [ Projects  ](/ros-planning/navigation2/projects)
  * [ Security  ](/ros-planning/navigation2/security)
  * [ Insights  ](/ros-planning/navigation2/pulse)


Include my email address so I can be contacted


###  Standards  ¶


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


By clicking “Sign up for GitHub”, you agree to our [ terms of service
](https://docs.github.com/terms) and [ privacy statement
](https://docs.github.com/privacy) . We’ll occasionally send you account
related emails.


Contributor  Author


**[ GMahmoud ](/GMahmoud) ** commented  Jun 28, 2022


* [ 2DCostmapROS ](/questions/scope:all/sort:activity-desc/tags:2DCostmapROS/page:1/)


Agree, 8-bit value should be OK, since we won't use each own unique priority
per each vector object


edit


Behavior Trees provide a formal structure for navigation logic which can be
both used to create complex systems but also be verifiable and validated as
provenly correct using advanced tools. Having the application logic
centralized in the behavior tree and with independent task servers (which only
communicate data over the tree) allows for formal analysis.


> An aside, but the ` nav2_msgs/Costmap ` was made at a time long ago back
> when there were other design plans which were abandoned for the world
> models. Doing a brief survey, I cannot find a reason why we still even have
> that message around or use it for anything. We can probably throw that away
> entirely and replace it with the OccupancyGrid messages, which as far as I
> can tell provide the same information. Its actually quite annoying that we
> have that extra type around which serves little functional purpose.


* Open Source


I tried making a separate regular node that I could set as a shared pointer
within my costmap layer which also didn't work. This was due to the plugin not
even recognizing the node I had made within my code.


I would indeed, I haven't looked in excessive detail how this works exactly,
but the concept seems good to me to have in Nav2 and would be actually very
convenient for testing purposes (mainly). Curious though for a more production
reason what you might be doing with this?


Copy link


[ edit ](/s/answers/416541/edit/) flag offensive  delete  [ link
](/question/414211/adding-subscriber-to-custom-costmap/?answer=416541#post-
id-416541 "permanent link") more


So, the timings are more than suitable for dynamic objects support on
centralized VO-server side.

---

All reactions


But what are the specific mechanics at which you'd make transparency? I don't
think its possible with the information you have available. You don't know
what value of cost 0-255 would remap to "do nothing". 0 could be 0% speed or 0
could be trigger the binary filter -- we simply cannot know.


* 👍  1 reaction


> I have some doubts about the case when we have large map


* Speed restriction areas. Maximum speed of robots going inside those areas will be limited.


I agree with you about defining only outerline of a ` polygon ` (which I call
a ring here) or as you said ` a series of connected line segments ` . This is
sufficient for mobile robot to take only the boundary of **an obstacle** and
add an inflation layer to it.
About the polygon concept I am using the boost.geomerty one. Here is a [ link
](https://www.boost.org/doc/libs/1_80_0/libs/geometry/doc/html/geometry/reference/concepts/concept_polygon.html)
for better understanding.


edited


ROS 2 is the core middleware used for Nav2. If you are unfamilar with this,
please visit [ the ROS 2 documentation ](https://docs.ros.org/en/rolling/)
before continuing.


  * [ Getting Started ](../getting_started/index.html)
    * [ Installation ](../getting_started/index.html#installation)
    * [ Running the Example ](../getting_started/index.html#running-the-example)
    * [ Navigating ](../getting_started/index.html#navigating)
  * [ Development Guides ](../development_guides/index.html)
    * [ Build and Install ](../development_guides/build_docs/index.html)
      * [ Install ](../development_guides/build_docs/index.html#install)
      * [ Build ](../development_guides/build_docs/index.html#build)
        * [ Released Distribution Binaries ](../development_guides/build_docs/index.html#released-distribution-binaries)
        * [ Rolling Development Source ](../development_guides/build_docs/index.html#rolling-development-source)
        * [ Docker Container Images ](../development_guides/build_docs/index.html#docker-container-images)
      * [ Generate Doxygen ](../development_guides/build_docs/index.html#generate-doxygen)
      * [ Help ](../development_guides/build_docs/index.html#help)
        * [ Build Troubleshooting Guide ](../development_guides/build_docs/build_troubleshooting_guide.html)
    * [ Dev Containers ](../development_guides/devcontainer_docs/index.html)
      * [ Dev Container Guide ](../development_guides/devcontainer_docs/devcontainer_guide.html)
        * [ Creating Dev Containers ](../development_guides/devcontainer_docs/devcontainer_guide.html#creating-dev-containers)
        * [ Using Dev Containers ](../development_guides/devcontainer_docs/devcontainer_guide.html#using-dev-containers)
      * [ What, Why, How? ](../development_guides/devcontainer_docs/index.html#what-why-how)
        * [ What is a Dev Container? ](../development_guides/devcontainer_docs/index.html#what-is-a-dev-container)
        * [ Why use a Dev Container? ](../development_guides/devcontainer_docs/index.html#why-use-a-dev-container)
        * [ How do Dev Containers work? ](../development_guides/devcontainer_docs/index.html#how-do-dev-containers-work)
      * [ Prerequisites ](../development_guides/devcontainer_docs/index.html#prerequisites)
      * [ Getting started ](../development_guides/devcontainer_docs/index.html#getting-started)
      * [ Security ](../development_guides/devcontainer_docs/index.html#security)
    * [ Getting Involved ](../development_guides/involvement_docs/index.html)
      * [ Getting Involved ](../development_guides/involvement_docs/index.html#id1)
      * [ Process ](../development_guides/involvement_docs/index.html#process)
      * [ Licensing ](../development_guides/involvement_docs/index.html#licensing)
      * [ Developer Certification of Origin (DCO) ](../development_guides/involvement_docs/index.html#developer-certification-of-origin-dco)
  * Navigation Concepts
    * ROS 2
      * Action Server
      * Lifecycle Nodes and Bond
    * Behavior Trees
    * Navigation Servers
      * Planner, Controller, Smoother and Recovery Servers
      * Planners
      * Controllers
      * Behaviors


🎉  1  SteveMacenski reacted with hooray emoji


Hello [ @tonynajjar ](https://github.com/tonynajjar)


  * [ ](../index.html)
  * Navigation Concepts
  *


Sorry, something went wrong.


No, I don't see any issue when I don't use the cost map, only when I include a
custom plugin. I am stuck at this step and have run out of ideas to correct
it. [ @SteveMacenski ](https://github.com/SteveMacenski)

---

All reactions


Initially, I thought about making some kind of "holes" inside vector objects,
and filling them with ` FREE_SPACE ` values, allowing to underlying objects
with lower priority to be on the resulting map.
The example depicted below could not be drawn only by utilizing only ` use_max
` and ` priority ` values:
[ ![Transparency](https://user-
images.githubusercontent.com/60094858/221843324-49dacf75-ae01-4a6f-adba-9d201a2c1d94.png)
](https://user-
images.githubusercontent.com/60094858/221843324-49dacf75-ae01-4a6f-adba-9d201a2c1d94.png)
Polygons "A" and "B" having the same priority = 1, while circles "C" and "D"
are having lower priority = 2. Circle "C" in this case should be laid always
_under_ the border "A&B", which seems to be impossible w/o additional
attribute like ` transparency ` allowing to show vector objects laid under the
current one.


    KeepoutFilter::process() time, us
    mask in "map" frame, global_frame = "odom": 213.76 us
    mask and global_frame are both "odom": 176.97 us
    difference: 36.79 us


Query


Updated according to latest discussions, feature design is attached as [
VO_layer_design_20230203.pdf ](https://github.com/ros-
planning/navigation2/files/10578527/VO_layer_design_20230203.pdf)

---

All reactions


  // Enforce bounds
  lethal_threshold_ = std::max(std::min(temp_lethal_threshold, 100), 0);
  map_received_ = false;
  map_received_in_update_bounds_ = false;


This page is to help familiarize new robotists to the concepts of mobile robot
navigation, in particular, with the concepts required to appreciating and
working with this project.


* 3D costmaps, which represent the space in 3D, but then also requires 3D planning and collision checking


Planners and controllers are at the heart of a navigation task. Recoveries are
used to get the robot out of a bad situation or attempt to deal with various
forms of issues to make the system fault-tolerant. Smoothers can be used for
additional quality improvements of the planned path. In this section, the
general concepts around them and their uses in this project are analyzed.


**[ SteveMacenski ](/SteveMacenski) ** commented  Feb 22, 2023


[ Rosserial on ros2 humble ](/question/413012/rosserial-on-ros2-humble/)


[ ![@dharanish-
nh](https://avatars.githubusercontent.com/u/15521002?s=80&u=ef939dba8902fa59a5ab3a6fceb06a2486ead81a&v=4)
](/dharanish-nh)


Password


  * We have a server that reads some polygons from file and generates an ` OccupancyGrid ` from it
  * Assuming the CPU or latency of regularly publishing that out isn't too high, then that occupancy grid is then subscribed to by the Costmap Filter plugins to interpret the polygons files' shape values to perform some action (e.g. speed, keepout, higher cost, lanes, whatever).
  * That lets us not have to create any new costmap filters or costmap layers because there's no difference between an OccGrid like this and a map file.
  * Each type of polygon (speed zone, keepout, etc) is in a separate file so they're subscribed to by different costmap filters on different topics


[ Spawner waiting for '/controller_manager' services to be available when they
are already available ](/question/416031/spawner-waiting-for-
controller_manager-services-to-be-available-when-they-are-already-available/)


**[ tonynajjar ](/tonynajjar) ** commented  Feb 2, 2023  •


No one assigned


Copy link


This can be thought of more as a normal costmap layer as a vector option
instead of rastered maps, which that is a more sensible option. I had not at
least initially considered the use of this feature for anything other than
obstacles / costs in the costmap for navigation (e.g. Speed limit zones as
polygons). How would that analog for the costmap filter info be send here for
the multiplier, base, and action to use for the polygons? I don't think that
was initially in the presentation.


If you want to take a look at it. [ @tonynajjar
](https://github.com/tonynajjar) I will let you know when I start to work on
Nav2


**[ SteveMacenski ](/SteveMacenski) ** commented  Jun 12, 2023


Hello [ @AlexeyMerzlyakov ](https://github.com/AlexeyMerzlyakov) and the whole
maintainers team.
i just want to say that I had been tracking this feature request since two
years because this is something I need in my uni project. Today I tested it
and it is working perfectly and it is very well documented too.
Thank you

---

All reactions


By clicking “Sign up for GitHub”, you agree to our [ terms of service
](https://docs.github.com/terms) and [ privacy statement
](https://docs.github.com/privacy) . We’ll occasionally send you account
related emails.


**[ jplapp ](/jplapp) ** commented  Jun 19, 2022


##  Behavior Trees  ¶


#include "nav2_costmap_2d/static_layer.hpp"


Agreed 👍🏻 (Added to task list)

---

❤  1  SteveMacenski reacted with heart emoji


[
![@AlexeyMerzlyakov](https://avatars.githubusercontent.com/u/60094858?s=80&u=bb82ce480f0854e3758a8c4f07129af932258cb1&v=4)
](/AlexeyMerzlyakov)


**[ SteveMacenski ](/SteveMacenski) ** commented  Jun 22, 2022  •


Member


Cancel  Create saved search


[ ros-planning ](/ros-planning) /  **[ navigation2 ](/ros-
planning/navigation2) ** Public


Sorry, something went wrong.


**[ AlexeyMerzlyakov ](/AlexeyMerzlyakov) ** commented  Feb 28, 2023  •


  // Add callback for dynamic parameters
  dyn_params_handler_ = node->add_on_set_parameters_callback(
    std::bind(
      &StaticLayer::dynamicParametersCallback,
      this, std::placeholders::_1));
}


  current_ = true;
}


Copy link


All reactions


Adding Subscriber to custom Costmap


Via services? Yes, that was my thought as well 😄


Hm... that is really interesting. I thought, it actively used in Costmap2D-s.
But anyway, no one forbids us to revive this format, if we will really have a
needs for it.

---

All reactions


> Not certainly in that way. In case of StaticLayer, we will re-use one of the
> existing costmap layer to make and apply (to master grid) raster costmap
> made from obtained input OccupancyGrid map, which is made by VO server from
> vector objects.


  * [ Code  ](/ros-planning/navigation2)
  * [ Issues  ](/ros-planning/navigation2/issues)
  * [ Pull requests  ](/ros-planning/navigation2/pulls)
  * [ Actions  ](/ros-planning/navigation2/actions)
  * [ Projects  ](/ros-planning/navigation2/projects)
  * [ Security  ](/ros-planning/navigation2/security)
  * [ Insights  ](/ros-planning/navigation2/pulse)


    "/vo_server/in_polygon" <- with Polygon.msg type
    "/vo_server/in_broken_line" <- with BrokenLine.msg type
    "/vo_server/in_circle" <- with Circle.msg type