      * [ Alphas ](../../Releases/Alpha-Overview.html)
    * [ Development process for a release ](../../Releases/Release-Process.html)
  * [ Tutorials ](../../Tutorials.html)
    * [ Beginner: CLI tools ](../../Tutorials/Beginner-CLI-Tools.html)
      * [ Configuring environment ](../../Tutorials/Beginner-CLI-Tools/Configuring-ROS2-Environment.html)
      * [ Using ` turtlesim  ` , ` ros2  ` , and ` rqt  ` ](../../Tutorials/Beginner-CLI-Tools/Introducing-Turtlesim/Introducing-Turtlesim.html)
      * [ Understanding nodes ](../../Tutorials/Beginner-CLI-Tools/Understanding-ROS2-Nodes/Understanding-ROS2-Nodes.html)
      * [ Understanding topics ](../../Tutorials/Beginner-CLI-Tools/Understanding-ROS2-Topics/Understanding-ROS2-Topics.html)
      * [ Understanding services ](../../Tutorials/Beginner-CLI-Tools/Understanding-ROS2-Services/Understanding-ROS2-Services.html)
      * [ Understanding parameters ](../../Tutorials/Beginner-CLI-Tools/Understanding-ROS2-Parameters/Understanding-ROS2-Parameters.html)
      * [ Understanding actions ](../../Tutorials/Beginner-CLI-Tools/Understanding-ROS2-Actions/Understanding-ROS2-Actions.html)
      * [ Using ` rqt_console  ` to view logs ](../../Tutorials/Beginner-CLI-Tools/Using-Rqt-Console/Using-Rqt-Console.html)
      * [ Launching nodes ](../../Tutorials/Beginner-CLI-Tools/Launching-Multiple-Nodes/Launching-Multiple-Nodes.html)
      * [ Recording and playing back data ](../../Tutorials/Beginner-CLI-Tools/Recording-And-Playing-Back-Data/Recording-And-Playing-Back-Data.html)
    * [ Beginner: Client libraries ](../../Tutorials/Beginner-Client-Libraries.html)
      * [ Using ` colcon  ` to build packages ](../../Tutorials/Beginner-Client-Libraries/Colcon-Tutorial.html)
      * [ Creating a workspace ](../../Tutorials/Beginner-Client-Libraries/Creating-A-Workspace/Creating-A-Workspace.html)
      * [ Creating a package ](../../Tutorials/Beginner-Client-Libraries/Creating-Your-First-ROS2-Package.html)
      * [ Writing a simple publisher and subscriber (C++) ](../../Tutorials/Beginner-Client-Libraries/Writing-A-Simple-Cpp-Publisher-And-Subscriber.html)
      * [ Writing a simple publisher and subscriber (Python) ](../../Tutorials/Beginner-Client-Libraries/Writing-A-Simple-Py-Publisher-And-Subscriber.html)
      * [ Writing a simple service and client (C++) ](../../Tutorials/Beginner-Client-Libraries/Writing-A-Simple-Cpp-Service-And-Client.html)
      * [ Writing a simple service and client (Python) ](../../Tutorials/Beginner-Client-Libraries/Writing-A-Simple-Py-Service-And-Client.html)
      * [ Creating custom msg and srv files ](../../Tutorials/Beginner-Client-Libraries/Custom-ROS2-Interfaces.html)
      * [ Implementing custom interfaces ](../../Tutorials/Beginner-Client-Libraries/Single-Package-Define-And-Use-Interface.html)
      * [ Using parameters in a class (C++) ](../../Tutorials/Beginner-Client-Libraries/Using-Parameters-In-A-Class-CPP.html)
      * [ Using parameters in a class (Python) ](../../Tutorials/Beginner-Client-Libraries/Using-Parameters-In-A-Class-Python.html)
      * [ Using ` ros2doctor  ` to identify issues ](../../Tutorials/Beginner-Client-Libraries/Getting-Started-With-Ros2doctor.html)
      * [ Creating and using plugins (C++) ](../../Tutorials/Beginner-Client-Libraries/Pluginlib.html)
    * [ Intermediate ](../../Tutorials/Intermediate.html)
      * [ Managing Dependencies with rosdep ](../../Tutorials/Intermediate/Rosdep.html)
      * [ Creating an action ](../../Tutorials/Intermediate/Creating-an-Action.html)
      * [ Writing an action server and client (C++) ](../../Tutorials/Intermediate/Writing-an-Action-Server-Client/Cpp.html)
      * [ Writing an action server and client (Python) ](../../Tutorials/Intermediate/Writing-an-Action-Server-Client/Py.html)
      * [ Writing a Composable Node (C++) ](../../Tutorials/Intermediate/Writing-a-Composable-Node.html)
      * [ Composing multiple nodes in a single process ](../../Tutorials/Intermediate/Composition.html)
      * [ Monitoring for parameter changes (C++) ](../../Tutorials/Intermediate/Monitoring-For-Parameter-Changes-CPP.html)
      * [ Monitoring for parameter changes (Python) ](../../Tutorials/Intermediate/Monitoring-For-Parameter-Changes-Python.html)
      * [ Launch ](../../Tutorials/Intermediate/Launch/Launch-Main.html)
        * [ Creating a launch file ](../../Tutorials/Intermediate/Launch/Creating-Launch-Files.html)
        * [ Integrating launch files into ROS 2 packages ](../../Tutorials/Intermediate/Launch/Launch-system.html)


[ Previous ](Custom-ROS2-Interfaces.html "Creating custom msg and srv files")
[ Next  ](Using-Parameters-In-A-Class-CPP.html "Using parameters in a class
\(C++\)")


Specifically, this is called _snake case_ .


* 3 Use an interface from the same package


You also learned how to use another interface as a field type, as well as the
` package.xml  ` , ` CMakeLists.txt  ` , and ` #include  ` statements
necessary for utilizing that feature.


unsigned long

int64


[ Rolling ](../../../rolling/Tutorials/Beginner-Client-Libraries/Single-Package-Define-And-Use-Interface.html)


custom_class<T, N>


thank you!
So… if I named a .msg “Sensor3DState.msg” what would the .hpp be?
sensor3_Dstate.hpp? sensor3_d_state.hpp?
Or I should I also never name anything that allows for 2 Caps to be together…
which i guess makes sense.
and also… why does it seem to be an obvious thing? i dont see it mentioned or
explained anywhere. Granted im a noob to it all but is like everyone
understands it and is obvious. But I dont see it explained. Is it a C++ thing
or a ROS thing?


I realize this is an old thread, but (I hope) this is related: is there
documentation somewhere about the naming conventions for the generated message
headers in ROS 2? The ` .msg ` files are all CamelCase, but the ` .hpp ` file
names all seem to be converted to snake_case, which was a bit confusing at
first.


ament_export_dependencies(rosidl_default_runtime)


Include the header of our newly created ` AddressBook.msg  ` .


This tutorial will focus on the msg interface type, but the steps here are
applicable to all interface types.


####  2.1 Build a msg file  ï


* **bounded strings** : Whereas the ROS 1 IDL allows unbounded strings (e.g., ` string  foo  ` ), the ROS 2 IDL further allows bounded strings (e.g., ` string<=5  bar  ` ).


* Services


[ DDS type ](https://design.ros2.org/articles/mapping_dds_types.html)

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

bool


* Fields


builtins.int*


**You're reading the documentation for a version of ROS 2 that has reached its
EOL (end-of-life), and is no longer officially supported. If you want up-to-
date information, please have a look at[ Iron ](../../iron/index.html) . **


_Built-in-types currently supported:_


#include "rosidl_tutorials_msgs/msg/contact.hpp"


  * [ ](../../index.html)
  * [ Concepts ](../../Concepts.html)
  * [ Basic Concepts ](../Basic.html)
  * Interfaces
  * [ Edit on GitHub ](https://github.com/ros2/ros2_documentation/blob/rolling/source/Concepts/Basic/About-Interfaces.rst)


[ @dirk-thomas ](/u/dirk-thomas) ’s link above mentions


long long

uint64


Releases


Note


You cannot embed another service inside of a service.


    rosidl_generate_interfaces(${PROJECT_NAME}
      ${msg_files}
    )


Default values can be set to any field in the message type. Currently default
values are not supported for string arrays and complex types (i.e. types not
present in the built-in-types table above; that applies to all nested
messages).


For ROS 2 the format of the interface files is specified in [
http://design.ros2.org/articles/interface_definition.html#naming-of-messages-
and-services
](http://design.ros2.org/articles/interface_definition.html#naming-of-
messages-and-services) . The naming scheme for the filename hasn’t changed
since ROS 1 and still only allows alphanumeric characters.


* 4\. New features in ROS 2 interfaces


Camel case would start the identifier with a lower-case letter.


* Background


While best practice is to declare interfaces in dedicated interface packages,
sometimes it can be convenient to declare, create and use an interface all in
one package.


builtins.list*


Constants names have to be UPPERCASE


* action: ` .action  ` files describe actions. They are composed of three parts: a goal, a result, and feedback. Each part is a message declaration itself.


There are [ several design articles ](https://design.ros2.org/#interfaces) on
ROS 2 interfaces and the IDL (interface definition language).


builtins.int*


builtins.bool


    rosidl_generate_interfaces(${PROJECT_NAME}
      ${msg_files}
      ${srv_files}
    )


    uint8 x 42
    int16 y -2000
    string full_name "John Doe"
    int32[] samples [-200, -100, 0, 100, 200]


For example:


> So… if I named a .msg “Sensor3DState.msg” what would the .hpp be?
>  sensor3_Dstate.hpp? sensor3_d_state.hpp?


    <build_depend>rosidl_tutorials_msgs</build_depend>

    <exec_depend>rosidl_tutorials_msgs</exec_depend>


sequence

bounded dynamic array


Here is a very simple example of a service that takes in a string and returns
a string:


> “all lowercases and an underscore before every upercase in the the original
> camelcase name + .hpp”


###  4 Try it out  ï


std::array<T, N>


Each constant definition is like a field description with a default value,
except that this value can never be changed programatically. This value
assignment is indicated by use of an equal â=â sign, e.g.


builtins.str


[ dirk-thomas  ](https://discourse.ros.org/u/dirk-thomas) September 7, 2017,
3:40pm  2


    int32 my_int
    string my_string


Path to the output file or directory. A relative path is treated with respect
to the value of  [ ` CMAKE_CURRENT_BINARY_DIR  `
](../variable/CMAKE_CURRENT_BINARY_DIR.html#variable:CMAKE_CURRENT_BINARY_DIR
"CMAKE_CURRENT_BINARY_DIR") . If the path names an existing directory the
output file is placed in that directory with the same file name as the input
file. If the path contains non-existent directories, they are created.
` NO_SOURCE_PERMISSIONS  `

New in version 3.19.
Do not transfer the permissions of the input file to the output file. The
copied file permissions default to the standard 644 value (-rw-r--r--).
` USE_SOURCE_PERMISSIONS  `

New in version 3.20.
Transfer the permissions of the input file to the output file. This is already
the default behavior if none of the three permissions-related keywords are
given ( ` NO_SOURCE_PERMISSIONS  ` , ` USE_SOURCE_PERMISSIONS  ` or `
FILE_PERMISSIONS  ` ). The ` USE_SOURCE_PERMISSIONS  ` keyword mostly serves
as a way of making the intended behavior clearer at the call site.
` FILE_PERMISSIONS  <permissions>...  `

New in version 3.20.
Ignore the input file's permissions and use the specified ` <permissions> `
for the output file instead.
` COPYONLY  `

Copy the file without replacing any variable references or other content. This
option may not be used with ` NEWLINE_STYLE  ` .
` ESCAPE_QUOTES  `

Escape any substituted quotes with backslashes (C-style).
` @ONLY  `

Restrict variable replacement to references of the form ` @VAR@  ` . This is
useful for configuring scripts that use ` ${VAR}  ` syntax.
` NEWLINE_STYLE  <style> `

Specify the newline style for the output file. Specify ` UNIX  ` or ` LF  `
for ` \n  ` newlines, or specify ` DOS  ` , ` WIN32  ` , or ` CRLF  ` for `


std::string


builtins.str*


Messages are described and defined in ` .msg  ` files in the ` msg/  `
directory of a ROS package. ` .msg  ` files are composed of two parts: fields
and constants.


Now youâre ready to generate source files from your msg definition. Weâll
skip the compile step for now as weâll do it all together below in step 4.


Messages are a way for a ROS 2 node to send data on the network to other ROS
nodes, with no response expected. For instance, if a ROS 2 node reads
temperature data from a sensor, it can then publish that data on the ROS 2
network using a ` Temperature  ` message. Other nodes on the ROS 2 network can
subscribe to that data and receive the ` Temperature  ` message.


Each field consists of a type and a name, separated by a space, i.e:


#  Interfaces  ï


Finally send the message periodically.


builtins.int*


Building and running these changes would show the msg defined as expected, as
well as the array of msgs defined above.


* 5 (Extra) Use an existing interface definition


* msg: ` .msg  ` files are simple text files that describe the fields of a ROS message. They are used to generate source code for messages in different languages.


* Background


constanttype CONSTANTNAME=constantvalue


builtins.float*


  * [ Installation ](../Installation.html)
    * [ Ubuntu (Debian) ](../Installation/Ubuntu-Install-Debians.html)
    * [ Windows (binary) ](../Installation/Windows-Install-Binary.html)
    * [ Alternatives ](../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)
      * [ macOS (source) ](../Installation/Alternatives/macOS-Development-Setup.html)
      * [ macOS (binary) ](../Installation/Alternatives/macOS-Install-Binary.html)
      * [ Fedora (source) ](../Installation/Alternatives/Fedora-Development-Setup.html)
      * [ Latest development (source) ](../Installation/Alternatives/Latest-Development-Setup.html)
    * [ Maintain source checkout ](../Installation/Maintaining-a-Source-Checkout.html)
    * [ Testing with pre-release binaries ](../Installation/Testing.html)
    * [ DDS implementations ](../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)
  * [ Distributions ](../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)
    * [ 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)
      * [ Foxy Fitzroy ( ` foxy  ` ) ](../Releases/Release-Foxy-Fitzroy.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)
      * [ Alphas ](../Releases/Alpha-Overview.html)


* 2.1 Fields


[ Previous ](About-ROS-2-Client-Libraries.html "About ROS 2 client libraries")
[ Next  ](About-ROS-2-Parameters.html "About parameters in ROS 2")


[ clalancette  ](https://discourse.ros.org/u/clalancette) May 31, 2022, 3:20pm
11


float


##  Background  ï


In your workspace ` src  ` directory, create a package ` more_interfaces  `
and make a directory within it for msg files:


    source install/setup.bash
    ros2 topic echo /address_book

    . install/setup.bash
    ros2 topic echo /address_book

    call install/setup.bat
    ros2 topic echo /address_book


Recall that interfaces can currently only be defined in CMake packages. It is
possible, however, to have Python libraries and nodes in CMake packages (using
[ ament_cmake_python
](https://github.com/ament/ament_cmake/tree/foxy/ament_cmake_python) ), so you
could define interfaces and Python nodes together in one package. Weâll use
a CMake package and C++ nodes here for the sake of simplicity.


octet

char


[ BBelmar  ](https://discourse.ros.org/u/BBelmar) May 31, 2022, 2:18pm  9


You can use ` set  ` in ` CMakeLists.txt  ` to neatly list all of your
interfaces:


[ Next Generation ROS  ](/c/ng-ros/25)


[ ROS 2 Documentation: Rolling ![Logo](../../_static/rolling-small.png)
](../../index.html)


Type name


    using namespace std::chrono_literals;

    class AddressBookPublisher : public rclcpp::Node
    {
    public:
      AddressBookPublisher()
      : Node("address_book_publisher")
      {
        address_book_publisher_ =
          this->create_publisher<more_interfaces::msg::AddressBook>("address_book");


* Constants


      * [ Recording a bag from a node (C++) ](../../Tutorials/Advanced/Recording-A-Bag-From-Your-Own-Node-CPP.html)
      * [ Recording a bag from a node (Python) ](../../Tutorials/Advanced/Recording-A-Bag-From-Your-Own-Node-Py.html)
      * [ Reading from a bag file (C++) ](../../Tutorials/Advanced/Reading-From-A-Bag-File-CPP.html)
      * [ How to use ros2_tracing to trace and analyze an application ](../../Tutorials/Advanced/ROS2-Tracing-Trace-and-Analyze.html)
      * [ Simulators ](../../Tutorials/Advanced/Simulators/Simulation-Main.html)
        * [ Webots ](../../Tutorials/Advanced/Simulators/Webots/Simulation-Webots.html)
          * [ Installation (Ubuntu) ](../../Tutorials/Advanced/Simulators/Webots/Installation-Ubuntu.html)
          * [ Installation (Windows) ](../../Tutorials/Advanced/Simulators/Webots/Installation-Windows.html)
          * [ Installation (macOS) ](../../Tutorials/Advanced/Simulators/Webots/Installation-MacOS.html)
          * [ Setting up a robot simulation (Basic) ](../../Tutorials/Advanced/Simulators/Webots/Setting-Up-Simulation-Webots-Basic.html)
          * [ Setting up a robot simulation (Advanced) ](../../Tutorials/Advanced/Simulators/Webots/Setting-Up-Simulation-Webots-Advanced.html)
          * [ Setting up a Reset Handler ](../../Tutorials/Advanced/Simulators/Webots/Simulation-Reset-Handler.html)
          * [ The Ros2Supervisor Node ](../../Tutorials/Advanced/Simulators/Webots/Simulation-Supervisor.html)
        * [ Gazebo ](../../Tutorials/Advanced/Simulators/Gazebo/Simulation-Gazebo.html)
          * [ Setting up a robot simulation (Gazebo) ](../../Tutorials/Advanced/Simulators/Gazebo/Gazebo.html)
      * [ Security ](../../Tutorials/Advanced/Security/Security-Main.html)
        * [ Setting up security ](../../Tutorials/Advanced/Security/Introducing-ros2-security.html)
        * [ Understanding the security keystore ](../../Tutorials/Advanced/Security/The-Keystore.html)
        * [ Ensuring security across machines ](../../Tutorials/Advanced/Security/Security-on-Two.html)
        * [ Examining network traffic ](../../Tutorials/Advanced/Security/Examine-Traffic.html)
        * [ Setting access controls ](../../Tutorials/Advanced/Security/Access-Controls.html)
        * [ Deployment Guidelines ](../../Tutorials/Advanced/Security/Deployment-Guidelines.html)
    * [ Demos ](../../Tutorials/Demos.html)
      * [ Using quality-of-service settings for lossy networks ](../../Tutorials/Demos/Quality-of-Service.html)
      * [ Managing nodes with managed lifecycles ](../../Tutorials/Demos/Managed-Nodes.html)
      * [ Setting up efficient intra-process communication ](../../Tutorials/Demos/Intra-Process-Communication.html)
      * [ Recording and playing back data with ` rosbag  ` using the ROS 1 bridge ](../../Tutorials/Demos/Rosbag-with-ROS1-Bridge.html)
      * [ Understanding real-time programming ](../../Tutorials/Demos/Real-Time-Programming.html)
      * [ Experimenting with a dummy robot ](../../Tutorials/Demos/dummy-robot-demo.html)
      * [ Logging ](../../Tutorials/Demos/Logging-and-logger-configuration.html)
      * [ Creating a content filtering subscription ](../../Tutorials/Demos/Content-Filtering-Subscription.html)
      * [ Configure service introspection ](../../Tutorials/Demos/Service-Introspection.html)
    * [ Miscellaneous ](../../Tutorials/Miscellaneous.html)
      * [ Deploying on IBM Cloud Kubernetes [community-contributed] ](../../Tutorials/Miscellaneous/Deploying-ROS-2-on-IBM-Cloud.html)
      * [ Using Eclipse Oxygen with ` rviz2  ` [community-contributed] ](../../Tutorials/Miscellaneous/Eclipse-Oxygen-with-ROS-2-and-rviz2.html)
      * [ Building a real-time Linux kernel [community-contributed] ](../../Tutorials/Miscellaneous/Building-Realtime-rt_preempt-kernel-for-ROS-2.html)
      * [ Building a package with Eclipse 2021-06 ](../../Tutorials/Miscellaneous/Building-ROS2-Package-with-eclipse-2021-06.html)
  * [ How-to Guides ](../../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)


You could change the callback to something like this:


For example:


    fieldtype1 fieldname1
    fieldtype2 fieldname2
    fieldtype3 fieldname3


* 2.1.1 Field types


* srv: ` .srv  ` files describe a service. They are composed of two parts: a request and a response. The request and response are message declarations.


This creates a ` foo.h  ` in the build directory corresponding to this source
directory. If the ` FOO_ENABLE  ` option is on, the configured file will
contain:

    #define FOO_ENABLE
    #define FOO_STRING "foo"

Otherwise it will contain:

    /* #undef FOO_ENABLE */
    /* #undef FOO_STRING */

One may then use the  [ ` target_include_directories()  `
](target_include_directories.html#command:target_include_directories
"target_include_directories") command to specify the output directory as an
include directory:

    target_include_directories(<target> [SYSTEM] <INTERFACE|PUBLIC|PRIVATE> "${CMAKE_CURRENT_BINARY_DIR}")

so that sources may include the header as ` #include  <foo.h> ` .
##  See Also  Â¶
  * [ ` file(GENERATE)  ` ](file.html#generate "file\(generate\)")
###  [ Table of Contents ](../index.html)
  * configure_file
    * Options
    * Transformations
    * Example
    * See Also
####  Previous topic
[ cmake_policy ](cmake_policy.html "previous chapter")
####  Next topic
[ continue ](continue.html "next chapter")
###  This Page
  * [ Show Source ](../_sources/command/configure_file.rst.txt)
###  Quick search
###  Navigation
  * [ index ](../genindex.html "General Index")


* Tasks


##  Background  ï


sequence

bounded dynamic array


* a built-in-type


    install/local_setup.ps1
    ros2 run more_interfaces publish_address_book


Note


A service description file consists of a request and a response msg type,
separated by ` ---  ` . Any two ` .msg  ` files concatenated with a ` ---  `
are a legal service description.


###  Fields  ï


boolean

byte


float

float64


char


[ ros2 ](https://discourse.ros.org/tag/ros2)


string

All types that are more permissive than their ROS definition enforce the ROS
constraints in range and length by software


sequence<T, N>

bounded string


####  Field default value  ï


    #include <chrono>
    #include <memory>

    #include "rclcpp/rclcpp.hpp"
    #include "more_interfaces/msg/address_book.hpp"

    using namespace std::chrono_literals;

    class AddressBookPublisher : public rclcpp::Node
    {
    public:
      AddressBookPublisher()
      : Node("address_book_publisher")
      {
        address_book_publisher_ =
          this->create_publisher<more_interfaces::msg::AddressBook>("address_book", 10);

        auto publish_msg = [this]() -> void {
            auto message = more_interfaces::msg::AddressBook();

            message.first_name = "John";
            message.last_name = "Doe";
            message.phone_number = "1234567890";
            message.phone_type = message.PHONE_TYPE_MOBILE;

            std::cout << "Publishing Contact\nFirst:" << message.first_name <<
              "  Last:" << message.last_name << std::endl;

            this->address_book_publisher_->publish(message);
          };
        timer_ = this->create_wall_timer(1s, publish_msg);
      }

    private:
      rclcpp::Publisher<more_interfaces::msg::AddressBook>::SharedPtr address_book_publisher_;
      rclcpp::TimerBase::SharedPtr timer_;
    };


[ C++ ](https://design.ros2.org/articles/generated_interfaces_cpp.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++) ](../Advanced/Topic-Statistics-Tutorial/Topic-Statistics-Tutorial.html)
      * [ Using Fast DDS Discovery Server as discovery protocol [community-contributed] ](../Advanced/Discovery-Server/Discovery-Server.html)
      * [ Implementing a custom memory allocator ](../Advanced/Allocator-Template-Tutorial.html)
      * [ Recording a bag from a node (C++) ](../Advanced/Recording-A-Bag-From-Your-Own-Node-CPP.html)
      * [ Simulators ](../Advanced/Simulators/Simulation-Main.html)
        * [ Webots ](../Advanced/Simulators/Webots/Simulation-Webots.html)
          * [ Installation (Ubuntu) ](../Advanced/Simulators/Webots/Installation-Ubuntu.html)
          * [ Installation (Windows) ](../Advanced/Simulators/Webots/Installation-Windows.html)
          * [ Installation (macOS) ](../Advanced/Simulators/Webots/Installation-MacOS.html)
          * [ Setting up a robot simulation (Basic) ](../Advanced/Simulators/Webots/Setting-Up-Simulation-Webots-Basic.html)
          * [ Setting up a robot simulation (Advanced) ](../Advanced/Simulators/Webots/Setting-Up-Simulation-Webots-Advanced.html)
        * [ Ignition ](../Advanced/Simulators/Ignition/Simulation-Ignition.html)
          * [ Setting up a robot simulation (Ignition Gazebo) ](../Advanced/Simulators/Ignition/Ignition.html)


Type name


* action: ` .action  ` files describe actions. They are composed of three parts: a goal, a result, and feedback. Each part is a message declaration itself.


* Field default value


builtins.int*


* 2\. Message description specification


Defining a default value is done by adding a third element to the field
definition line, i.e:


As always, donât forget to [ source ROS 2  ](../Beginner-CLI-
Tools/Configuring-ROS2-Environment.html) in every new terminal you open.


* first_name: of type string


Contents


double

int8


T[N]

unbounded dynamic array


* phone_type: of type uint8, with several named constant values defined


* Next steps


    string str
    ---
    string str


long

uint32


std::string


builtins.str


* **default values** : Whereas the ROS 1 IDL allows constant fields (e.g., ` int32  X=123  ` ), the ROS 2 IDL further allows default values to be specified (e.g., ` int32  X  123  ` ). The default value is used when constructing a message/service object and can be subsequently overridden by assigning to the field. You can also specify default values for action parts.


builtins.str*


[ christophebedard  ](https://discourse.ros.org/u/christophebedard) April 9,
2020, 1:35pm  4


* Summary


We need to create a new target for this node in the ` CMakeLists.txt  ` :


builtins.int*


Note


    int32[] unbounded_integer_array
    int32[5] five_integers_array
    int32[<=5] up_to_five_integers_array

    string string_of_unbounded_size
    string<=10 up_to_ten_characters_string

    string[<=5] up_to_five_unbounded_strings
    string<=10[] unbounded_array_of_strings_up_to_ten_characters_each
    string<=10[<=5] up_to_five_strings_up_to_ten_characters_each


unsigned long

int64


    * [ Building ROS 2 with tracing instrumentation ](../How-To-Guides/Building-ROS-2-with-Tracing-Instrumentation.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)
    * [ 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 ](../Concepts.html)
    * [ The ROS_DOMAIN_ID ](About-Domain-ID.html)
    * [ About different ROS 2 DDS/RTPS vendors ](About-Different-Middleware-Vendors.html)
    * [ About logging and logger configuration ](About-Logging.html)
    * [ About Quality of Service settings ](About-Quality-of-Service-Settings.html)
    * [ About ROS 2 client libraries ](About-ROS-2-Client-Libraries.html)
    * About ROS 2 interfaces
    * [ About parameters in ROS 2 ](About-ROS-2-Parameters.html)
    * [ Executors ](About-Executors.html)
    * [ About topic statistics ](About-Topic-Statistics.html)
    * [ Introspection with command line tools ](About-Command-Line-Tools.html)
    * [ Overview and usage of RQt ](About-RQt.html)
    * [ About Composition ](About-Composition.html)
    * [ On the mixing of ament and catkin (catment) ](About-Catment.html)
    * [ About Cross-compilation ](About-Cross-Compilation.html)
    * [ About tf2 ](About-Tf2.html)
    * [ About the build system ](About-Build-System.html)
    * [ About internal ROS 2 interfaces ](About-Internal-Interfaces.html)
    * [ About ROS 2 middleware implementations ](About-Middleware-Implementations.html)
    * [ About ROS 2 client libraries ](About-ROS-2-Client-Libraries.html)
  * [ Contact ](../Contact.html)
  * [ The ROS 2 Project ](../The-ROS2-Project.html)
    * [ Contributing ](../The-ROS2-Project/Contributing.html)
      * [ ROS 2 developer guide ](../The-ROS2-Project/Contributing/Developer-Guide.html)
      * [ Code style and language versions ](../The-ROS2-Project/Contributing/Code-Style-Language-Versions.html)
      * [ Quality guide: ensuring code quality ](../The-ROS2-Project/Contributing/Quality-Guide.html)
      * [ Migration guide from ROS 1 ](../The-ROS2-Project/Contributing/Migration-Guide.html)
        * [ Python migration guide from ROS 1 ](../The-ROS2-Project/Contributing/Migration-Guide-Python.html)
      * [ ROS Build Farms ](../The-ROS2-Project/Contributing/Build-Farms.html)
      * [ Windows Tips and Tricks ](../The-ROS2-Project/Contributing/Windows-Tips-and-Tricks.html)


For instance, the ` Fibonacci  ` action definition contains the following:


In order to use the messages generated in the same package we need to use the
following CMake code:


Type name


  * [ Installation ](../../Installation.html)
    * [ Ubuntu (Debian packages) ](../../Installation/Ubuntu-Install-Debians.html)
    * [ Windows (binary) ](../../Installation/Windows-Install-Binary.html)
    * [ RHEL (RPM packages) ](../../Installation/RHEL-Install-RPMs.html)
    * [ Alternatives ](../../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)
    * [ Maintain source checkout ](../../Installation/Maintaining-a-Source-Checkout.html)
    * [ Testing with pre-release binaries ](../../Installation/Testing.html)
    * [ DDS implementations ](../../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)
  * [ Distributions ](../../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)
    * [ Rolling Ridley ( ` rolling  ` ) ](../../Releases/Release-Rolling-Ridley.html)
    * [ Development Distribution ](../../Releases/Development.html)
      * [ Jazzy Jalisco ( ` jazzy  ` ) ](../../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)
      * [ Foxy Fitzroy ( ` foxy  ` ) ](../../Releases/Release-Foxy-Fitzroy.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)


Create an ` AddressBook  ` message instance that we will later publish.


Services are a request/response communication, where the client (requester) is
waiting for the server (responder) to make a short computation and return a
result.


|  6  |  1958  |  June 19, 2020

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


builtins.bytes*


    * [ Using Custom Rosdistro Version ](../../How-To-Guides/Using-Custom-Rosdistro.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 ](../../Concepts.html)
    * [ Basic Concepts ](../Basic.html)
      * [ Nodes ](About-Nodes.html)
      * [ Discovery ](About-Discovery.html)
      * Interfaces
      * [ Topics ](About-Topics.html)
      * [ Services ](About-Services.html)
      * [ Actions ](About-Actions.html)
      * [ Parameters ](About-Parameters.html)
      * [ Introspection with command line tools ](About-Command-Line-Tools.html)
      * [ Launch ](About-Launch.html)
      * [ Client libraries ](About-Client-Libraries.html)
    * [ Intermediate Concepts ](../Intermediate.html)
      * [ The ROS_DOMAIN_ID ](../Intermediate/About-Domain-ID.html)
      * [ Different ROS 2 middleware vendors ](../Intermediate/About-Different-Middleware-Vendors.html)
      * [ Logging and logger configuration ](../Intermediate/About-Logging.html)
      * [ Quality of Service settings ](../Intermediate/About-Quality-of-Service-Settings.html)
      * [ Executors ](../Intermediate/About-Executors.html)
      * [ Topic statistics ](../Intermediate/About-Topic-Statistics.html)
      * [ Overview and usage of RQt ](../Intermediate/About-RQt.html)
      * [ Composition ](../Intermediate/About-Composition.html)
      * [ Cross-compilation ](../Intermediate/About-Cross-Compilation.html)
      * [ ROS 2 Security ](../Intermediate/About-Security.html)
      * [ Tf2 ](../Intermediate/About-Tf2.html)
    * [ Advanced Concepts ](../Advanced.html)
      * [ The build system ](../Advanced/About-Build-System.html)
      * [ Internal ROS 2 interfaces ](../Advanced/About-Internal-Interfaces.html)
      * [ ROS 2 middleware implementations ](../Advanced/About-Middleware-Implementations.html)
  * [ Contact ](../../Contact.html)
  * [ The ROS 2 Project ](../../The-ROS2-Project.html)
    * [ Contributing ](../../The-ROS2-Project/Contributing.html)
      * [ ROS 2 developer guide ](../../The-ROS2-Project/Contributing/Developer-Guide.html)
      * [ Code style and language versions ](../../The-ROS2-Project/Contributing/Code-Style-Language-Versions.html)
      * [ Quality guide: ensuring code quality ](../../The-ROS2-Project/Contributing/Quality-Guide.html)
      * [ ROS Build Farms ](../../The-ROS2-Project/Contributing/Build-Farms.html)
      * [ Windows Tips and Tricks ](../../The-ROS2-Project/Contributing/Windows-Tips-and-Tricks.html)


* a built-in-type


double

int8


timer_ = this->create_wall_timer(1s, publish_msg);


Yes, that’s pretty much it.


builtins.str*


    <request_type> <request_fieldname>
    ---
    <response_type> <response_fieldname>
    ---
    <feedback_type> <feedback_fieldname>


ROS applications typically communicate through interfaces of one of three
types: [ topics  ](About-Topics.html) , [ services  ](About-Services.html) ,
or [ actions  ](About-Actions.html) . ROS 2 uses a simplified description
language, the interface definition language (IDL), to describe these
interfaces. This description makes it easy for ROS tools to automatically
generate source code for the interface type in several target languages.


octet

int16


    int32 my_int
    string my_string


Thanks!


By adding the .msg files manually, we make sure that CMake knows when it has
to reconfigure the project after you add other .msg files.


* srv: ` .srv  ` files describe a service. They are composed of two parts: a request and a response. The request and response are message declarations.


Open ` package.xml  ` and add the following lines:


In a [ previous tutorial  ](Custom-ROS2-Interfaces.html) , you learned how to
create custom msg and srv interfaces.


* 2.2 Constants


Other Versions  v: rolling


Field types can be:


builtins.str


Services are described and defined in ` .srv  ` files in the ` srv/  `
directory of a ROS package.


To confirm the message is being published on the ` address_book  ` topic, open
another terminal, source the workspace, and call ` topic  echo  ` :


builtins.int*


* The source code for this example is available [ here ](https://github.com/turtlebot/turtlebot4_tutorials/blob/galactic/turtlebot4_python_tutorials/turtlebot4_python_tutorials/nav_through_poses.py) .


TurtleBot 4 Navigator requires at least version 1.0.11 of Nav2 Simple
Commander


[ __ Previous ](/turtlebot4-user-manual/tutorials/navigation.html
"Navigation")


        navigator.info(f'Battery is at {(battery_percent*100):.2f}% charge')

    # Check battery charge level
    if (battery_percent < BATTERY_CRITICAL):
        navigator.error('Battery critically low. Charge or power down')
        break


![Office Map](media/office.png) Office Map shown in Rviz


        def main():
        rclpy.init()

        navigator = TurtleBot4Navigator()

        # Start on dock
        if not navigator.getDockedStatus():
            navigator.info('Docking before initialising pose')
            navigator.dock()

        # Set initial pose
        initial_pose = navigator.getPoseStamped([0.0, 0.0], TurtleBot4Directions.NORTH)
        navigator.setInitialPose(initial_pose)

        # Wait for Nav2
        navigator.waitUntilNav2Active()

        # Set goal poses
        goal_pose = navigator.getPoseStamped([-13.0, 9.0], TurtleBot4Directions.EAST)

        # Undock
        navigator.undock()

        # Go to each goal pose
        navigator.startToPose(goal_pose)

        rclpy.shutdown()


[ Troubleshooting ](/turtlebot4-user-manual/troubleshooting/)


  * galactic
  * humble


ros2 launch turtlebot4_ignition_bringup ignition.launch.py nav:=true slam:=off localization:=true


###  Watch Navigation Progress in RViz


The next step is to create a list of ` PoseStamped ` messages which represent
the poses that the robot needs to drive through.


global_costmap:
  global_costmap:
    ros__parameters:
      update_frequency: 1.0
      publish_frequency: 1.0
      global_frame: map
      robot_base_frame: base_link
      use_sim_time: True
      robot_radius: 0.175
      resolution: 0.06
      track_unknown_space: true
      plugins: ["static_layer", "obstacle_layer", "inflation_layer"]
      obstacle_layer:
        plugin: "nav2_costmap_2d::ObstacleLayer"
        enabled: True
        observation_sources: scan
        scan:
          topic: scan
          max_obstacle_height: 2.0
          clearing: True
          marking: True
          data_type: "LaserScan"
          raytrace_max_range: 3.0
          raytrace_min_range: 0.0
          obstacle_max_range: 2.5
          obstacle_min_range: 0.0
      static_layer:
        plugin: "nav2_costmap_2d::StaticLayer"
        map_subscribe_transient_local: True
      inflation_layer:
        plugin: "nav2_costmap_2d::InflationLayer"
        cost_scaling_factor: 4.0
        inflation_radius: 0.45
      always_send_full_costmap: True


If the user selected to exit the program then the loop is terminated and the
program will exit.


The user will then enter a number and press enter.


v1.0.0  __


        class BatteryMonitor(Node):

        def __init__(self, lock):
            super().__init__('battery_monitor')

            self.lock = lock

            # Subscribe to the /battery_state topic
            self.battery_state_subscriber = self.create_subscription(
                BatteryState,
                'battery_state',
                self.battery_state_callback,
                qos_profile_sensor_data)

        # Callbacks
        def battery_state_callback(self, batt_msg: BatteryState):
            with self.lock:
                self.battery_percent = batt_msg.percentage

        def thread_function(self):
            executor = SingleThreadedExecutor()
            executor.add_node(self)
            executor.spin()


bt_navigator_navigate_through_poses_rclcpp_node:
  ros__parameters:
    use_sim_time: True


If using multiple robots through the namespacing method, an additional `
namespace ` parameter must be passed to both the Localization and Nav2 launch
files. For example: ` namespace:=/robot1 ` See [ Multiple robots
](/turtlebot4-user-manual/tutorials/multiple_robots.html) for more details.


[ Setup ](/turtlebot4-user-manual/setup/)


ros2 launch turtlebot4_navigation nav2.launch.py


behavior_server:
  ros__parameters:
    costmap_topic: local_costmap/costmap_raw
    footprint_topic: local_costmap/published_footprint
    cycle_frequency: 10.0
    behavior_plugins: ["spin", "backup", "drive_on_heading", "assisted_teleop", "wait"]
    spin:
      plugin: "nav2_behaviors/Spin"
    backup:
      plugin: "nav2_behaviors/BackUp"
    drive_on_heading:
      plugin: "nav2_behaviors/DriveOnHeading"
    wait:
      plugin: "nav2_behaviors/Wait"
    assisted_teleop:
      plugin: "nav2_behaviors/AssistedTeleop"
    global_frame: odom
    robot_base_frame: base_link
    transform_tolerance: 0.1
    use_sim_time: true
    simulate_ahead_time: 2.0
    max_rotational_vel: 1.0
    min_rotational_vel: 0.4
    rotational_acc_lim: 3.2


The robot poses that make up the robot's patrol loop are assembled into a
list.


    def user_input(self, msg):
        """Process user input and optionally execute resulting code."""
        # User input
        if not self.ready_for_input:
            # This doesn't seem to be an issue when there's only one publisher
            # but it's good practice
            self.info(f"Received input <{msg.data}> when not ready, skipping")
            return
        self.publish_status(False)
        self.info(f"Received input <{msg.data}>")

        # Add "# " to the start to match code samples, issue query
        query = '# ' + msg.data
        result = self.query(f'{self.full_prompt}', query, ['#', 'objects = ['])

        # This is because the example API calls 'navigator', not 'self.navigator'
        navigator = self.navigator

        # Execute?
        if not self.get_parameter('parking_brake').value:
            try:
                exec(result, globals(), locals())
            except Exception:
                self.error("Failure to execute resulting code:")
                self.error("---------------\n"+result)
                self.error("---------------")
        self.publish_status(True)


    rclpy.init()

    navigator = TurtleBot4Navigator()


ros2 run turtlebot4_python_tutorials nav_through_poses


This will launch the simulation in the default ` depot ` world and will use
the existing ` depot.yaml ` file for the map. If you are using a custom world
you will need to build the [ turtlebot4_simulator package ](/turtlebot4-user-
manual/software/turtlebot4_simulator.html#source-installation) from source and
place your world file [ alongside the others
](https://github.com/turtlebot/turtlebot4_simulator/tree/galactic/turtlebot4_ignition_bringup/worlds)
. You will then need to create a map for it and pass both the world name and
the map file path in as launch arguments.


` model_name ` is unlikely to need to change, but options can be found [ here
](https://platform.openai.com/docs/guides/gpt)


* This example demonstrates how to create an interactive delivery route. The user is able to send the robot to different pre-defined locations on demand using the terminal interface. It then uses the  Navigate to Pose  behaviour to navigate to the pose.


where STRING is a command string which corresponds to the prompted API. If you
are using unmodified code, the following commands are all good examples:


Once the simulation has started, open another terminal and run:


####  GPTNode


    # Progress checker parameters
    progress_checker:
      plugin: "nav2_controller::SimpleProgressChecker"
      required_movement_radius: 0.5
      movement_time_allowance: 10.0
    # Goal checker parameters
    #precise_goal_checker:
    #  plugin: "nav2_controller::SimpleGoalChecker"
    #  xy_goal_tolerance: 0.25
    #  yaw_goal_tolerance: 0.25
    #  stateful: True
    general_goal_checker:
      stateful: True
      plugin: "nav2_controller::SimpleGoalChecker"
      xy_goal_tolerance: 0.25
      yaw_goal_tolerance: 0.25
    # DWB parameters
    FollowPath:
      plugin: "dwb_core::DWBLocalPlanner"
      debug_trajectory_details: True
      min_vel_x: 0.0
      min_vel_y: 0.0
      max_vel_x: 0.26
      max_vel_y: 0.0
      max_vel_theta: 1.0
      min_speed_xy: 0.0
      max_speed_xy: 0.26
      min_speed_theta: 0.0
      # Add high threshold velocity for turtlebot 3 issue.
      # https://github.com/ROBOTIS-GIT/turtlebot3_simulations/issues/75
      acc_lim_x: 2.5
      acc_lim_y: 0.0
      acc_lim_theta: 3.2
      decel_lim_x: -2.5
      decel_lim_y: 0.0
      decel_lim_theta: -3.2
      vx_samples: 20
      vy_samples: 5
      vtheta_samples: 20
      sim_time: 1.7


To buy a TurtleBot 4 please visit one of our distributors


    def generate_launch_description():
        return LaunchDescription([
            DeclareLaunchArgument('openai_api_key', default_value='',
                                  description='API key set up via \
                                  https://platform.openai.com/account/api-keys'),
            DeclareLaunchArgument('model_name', default_value='gpt-3.5-turbo',
                                  description='OpenAI model name as selected from \
                                  https://platform.openai.com/docs/guides/gpt'),
            DeclareLaunchArgument('parking_brake', default_value='true',
                                  description='Set to false to execute commands on the robot'),
            Node(
                package='turtlebot4_openai_tutorials',
                executable='natural_language_nav',
                output='screen',
                emulate_tty=True,
                parameters=[
                    {'openai_api_key': LaunchConfiguration('openai_api_key')},
                    {'model_name': LaunchConfiguration('model_name')},
                    {'parking_brake': LaunchConfiguration('parking_brake')}
                ]
            ),
        ])


__ Note


  *     goal_pose = []
    goal_pose.append(navigator.getPoseStamped([0.0, -1.0], TurtleBot4Directions.NORTH))
    goal_pose.append(navigator.getPoseStamped([1.7, -1.0], TurtleBot4Directions.EAST))
    goal_pose.append(navigator.getPoseStamped([1.6, -3.5], TurtleBot4Directions.NORTH))
    goal_pose.append(navigator.getPoseStamped([6.75, -3.46], TurtleBot4Directions.NORTH_WEST))
    goal_pose.append(navigator.getPoseStamped([7.4, -1.0], TurtleBot4Directions.SOUTH))
    goal_pose.append(navigator.getPoseStamped([-1.0, -1.0], TurtleBot4Directions.WEST))


[ ](https://clearpathrobotics.com/) [ ](https://www.openrobotics.org/) [
](https://docs.ros.org/en/humble/index.html) [
](https://github.com/turtlebot/TurtleBot4Lessons) [
](https://github.com/turtlebot) [
](https://clearpathrobotics.com/turtlebot-4/)


#  TurtleBot 4 Navigator


                    if position_index >= len(goal_pose):
                        position_index = 0

        battery_monitor.destroy_node()
        rclpy.shutdown()


The first part of ` main() ` creates the ` navigator ` and ` gpt ` nodes,
reads in the prompt file, and initializes navigation. The latter is virtually
identical to previous examples, with the only difference being the `
parking_brake ` parameter.


  * galactic
  * humble


This call will block until Nav2 is ready. Make sure you have launched Nav2.


Let's take a look at the launchfile.


####  2D Pose Estimate


###  Interacting with Nav2


    class TurtleBot4Directions(IntEnum):
        NORTH = 0
        NORTH_WEST = 45
        WEST = 90
        SOUTH_WEST = 135
        SOUTH = 180
        SOUTH_EAST = 225
        EAST = 270
        NORTH_EAST = 315


        map_subscribe_transient_local: True
      always_send_full_costmap: True


  * [ 1\. TurtleBot 4 Galactic ](/turtlebot4-user-manual/changelogs/galactic.html)
  * [ 2\. TurtleBot 4 Humble ](/turtlebot4-user-manual/changelogs/humble.html)


Now we can undock and follow the created path. In this example we use the
Follow Waypoints  behaviour, but this can easily be replaced with  Navigate
Through Poses  .


* This tutorial is only available in Humble


Let's take a look at the main function.


#####  User Input


__ Note


Stay Connected


* The [ TurtleBot 4 Navigator ](https://github.com/turtlebot/turtlebot4/blob/humble/turtlebot4_navigation/turtlebot4_navigation/turtlebot4_navigator.py) is a Python node that adds on to the [ Nav2 Simple Commander ](https://github.com/ros-planning/navigation2/blob/humble/nav2_simple_commander/nav2_simple_commander/robot_navigator.py) . It includes TurtleBot 4 specific features such as docking and undocking, as well as easy to use methods for navigating.


SLAM is useful for generating a new map, or navigating in unknown or dynamic
environments. It updates the map as it detects and changes, but cannot see
areas of the environment that it has not discovered yet.


[ Electrical ](/turtlebot4-user-manual/electrical/)


####  Set the initial pose


        # Check for exit
    elif goal_options[selected_index]['name'] == 'Exit':
        break


###  Launching navigation


* The [ TurtleBot 4 Navigator ](https://github.com/turtlebot/turtlebot4/blob/galactic/turtlebot4_navigation/turtlebot4_navigation/turtlebot4_navigator.py) is a Python node that adds on to the [ Nav2 Simple Commander ](https://github.com/ros-planning/navigation2/blob/galactic/nav2_simple_commander/nav2_simple_commander/robot_navigator.py) . It includes TurtleBot 4 specific features such as docking and undocking, as well as easy to use methods for navigating.


velocity_smoother:
  ros__parameters:
    use_sim_time: True
    smoothing_frequency: 20.0
    scale_velocities: False
    feedback: "OPEN_LOOP"
    max_velocity: [0.26, 0.0, 1.0]
    min_velocity: [-0.26, 0.0, -1.0]
    max_accel: [2.5, 0.0, 3.2]
    max_decel: [-2.5, 0.0, -3.2]
    odom_topic: "odom"
    odom_duration: 0.1
    deadband_velocity: [0.0, 0.0, 0.0]
    velocity_timeout: 1.0


![Navigation tools](media/nav_tools.png) Navigation tools in Rviz


        thread = Thread(target=battery_monitor.thread_function, daemon=True)
    thread.start()


    def __init__(self, navigator):
        super().__init__('gpt_node')
        self.declare_parameter('openai_api_key', '')
        self.declare_parameter('model_name', 'gpt-3.5-turbo')
        self.declare_parameter('parking_brake', True)

        # OpenAI key, model, prompt setup
        openai.api_key = self.get_parameter('openai_api_key').value
        self.model_name = self.get_parameter('model_name').value
        self.prompts = []
        self.full_prompt = ""

        # ROS stuff. Navigator node handle, topics
        self.navigator = navigator
        self.sub_input = self.create_subscription(String, 'user_input', self.user_input, 10)
        self.pub_ready = self.create_publisher(Bool, 'ready_for_input', 10)
        self.publish_status(False)


This code is the handler for new user input. If the system is ready to process
new information, it applies some formatting, calls the OpenAI API via `
self.query ` , and optionally executes the resulting code. The use of the `
globals() ` and ` locals() ` variables could likely be improved.


[ Setup ](/turtlebot4-user-manual/setup/)


bt_navigator:
  ros__parameters:
    use_sim_time: True
    global_frame: map
    robot_base_frame: base_link
    odom_topic: odom
    bt_loop_duration: 10
    default_server_timeout: 20
    # 'default_nav_through_poses_bt_xml' and 'default_nav_to_pose_bt_xml' are use defaults:
    # nav2_bt_navigator/navigate_to_pose_w_replanning_and_recovery.xml
    # nav2_bt_navigator/navigate_through_poses_w_replanning_and_recovery.xml
    # They can be set here or via a RewrittenYaml remap from a parent launch file to Nav2.
    plugin_lib_names:
    - nav2_compute_path_to_pose_action_bt_node
    - nav2_compute_path_through_poses_action_bt_node
    - nav2_smooth_path_action_bt_node
    - nav2_follow_path_action_bt_node
    - nav2_spin_action_bt_node
    - nav2_wait_action_bt_node
    - nav2_assisted_teleop_action_bt_node
    - nav2_back_up_action_bt_node
    - nav2_drive_on_heading_bt_node
    - nav2_clear_costmap_service_bt_node
    - nav2_is_stuck_condition_bt_node
    - nav2_goal_reached_condition_bt_node
    - nav2_goal_updated_condition_bt_node
    - nav2_globally_updated_goal_condition_bt_node
    - nav2_is_path_valid_condition_bt_node
    - nav2_initial_pose_received_condition_bt_node
    - nav2_reinitialize_global_localization_service_bt_node
    - nav2_rate_controller_bt_node
    - nav2_distance_controller_bt_node
    - nav2_speed_controller_bt_node
    - nav2_truncate_path_action_bt_node
    - nav2_truncate_path_local_action_bt_node
    - nav2_goal_updater_node_bt_node
    - nav2_recovery_node_bt_node
    - nav2_pipeline_sequence_bt_node
    - nav2_round_robin_node_bt_node
    - nav2_transform_available_condition_bt_node


ros2 run turtlebot4_python_tutorials patrol_loop


  * To run this example, start the Ignition Gazebo simulation:

        ros2 launch turtlebot4_ignition_bringup turtlebot4_ignition.launch.py nav2:=true slam:=false localization:=true rviz:=true


##  Navigate to Pose


To run this example, start the Ignition Gazebo simulation:


    def main():
        rclpy.init()

        navigator = TurtleBot4Navigator()

        # Set goal poses
        goal_pose = navigator.createPath()

        if len(goal_pose) == 0:
            navigator.error('No poses were given, exiting.')
            exit(0)

        # Start on dock
        if not navigator.getDockedStatus():
            navigator.info('Docking before initialising pose')
            navigator.dock()

        # Set initial pose
        initial_pose = navigator.getPoseStamped([0.0, 0.0], TurtleBot4Directions.NORTH)
        navigator.clearAllCostmaps()
        navigator.setInitialPose(initial_pose)

        # Wait for Nav2
        navigator.waitUntilNav2Active()

        # Undock
        navigator.undock()

        # Navigate through poses
        navigator.startFollowWaypoints(goal_pose)

        # Finished navigating, dock
        navigator.dock()

        rclpy.shutdown()


The loop then repeats, prompting the user for the next goal position.


This class serves to monitor the Create3® battery charge percentage and to
make it available for decision making.


An initial pose is required before navigation can begin.


![Nav2 Goal](media/nav_goal.gif) Driving the TurtleBot4 with a Nav2 Goal


  * ![Follow Waypoints](media/follow_waypoint_rviz.gif) Follow a set of Waypoints
  * Your browser does not support the video tag.  Follow a set of Waypoints


  * [ __ ](/turtlebot4-user-manual/ "/")
  * [ tutorials ](/turtlebot4-user-manual/tutorials/)
  * turtlebot4_navigator.md


Note that code constructs covered in previous tutorials may not be explained
in detail here.


  * galactic
  * humble


ros2 run turtlebot4_python_tutorials nav_to_pose


        with lock:
        battery_percent = battery_monitor.battery_percent


The remainder of the code continues until it is interrupted.


This will launch the simulation in the default ` warehouse ` world and will
use the existing [ ` warehouse.yaml `
](https://github.com/turtlebot/turtlebot4/blob/humble/turtlebot4_navigation/maps/warehouse.yaml)
file for the map.


To find out more please visit the TurtleBot 4 Overview


_Be sure to use the` --once ` flag, or else a forgotten terminal will be
billing you for credits constantly _


  * [ 1\. TurtleBot 4 ](/turtlebot4-user-manual/mechanical/turtlebot4.html)
  * [ 2\. TurtleBot 4 Lite ](/turtlebot4-user-manual/mechanical/turtlebot4_lite.html)
  * [ 3\. Payloads Over 9kg ](/turtlebot4-user-manual/mechanical/payloads.html)


Once the simulation has started, open another terminal and run:


This is a straightforward Python ROS 2 node ` __init__ ` example. It declares
and uses some parameters, sets up some variables, creates a subscription for a
user input string, and creates a publisher to provide status feedback.


* The source code for this example is available [ here ](https://github.com/turtlebot/turtlebot4_tutorials/blob/humble/turtlebot4_python_tutorials/turtlebot4_python_tutorials/nav_to_pose.py) .


     [ __ ](https://www.youtube.com/c/Clearpath "Clearpath Robotics Youtube")
     [ __ ](https://www.facebook.com/ClearpathInc/ "Clearpath Robotics Facebook")
     [ __ ](https://ca.linkedin.com/company/clearpathinc "Clearpath Robotics Linkedin")
     [ __ ](https://twitter.com/clearpathrobots "Clearpath Robotics Twitter")


All of these examples are designed to be run in the simulation environment. In
order to run these tutorial codes with a physical robot you must install the
tutorial package from source and modify target destinations to ones that make
sense in your map. You then must individually launch SLAM, Nav2, Localization,
and RViz as necessary and pass a map of your environment when launching
localization. This is only recommended for intermediate users and up because
there are no walkthrough instructions.


* For this tutorial we can launch navigation with the [ turtlebot4_navigation ](https://github.com/turtlebot/turtlebot4/tree/humble/turtlebot4_navigation) package.


[ __ Previous ](/turtlebot4-user-manual/tutorials/generate_map.html
"Generating a map")


It demonstrates how an Large Language Model (LLM) can be ‘taught' how to use
the Turtlebot 4 Navigation API with only a few examples, and also shows how an
LLM can easily bridge natural language commands to API calls without an
intermediate parsing step.


###  Creating a path with Rviz


        goal_options = [
        {'name': 'Home',
            'pose': navigator.getPoseStamped([-1.0, 1.0], TurtleBot4Directions.EAST)},

        {'name': 'Position 1',
            'pose': navigator.getPoseStamped([10.0, 6.0], TurtleBot4Directions.EAST)},

        {'name': 'Position 2',
            'pose': navigator.getPoseStamped([-9.0, 9.0], TurtleBot4Directions.NORTH)},

        {'name': 'Position 3',
            'pose': navigator.getPoseStamped([-12.0, 2.0], TurtleBot4Directions.NORTH_WEST)},

        {'name': 'Position 4',
            'pose': navigator.getPoseStamped([3.0, -7.0], TurtleBot4Directions.WEST)},

        {'name': 'Exit',
            'pose': None}
    ]


ros2 launch turtlebot4_viz view_robot.launch.py


Finally, if the battery was not critical or low then the robot navigates to
the next position in the loop. This position is tracked by the
‘position_index' variable


The remainder of the program is repeated in a loop.


__ Note


    navigator.undock()

    navigator.startFollowWaypoints(goal_pose)

    navigator.dock()


  * To run this example, first start the Gazebo simulation, specifying the ‘depot' world:

        ros2 launch turtlebot4_ignition_bringup turtlebot4_ignition.launch.py nav2:=true slam:=false localization:=true rviz:=true world:=depot map:=/opt/ros/humble/share/turtlebot4_navigation/maps/depot.yaml


![Pose Estimate](media/pose_estimate.gif) Setting the initial pose


    - nav2_time_expired_condition_bt_node
    - nav2_path_expiring_timer_condition
    - nav2_distance_traveled_condition_bt_node
    - nav2_single_trigger_bt_node
    - nav2_goal_updated_controller_bt_node
    - nav2_is_battery_low_condition_bt_node
    - nav2_navigate_through_poses_action_bt_node
    - nav2_navigate_to_pose_action_bt_node
    - nav2_remove_passed_goals_action_bt_node
    - nav2_planner_selector_bt_node
    - nav2_controller_selector_bt_node
    - nav2_goal_checker_selector_bt_node
    - nav2_controller_cancel_bt_node
    - nav2_path_longer_on_approach_bt_node
    - nav2_wait_cancel_bt_node
    - nav2_spin_cancel_bt_node
    - nav2_back_up_cancel_bt_node
    - nav2_assisted_teleop_cancel_bt_node
    - nav2_drive_on_heading_cancel_bt_node


The class contains a subscriber that listens on the ` battery_state ` topic
for the latest battery state published by the Create3® and calls the `
battery_state_callback ` function whenever new information has been published.


Your browser does not support the video tag.  Patrol Loop (9x speed)


        # Add custom context
        context = "destinations = {'wood crate': [0.0, 3.0, 0], 'steel barrels': [2.0, 2.0, 90], \
            'bathroom door': [-6.0, -6.0, 180] }"
        exec(context, globals())
        gpt.info("Entering input parsing loop with context:")
        gpt.info(context)
        gpt.full_prompt = gpt.full_prompt + '\n' + context

        # Main loop
        gpt.publish_status(True)
        try:
            rclpy.spin(gpt)
        except KeyboardInterrupt:
            pass

        gpt.destroy_node()
        navigator.destroy_node()

        rclpy.shutdown()


The lock is created as well as the battery monitor node being created. The
lock is passed into the battery monitor node to ensure that both processes are
using the same lock.


###  Code breakdown


      linear_granularity: 0.05
      angular_granularity: 0.025
      transform_tolerance: 0.2
      xy_goal_tolerance: 0.25
      trans_stopped_velocity: 0.25
      short_circuit_trajectory_evaluation: True
      stateful: True
      critics: ["RotateToGoal", "Oscillation", "BaseObstacle", "GoalAlign", "PathAlign", "PathDist", "GoalDist"]
      BaseObstacle.scale: 0.02
      PathAlign.scale: 32.0
      PathAlign.forward_point_distance: 0.1
      GoalAlign.scale: 24.0
      GoalAlign.forward_point_distance: 0.1
      PathDist.scale: 32.0
      GoalDist.scale: 24.0
      RotateToGoal.scale: 32.0
      RotateToGoal.slowing_factor: 5.0
      RotateToGoal.lookahead_time: -1.0


Your browser does not support the video tag.  Mail Delivery (3x speed)


Once the simulation has started, open another terminal and run:


ros2 topic echo /clicked_point


This tutorial will cover various methods of navigating with the TurtleBot 4
and Nav2.


At the top of the Rviz window is the toolbar. You will notice that there are
three navigation tools available to you.


     [ __ Source ](https://github.com/turtlebot/turtlebot4-user-manual "Stars: 3")
     [ __ Issues ](https://github.com/turtlebot/turtlebot4-user-manual/issues "Open issues: 2")
     [ __ Download ](https://github.com/turtlebot/turtlebot4-user-manual/zipball/gh-pages "Size: 250111 Kb")


This example demonstrates an integration between the OpenAI [ Chat Completions
API ](https://platform.openai.com/docs/guides/gpt/chat-completions-api) and
the Turtlebot 4, substantially inspired by the [ ‘Code as Policies: Language
Model Programs for Embodied Control' (Liang et al.)
](https://arxiv.org/abs/2209.07753) research.


  * galactic
  * humble


#####  Operating Loop


To run this example, start the Ignition simulation:


There are two localization methods we can use to figure out where the robot is
on the map: SLAM or Localization. SLAM allows us to generate the map as we
navigate, while localization requires that a map already exists.


* This tutorial is only available in Humble


Built with [ GitHub Pages ](https://pages.github.com "github-pages v209")
using a [ theme ](https://github.com/rundocs/jekyll-rtd-theme "rundocs/jekyll-
rtd-theme v2.0.10") provided by [ RunDocs ](https://rundocs.io) .


__ Note


        ]

        navigator.info('Welcome to the mail delivery service.')

        while True:
            # Create a list of the goals for display
            options_str = 'Please enter the number corresponding to the desired robot goal position:\n'
            for i in range(len(goal_options)):
                options_str += f'    {i}. {goal_options[i]["name"]}\n'

            # Prompt the user for the goal location
            raw_input = input(f'{options_str}Selection: ')

            selected_index = 0

            # Verify that the value input is a number
            try:
                selected_index = int(raw_input)
            except ValueError:
                navigator.error(f'Invalid goal selection: {raw_input}')
                continue

            # Verify that the user input is within a valid range
            if (selected_index < 0) or (selected_index >= len(goal_options)):
                navigator.error(f'Goal selection out of bounds: {selected_index}')

            # Check for exit
            elif goal_options[selected_index]['name'] == 'Exit':
                break

            else:
                # Navigate to requested position
                navigator.startToPose(goal_options[selected_index]['pose'])

        rclpy.shutdown()


Use the API key you created earlier in place of API_KEY, and set `
parking_brake:=true ` if you don't want the commands to be passed to the
robot.


        def thread_function(self):
        executor = SingleThreadedExecutor()
        executor.add_node(self)
        executor.spin()


* For this tutorial we can launch navigation with [ Nav Bringup ](https://github.com/turtlebot/turtlebot4/blob/galactic/turtlebot4_navigation/launch/nav_bringup.launch.py) .


##  Patrol Loop


ros2 launch turtlebot4_ignition_bringup turtlebot4_ignition.launch.py nav2:=true slam:=false localization:=true rviz:=true


  * [ 1\. Diagnostics ](/turtlebot4-user-manual/troubleshooting/diagnostics.html)
  * [ 2\. ROS 2 Tests ](/turtlebot4-user-manual/troubleshooting/ros2_tests.html)
  * [ 3\. FAQ ](/turtlebot4-user-manual/troubleshooting/faq.html)


Next we set the initial pose and clear all costmaps. We clear costmaps because
the 2D Pose Estimate tool is subscribed to by the Nav2 stack, and every time
we use it Nav2 assumes that the robot is in that position, when it is not.
Clearing the costmaps will get rid of any false costmaps that may have spawned
when creating the path.


[ Tutorials ](/turtlebot4-user-manual/tutorials/)


GitHub


ros2 topic echo /ready_for_input


Clearpath Robotics, by Rockwell Automation. All rights reserved. Revision [
d523bec ](https://github.com/turtlebot/turtlebot4-user-
manual/commit/d523beca255aff8f224fecd6f08075cf71673416
"d523beca255aff8f224fecd6f08075cf71673416")
__ Clearpath Robotics, Inc., a Rockwell Automation Company. All rights
reserved.


    navigator.undock()

    navigator.startThroughPoses(goal_pose)

    navigator.dock()


Running this example will look something like this:


    navigator.undock()

    navigator.startToPose(goal_pose)


__ TurtleBot 4 User Manual


We also wait for Nav2 to be active before continuing.


  * Now we can create a [ geometry_msgs/PoseStamped ](https://github.com/ros2/common_interfaces/blob/galactic/geometry_msgs/msg/PoseStamped.msg) message. The ` getPoseStamped ` method makes it easy for us. All we have to do is pass in a list describing the x and y position that we want to drive to on the map, and the direction that we want the robot to be facing when it reaches that point.

        goal_pose = navigator.getPoseStamped([13.0, 5.0], TurtleBot4Directions.EAST)


        lock = Lock()
    battery_monitor = BatteryMonitor(lock)


Remember to always source your ROS 2 environment before trying to launch a
node.


This example starts with many of the same steps as  navigate to pose  . We
initialise the node, make sure the robot is docked, and set the initial pose.
Then we wait for Nav2 to become active. The additional steps are discussed
below.


ros2 run turtlebot4_python_tutorials follow_waypoints


The following examples can be installed with ` sudo apt install
ros-$ROS_DISTRO-turtlebot4-tutorials ` and are available at [
https://github.com/turtlebot/turtlebot4_tutorials
](https://github.com/turtlebot/turtlebot4_tutorials) . For each example, the
robot starts on a dock at the origin of the map.


Once the simulation has started, open another terminal and run:


Once the initial position has been set, the Nav2 stack will place the robot at
that position on the map and begin localizing. We want to wait for Nav2 to be
ready before we start sending navigation goals.


##  SLAM vs Localization


Except where otherwise noted, content on this site is licensed under the Creative Commons Attribution 3.0


[ Overview ](/turtlebot4-user-manual/overview/)


This example demonstrates the same behaviour as [ Nav2 Goal
](/turtlebot4-user-manual/tutorials/navigation.html#nav2-goal) . The Nav2
stack is given a pose on the map with which it calculates a path. The robot
then attempts to drive along the path. This example is demonstrated in the `
depot ` world of the TurtleBot 4 simulation.


  * galactic
  * humble


Once the navigation system is initialized, additional custom context can be
added. In this case, since an object detection system is not included,
relationships between certain objects in the environment and their positions
have been added to the context.


This example is very similar to  Navigate Through Poses  . The difference is
that we are using different poses as our waypoints, and that we use the `
startFollowWaypoints ` method to perform our navigation behaviour.


The battery percentage is updated when it is granted access by the lock.


* The source code for this example is available [ here ](https://github.com/turtlebot/turtlebot4_tutorials/blob/galactic/turtlebot4_python_tutorials/turtlebot4_python_tutorials/nav_to_pose.py) .


  * ![Create Path](media/create_path_rviz.gif) Creating a path and following it
  * Your browser does not support the video tag.  Creating a path and following it


    goal_pose = navigator.createPath()

    if len(goal_pose) == 0:
        navigator.error('No poses were given, exiting.')
        exit(0)


ros2 run turtlebot4_python_tutorials mail_delivery


#  Navigation


For example, a prompt of ` # Navigate to shelf ` is tied to the series of
valid Python commands


Now we can undock the robot and begin navigating through each point. Once the
robot has reached the final pose, it will then return to the dock.


User Manual
The User Manual provides all the documentation for how to use the TurtleBot 4. In addition it documents how you can get started using the open source simulation without needing to buy a robot at all.


  rclcpp::shutdown();
  return 0;
}


These cardinal directions are relative to the map, not the actual magnetic
north pole. Driving north is equivalent to driving upwards on the map, west is
driving left, and so on.


        def main(args=None):
        rclpy.init(args=args)

        lock = Lock()
        battery_monitor = BatteryMonitor(lock)

        navigator = TurtleBot4Navigator()
        battery_percent = None
        position_index = 0

        thread = Thread(target=battery_monitor.thread_function, daemon=True)
        thread.start()

        # Start on dock
        if not navigator.getDockedStatus():
            navigator.info('Docking before initialising pose')
            navigator.dock()

        # Set initial pose
        initial_pose = navigator.getPoseStamped([0.0, 0.0], TurtleBot4Directions.NORTH)
        navigator.setInitialPose(initial_pose)

        # Wait for Nav2
        navigator.waitUntilNav2Active()

        # Undock
        navigator.undock()

        # Prepare goal poses
        goal_pose = []
        goal_pose.append(navigator.getPoseStamped([-5.0, 1.0], TurtleBot4Directions.EAST))
        goal_pose.append(navigator.getPoseStamped([-5.0, -23.0], TurtleBot4Directions.NORTH))
        goal_pose.append(navigator.getPoseStamped([9.0, -23.0], TurtleBot4Directions.NORTH_WEST))
        goal_pose.append(navigator.getPoseStamped([10.0, 2.0], TurtleBot4Directions.WEST))

        while True:
            with lock:
                battery_percent = battery_monitor.battery_percent


  * [ 1\. Driving your TurtleBot 4 ](/turtlebot4-user-manual/tutorials/driving.html)
  * [ 2\. Creating your first node (C++) ](/turtlebot4-user-manual/tutorials/first_node_cpp.html)
  * [ 3\. Creating your first node (Python) ](/turtlebot4-user-manual/tutorials/first_node_python.html)
  * [ 4\. Generating a map ](/turtlebot4-user-manual/tutorials/generate_map.html)
  * [ 5\. Navigation ](/turtlebot4-user-manual/tutorials/navigation.html)
  * [ 6\. TurtleBot 4 Navigator ](/turtlebot4-user-manual/tutorials/turtlebot4_navigator.html)
  * [ 7\. Multiple robots ](/turtlebot4-user-manual/tutorials/multiple_robots.html)


Open a terminal and launch [ localization
](https://github.com/turtlebot/turtlebot4/blob/humble/turtlebot4_navigation/launch/localization.launch.py)
:


Once the simulation has started, open another terminal and run:


Built with [ GitHub Pages ](https://pages.github.com "github-pages v209")
using a [ theme ](https://github.com/rundocs/jekyll-rtd-theme "rundocs/jekyll-
rtd-theme v2.0.10") provided by [ RunDocs ](https://rundocs.io) .


[ __ User Manual ](/turtlebot4-user-manual/ "Turtlebot4 User Manual")


        # Callbacks
    def battery_state_callback(self, batt_msg: BatteryState):
        with self.lock:
            self.battery_percent = batt_msg.percentage


####  Set initial pose and clear costmaps


smoother_server:
  ros__parameters:
    use_sim_time: True
    smoother_plugins: ["simple_smoother"]
    simple_smoother:
      plugin: "nav2_smoother::SimpleSmoother"
      tolerance: 1.0e-10
      max_its: 1000
      do_refinement: True


####  Check for exit


controller_server:
  ros__parameters:
    use_sim_time: True
    controller_frequency: 20.0
    min_x_velocity_threshold: 0.001
    min_y_velocity_threshold: 0.5
    min_theta_velocity_threshold: 0.001
    failure_tolerance: 0.3
    progress_checker_plugin: "progress_checker"
    goal_checker_plugins: ["general_goal_checker"] # "precise_goal_checker"
    controller_plugins: ["FollowPath"]


  * To run this example, start the Ignition Gazebo simulation:

        ros2 launch turtlebot4_ignition_bringup ignition.launch.py nav:=true slam:=off localization:=true


If the battery is at critical levels, it breaks the loop, ending the program.


On your PC you will need to start Rviz:


        elif (battery_percent < BATTERY_LOW):
        # Go near the dock
        navigator.info('Docking for charge')
        navigator.startToPose(navigator.getPoseStamped([-1.0, 1.0],
                                TurtleBot4Directions.EAST))
        navigator.dock()

        if not navigator.getDockedStatus():
            navigator.error('Robot failed to dock')
            break

        # Wait until charged
        navigator.info('Charging...')
        battery_percent_prev = 0
        while (battery_percent < BATTERY_HIGH):
            sleep(15)
            battery_percent_prev = floor(battery_percent*100)/100
            with lock:
                battery_percent = battery_monitor.battery_percent

            # Print charge level every time it increases a percent
            if battery_percent > (battery_percent_prev + 0.01):
                navigator.info(f'Battery is at {(battery_percent*100):.2f}% charge')

        # Undock
        navigator.undock()
        position_index = 0


**On a physical TurtleBot 4, call:**


**For a physical TurtleBot 4:**


        ros2 launch turtlebot4_ignition_bringup turtlebot4_ignition.launch.py nav2:=true slam:=false localization:=true \
    rviz:=true world:=classroom map:=path/to/classroom.yaml


    ros2 topic pub --once /user_input std_msgs/msg/String "data: Dock"
    ros2 topic pub --once /user_input std_msgs/msg/String "data: Go to -1,0, face East"
    ros2 topic pub --once /user_input std_msgs/msg/String "data: Go to 5,5"
    ros2 topic pub --once /user_input std_msgs/msg/String "data: Move to the wooden object"
    ros2 topic pub --once /user_input std_msgs/msg/String "data: Navigate to the item which can hold oil"
    ros2 topic pub --once /user_input std_msgs/msg/String "data: Travel to the room containing a toilet"


* The source code for this example is available [ here ](https://github.com/turtlebot/turtlebot4_tutorials/blob/humble/turtlebot4_python_tutorials/turtlebot4_python_tutorials/create_path.py) .


If you do not have a map of the environment, [ generate a map
](/turtlebot4-user-manual/tutorials/generate_map.html) first.


  * [ 1\. Overview ](/turtlebot4-user-manual/software/overview.html)
  * [ 2\. TurtleBot 4 Common ](/turtlebot4-user-manual/software/turtlebot4_common.html)
  * [ 3\. TurtleBot 4 Robot ](/turtlebot4-user-manual/software/turtlebot4_robot.html)
  * [ 4\. TurtleBot 4 Simulator ](/turtlebot4-user-manual/software/turtlebot4_simulator.html)
  * [ 5\. TurtleBot 4 Desktop ](/turtlebot4-user-manual/software/turtlebot4_desktop.html)
  * [ 6\. TurtleBot 4 Setup ](/turtlebot4-user-manual/software/turtlebot4_setup.html)
  * [ 7\. Create® 3 ](/turtlebot4-user-manual/software/create3.html)
  * [ 8\. Sensors ](/turtlebot4-user-manual/software/sensors.html)
  * [ 9\. Rviz2 ](/turtlebot4-user-manual/software/rviz.html)
  * [ 10\. Simulation ](/turtlebot4-user-manual/software/simulation.html)


        def main(args=None):
        rclpy.init(args=args)

        navigator = TurtleBot4Navigator()

        # Start on dock
        if not navigator.getDockedStatus():
            navigator.info('Docking before initialising pose')
            navigator.dock()

        # Set initial pose
        initial_pose = navigator.getPoseStamped([0.0, 0.0], TurtleBot4Directions.NORTH)
        navigator.setInitialPose(initial_pose)

        # Wait for Nav2
        navigator.waitUntilNav2Active()

        # Undock
        navigator.undock()

        # Prepare goal pose options
        goal_options = [
            {'name': 'Home',
             'pose': navigator.getPoseStamped([-1.0, 1.0], TurtleBot4Directions.EAST)},

            {'name': 'Position 1',
             'pose': navigator.getPoseStamped([10.0, 6.0], TurtleBot4Directions.EAST)},

            {'name': 'Position 2',
             'pose': navigator.getPoseStamped([-9.0, 9.0], TurtleBot4Directions.NORTH)},

            {'name': 'Position 3',
             'pose': navigator.getPoseStamped([-12.0, 2.0], TurtleBot4Directions.NORTH_WEST)},

            {'name': 'Position 4',
             'pose': navigator.getPoseStamped([3.0, -7.0], TurtleBot4Directions.WEST)},

            {'name': 'Exit',
             'pose': None}


####  Launchfile


  * galactic
  * humble


#####  System Setup


  * Now we can create a [ geometry_msgs/PoseStamped ](https://github.com/ros2/common_interfaces/blob/humble/geometry_msgs/msg/PoseStamped.msg) message. The ` getPoseStamped ` method makes it easy for us. All we have to do is pass in a list describing the x and y position that we want to drive to on the map, and the direction that we want the robot to be facing when it reaches that point.

        goal_pose = navigator.getPoseStamped([-13.0, 9.0], TurtleBot4Directions.EAST)


####  Navigate through the poses


Open a new terminal and call:


To run this example, start the Ignition simulation:


####  Follow the path


Due to the use of an LLM, the system is capable of inferring a significant
amount of relationships which are not present in the code itself. For example,
the words ‘oil' and ‘toilet' are not found in the code base at all, much less
how they relate to the API.


For this tutorial, we will be using localization to navigate on a map [
generated with SLAM ](/turtlebot4-user-
manual/tutorials/generate_map.html#generating-a-map) .


The next step is to create a list of ` PoseStamped ` messages which represent
all possible poses that the robot can be sent to.


####  Select the Goal Pose


* The source code for this example is available [ here ](https://github.com/turtlebot/turtlebot4_tutorials/blob/humble/turtlebot4_python_tutorials/turtlebot4_python_tutorials/mail_delivery.py) .


Stay Connected


        def main():
        rclpy.init()

        navigator = TurtleBot4Navigator()

        # Start on dock
        if not navigator.getDockedStatus():
            navigator.info('Docking before initialising pose')
            navigator.dock()

        # Set initial pose
        initial_pose = navigator.getPoseStamped([0.0, 0.0], TurtleBot4Directions.NORTH)
        navigator.setInitialPose(initial_pose)

        # Wait for Nav2
        navigator.waitUntilNav2Active()

        # Set goal poses
        goal_pose = navigator.getPoseStamped([13.0, 5.0], TurtleBot4Directions.EAST)

        # Undock
        navigator.undock()

        # Go to each goal pose
        navigator.startToPose(goal_pose)

        rclpy.shutdown()


  }
  bool is_goal_done() const
  {
    return this->goal_done_;
  }
  void send_goal()
  {
    using namespace std::placeholders;
    this->timer_->cancel();
    this->goal_done_ = false;
    if (!this->client_ptr_) {
      RCLCPP_ERROR(this->get_logger(), "Action client not initialized");
    }
    if (!this->client_ptr_->wait_for_action_server(std::chrono::seconds(10))) {
      RCLCPP_ERROR(this->get_logger(), "Action server not available after waiting");
      this->goal_done_ = true;
      return;
    }
    auto goal_msg = Fibonacci::Goal();
    goal_msg.order = 10;
    RCLCPP_INFO(this->get_logger(), "Sending goal");
    auto send_goal_options = rclcpp_action::Client<Fibonacci>::SendGoalOptions();
    send_goal_options.goal_response_callback =
      std::bind(&MinimalActionClient::goal_response_callback, this, _1);
    send_goal_options.feedback_callback =
      std::bind(&MinimalActionClient::feedback_callback, this, _1, _2);
    send_goal_options.result_callback =
      std::bind(&MinimalActionClient::result_callback, this, _1);
    auto goal_handle_future = this->client_ptr_->async_send_goal(goal_msg, send_goal_options);
  }
private:
  rclcpp_action::Client<Fibonacci>::SharedPtr client_ptr_;
  rclcpp::TimerBase::SharedPtr timer_;
  bool goal_done_;
  void goal_response_callback(GoalHandleFibonacci::SharedPtr goal_handle)
  {
    if (!goal_handle) {
      RCLCPP_ERROR(this->get_logger(), "Goal was rejected by server");
    } else {
      RCLCPP_INFO(this->get_logger(), "Goal accepted by server, waiting for result");


Now that we know the robot is docked, we can set the initial pose to [0.0,
0.0], facing "North".


* This example demonstrates how to follow waypoints. The Nav2 stack is given a set of waypoints on the map and creates a path that goes through each waypoint in order until the last waypoint is reached. The robot then attempts to drive along the path. The difference between this example and Navigating Through Poses is that when following waypoints the robot will plan to reach each waypoint individually, rather than planning to reach the last pose by driving through the other poses. This example is demonstrated in the ` depot ` world of the TurtleBot 4 simulation.


  * [ 1\. Basic Setup ](/turtlebot4-user-manual/setup/basic.html)
  * [ 2\. Networking ](/turtlebot4-user-manual/setup/networking.html)
  * [ 3\. Simple Discovery ](/turtlebot4-user-manual/setup/simple_discovery.html)
  * [ 4\. Discovery Server ](/turtlebot4-user-manual/setup/discovery_server.html)


For example:


Initially when the processes are not ready, the battery percent may be None.
The program continues to check until the battery percent is not None.


In order to listen for new messages and run callbacks, a node must be actively
spinning. To simultaneously spin the node and run the navigation code, multi-
threading is used. Here the battery node is prepared to spin in a separate
thread which is created in the main function (see below).


####  Nav2 Goal


####  Initialise the node


The main script [ here
](https://github.com/turtlebot/turtlebot4_tutorials/blob/humble/turtlebot4_openai_tutorials/turtlebot4_openai_tutorials/natural_language_nav.py)
is similar to previous examples.


ros2 launch turtlebot4_viz view_robot.launch.py


Before using this as the basis for a product, please consult the substantial
list of caveats found in the original paper!
![:smile:](https://github.githubassets.com/images/icons/emoji/unicode/1f604.png)


Finally, navigate to the selected position.


__ Note


* This example demonstrates how to create an infinite patrol loop with auto-charging. The robot will continuously drive through a set of poses until the charge is low and then it will go charge. Once the robot is sufficiently charged, it will start driving through the set of poses again. It uses the  Navigate to Pose  behaviour to navigate to the pose.


ros2 launch turtlebot4_openai_tutorials natural_language_nav_launch.py openai_api_key:=API_KEY parking_brake:=false


####  Prepare Goal Poses


#####  Constructor


  * [ 1\. TurtleBot 4 Galactic ](/turtlebot4-user-manual/changelogs/galactic.html)
  * [ 2\. TurtleBot 4 Humble ](/turtlebot4-user-manual/changelogs/humble.html)


ros2 launch turtlebot4_ignition_bringup turtlebot4_ignition.launch.py nav2:=true slam:=false localization:=true rviz:=true


This example begins the same as the others by initialising the TurtleBot 4
Navigator.


We start by initialising ` rclpy ` and creating the ` TurtleBot4Navigator `
object. This will initialise any ROS 2 publishers, subscribers and action
clients that we need.


* The source code for this example is available [ here ](https://github.com/turtlebot/turtlebot4_tutorials/blob/humble/turtlebot4_python_tutorials/turtlebot4_python_tutorials/nav_through_poses.py) .


This is a straightforward launchfile, used to create three key parameters.


ros2 run turtlebot4_python_tutorials nav_to_pose


[ Overview ](/turtlebot4-user-manual/overview/)


ros2 topic pub --once /user_input std_msgs/msg/String "data: STRING"


ros2 launch turtlebot4_ignition_bringup ignition.launch.py nav2:=true slam:=off localization:=true world:=classroom map:=path/to/classroom.yaml


We are ready to drive to the goal pose. We start by undocking the robot so
that it does not attempt to drive through the dock, and then send the goal
pose. As the robot drives to the goal pose, we will be receiving feedback from
the action. This feedback includes the estimated time of arrival.


ros2 run turtlebot4_python_tutorials follow_waypoints


  * To run this example, first start the Gazebo simulation:

        ros2 launch turtlebot4_ignition_bringup ignition.launch.py nav2:=true slam:=false localization:=true rviz:=true


To run this example, start the Ignition Gazebo simulation:


    }
  }
  void feedback_callback(
    GoalHandleFibonacci::SharedPtr,
    const std::shared_ptr<const Fibonacci::Feedback> feedback)
  {
    RCLCPP_INFO(
      this->get_logger(),
      "Next number in sequence received: %" PRId32,
      feedback->sequence.back());
  }
  void result_callback(const GoalHandleFibonacci::WrappedResult & result)
  {
    this->goal_done_ = true;
    switch (result.code) {
      case rclcpp_action::ResultCode::SUCCEEDED:
        break;
      case rclcpp_action::ResultCode::ABORTED:
        RCLCPP_ERROR(this->get_logger(), "Goal was aborted");
        return;
      case rclcpp_action::ResultCode::CANCELED:
        RCLCPP_ERROR(this->get_logger(), "Goal was canceled");
        return;
      default:
        RCLCPP_ERROR(this->get_logger(), "Unknown result code");
        return;
    }
    RCLCPP_INFO(this->get_logger(), "Result received");
    for (auto number : result.result->sequence) {
      RCLCPP_INFO(this->get_logger(), "%" PRId32, number);
    }
  }
};  // class MinimalActionClient
int main(int argc, char ** argv)
{
  rclcpp::init(argc, argv);
  auto action_client = std::make_shared<MinimalActionClient>();
  while (!action_client->is_goal_done()) {
    rclcpp::spin_some(action_client);
  }


Then, select the Publish Point tool and click on a point on the map. You
should see the coordinates published in your terminal.


* This example demonstrates how to follow waypoints. The Nav2 stack is given a set of waypoints on the map and creates a path that goes through each waypoint in order until the last waypoint is reached. The robot then attempts to drive along the path. The difference between this example and Navigating Through Poses is that when following waypoints the robot will plan to reach each waypoint individually, rather than planning to reach the last pose by driving through the other poses. This example is demonstrated in the ` depot ` world of the TurtleBot 4 simulation.


__ Note


[ Mechanical ](/turtlebot4-user-manual/mechanical/)


Let's take a look at the main function.


This example demonstrates how to create a navigation path in Rviz during
runtime. It uses the [ 2D Pose Estimate ](/turtlebot4-user-
manual/tutorials/navigation.html#2d-pose-estimate) tool to pass the TurtleBot
4 Navigator a set of poses. Then we use the  Follow Waypoints  behaviour to
follow those poses. This example was run on a physical TurtleBot 4.


If the battery is low then it navigates near the charger, docks and then waits
for full charge. While charging it continues to periodically use the lock to
update the battery percentage. Once full, it undocks and prepares to start the
patrol loop again from the first position.


If you are using a custom world you will need to build the [
turtlebot4_simulator package ](/turtlebot4-user-
manual/software/turtlebot4_simulator.html#source-installation) from source and
place your world file [ alongside the others
](https://github.com/turtlebot/turtlebot4_simulator/tree/humble/turtlebot4_ignition_bringup/worlds)
. You will then need to create a map for it and pass both the world name and
the map file path in as launch arguments.


###  Code breakdown


  * [ 1\. Create® 3 ](/turtlebot4-user-manual/electrical/create3.html)
  * [ 2\. Raspberry Pi 4B ](/turtlebot4-user-manual/electrical/rpi4.html)
  * [ 3\. User Interface PCBA ](/turtlebot4-user-manual/electrical/pcba.html)
  * [ 4\. Power Budget ](/turtlebot4-user-manual/electrical/power_budget.html)


ros2 launch turtlebot4_viz view_robot.launch.py


####  Main Function


        else:
        # Navigate to next position
        navigator.startToPose(goal_pose[position_index])

        position_index = position_index + 1
        if position_index >= len(goal_pose):
            position_index = 0


local_costmap:
  local_costmap:
    ros__parameters:
      update_frequency: 5.0
      publish_frequency: 2.0
      global_frame: odom
      robot_base_frame: base_link
      use_sim_time: True
      rolling_window: true
      width: 3
      height: 3
      resolution: 0.06
      robot_radius: 0.175
      plugins: ["static_layer", "voxel_layer", "inflation_layer"]
      inflation_layer:
        plugin: "nav2_costmap_2d::InflationLayer"
        cost_scaling_factor: 4.0
        inflation_radius: 0.45
      voxel_layer:
        plugin: "nav2_costmap_2d::VoxelLayer"
        enabled: True
        publish_voxel_map: True
        origin_z: 0.0
        z_resolution: 0.05
        z_voxels: 16
        max_obstacle_height: 2.0
        mark_threshold: 0
        observation_sources: scan
        scan:
          topic: scan
          max_obstacle_height: 2.0
          clearing: True
          marking: True
          data_type: "LaserScan"
          raytrace_max_range: 3.0
          raytrace_min_range: 0.0
          obstacle_max_range: 2.5
          obstacle_min_range: 0.0
      static_layer:
        plugin: "nav2_costmap_2d::StaticLayer"


// Copyright 2019 Open Source Robotics Foundation, Inc.
//
// 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.
#include <chrono>
#include <cinttypes>
#include <functional>
#include <future>
#include <memory>
#include <string>
#include "example_interfaces/action/fibonacci.hpp"
#include "rclcpp/rclcpp.hpp"
// TODO(jacobperron): Remove this once it is included as part of 'rclcpp.hpp'
#include "rclcpp_action/rclcpp_action.hpp"
class MinimalActionClient : public rclcpp::Node
{
public:
  using Fibonacci = example_interfaces::action::Fibonacci;
  using GoalHandleFibonacci = rclcpp_action::ClientGoalHandle<Fibonacci>;
  explicit MinimalActionClient(const rclcpp::NodeOptions & node_options = rclcpp::NodeOptions())
  : Node("minimal_action_client", node_options), goal_done_(false)
  {
    this->client_ptr_ = rclcpp_action::create_client<Fibonacci>(
      this->get_node_base_interface(),
      this->get_node_graph_interface(),
      this->get_node_logging_interface(),
      this->get_node_waitables_interface(),
      "fibonacci");
    this->timer_ = this->create_wall_timer(
      std::chrono::milliseconds(500),
      std::bind(&MinimalActionClient::send_goal, this));


Localization uses an existing map along with live odometry and laserscan data
to figure out the position of the robot on the given map. It does not update
the map if any changes have been made to the environment, but we can still
avoid new obstacles when navigating. Because the map doesn't change, we can
get more repeatable navigation results.


[ ](https://clearpathrobotics.com/) [ ](https://www.openrobotics.org/) [
](https://docs.ros.org/en/humble/index.html) [
](https://github.com/turtlebot/TurtleBot4Lessons) [
](https://github.com/turtlebot) [
](https://clearpathrobotics.com/turtlebot-4/)


To run this example, start [ Navigation ](/turtlebot4-user-
manual/tutorials/navigation.html#launching-navigation) on your PC or on the
Raspberry Pi using a map of your environment.


#####  Battery State Callback


  * [ 1\. Diagnostics ](/turtlebot4-user-manual/troubleshooting/diagnostics.html)
  * [ 2\. ROS 2 Tests ](/turtlebot4-user-manual/troubleshooting/ros2_tests.html)
  * [ 3\. FAQ ](/turtlebot4-user-manual/troubleshooting/faq.html)


  * [ 1\. Features ](/turtlebot4-user-manual/overview/features.html)
  * [ 2\. Resources ](/turtlebot4-user-manual/overview/resources.html)


##  Navigate Through Poses


###  Installation