ROS2 PYTHON Script Pamoja Na Mchapishaji na Majiri – Swahili ROS Tutorial

ROS2 PYTHON Script Pamoja Na Mchapishaji na Majiri – Swahili ROS Tutorial

This tutorial is created by Rosbotics Ambassador 021 Kevin

Rosbotics Ambassador Program https://www.theconstruct.ai/rosbotics-ambassador/)


Mambo tunaenda kujifunza

  1. Jinsi ya kutengeneza rosject
  2. Jinsi ya kutengeneza kifurushi ya ROS2.
  3. Jinsi ya kuunda hati ya python..
  4. Jinsi ya kutengeneza mchapishaji.
  5. Jinsi ya kutengeneza mteja.
  6. Jinsi ya kujenga nafasi ya kazi ya ROS2..

Orodha ya rasilimali zilizotumiwa katika chapisho hili

  1. The Construct: https://app.theconstructsim.com/
  2. ROS2 Courses –▸
    1. ROS2 Basics in 5 Days Humble (Python): https://app.theconstructsim.com/Course/132

Muhtasari.

ROS (Mfumo wa Uendeshaji wa Roboti) unakuwa “mfumo” wa kawaida wa roboti za kutengeneza programu. Katika chapisho hili, hebu tujifunze jinsi ya kuunda kifurushi cha ROS2, muhimu kwa kutoa maagizo kwa roboti, kwa kutumia amri ya ros2.

Kutengeneza rosject

Ili kufuata mafunzo haya, tunahitaji kuwa na ROS2 iliyosakinishwa katika mfumo wetu, na kwa hakika ros2_ws (ROS2 Workspace). Ili kurahisisha maisha yako, tutaunda mpango wa kubofya kiungo hiki: https://app.theconstructsim.com/ 

Hii inakuleta kwenye ukurasa wa kutua wa kuunda, hapo tutaenda kwa myrosjects na kisha kuunda rosject mpya, hatua zimeangaziwa katika miraba ya bluu.

 

Baada ya kuunda rosject mpya, weka usambazaji ambao ungependa kutumia kwa kesi yetu Humble na jina la rosject na maelezo mafupi.

 

Baada ya kubonyeza kitufe cha Unda, unapaswa kuwa na rosject kwenye rosjects zangu Bonyeza na ubonyeze RUN.

 

Kuunda kifurushi cha ros2.

Ili kuunda kifurushi cha ROS2, tunahitaji kuwa na Nafasi ya Kazi ya ROS2, na kwa hiyo, tunahitaji terminal.

Wacha tufungue terminal kwa kubofya kitufe cha Fungua terminal mpya.

Mara tu ndani ya terminal tumia amri kuona vitu vilivyopo kwenye saraka ya sasa:

ls

Kisha nenda kwenye saraka ifuatayo ambapo tutaunda kifurushi:

cd ros2_ws/src

Tumia amri ifuatayo kuunda kifurushi cha python:
ros2 pkg create --build-type ament_python --license Apache-2.0 py_pubsub

Pamoja na hayo umeunda kifurushi cha python ROS2.

 

 

Kuunda hati ya python.

Fungua kihariri cha msimbo kulia na uunde hati kwenye py_pubsub fille inayoitwa py_pubsub.py. Hii inafanywa kwa kubofya kulia kwenye py_pubsub na kubofya kuunda faili mpya

 

Nakili na ubandike yafuatayo na hati ya python ambayo ina mchapishaji na aliyejiandikisha kwenye hati yetu

import rclpy

import math
from rclpy.node import Node
from std_msgs.msg import Float32

class MyNode(Node):
    def __init__(self):
        super().__init__(‘my_node’)
        self.subscription = self.create_subscription(Float32, ‘input_topic’, self.listener_callback, 10)
        self.publisher = self.create_publisher(Float32, ‘output_topic’, 10)

    def listener_callback(self, msg):
        radians = msg.data
        degrees = radians * 180 / math.pi
        self.publisher.publish(Float32(data=degrees))

def main(args=None):
    rclpy.init(args=args)
    node = MyNode()
    rclpy.spin(node)
    node.destroy_node()
    rclpy.shutdown()

if __name__ == ‘__main__’:
    main()

 

Kisha ongeza laini ifuatayo kwenye setup.py kwenye sehemu ya kuingilia.

‘talker = py_pubsub.py_pubsub:main’
Faili ya stepup.py inapaswa kuonekana kama ifuatavyo:

 

from setuptools import setup

package_name = ‘py_pubsub’

setup(
    name=package_name,
    version=’0.0.0′,
    packages=[package_name],
    data_files=[
        (‘share/ament_index/resource_index/packages’,
            [‘resource/’ + package_name]),
        (‘share/’ + package_name, [‘package.xml’]),
    ],
    install_requires=[‘setuptools’],
    zip_safe=True,
    maintainer=’user’,
    maintainer_email=’user@todo.todo’,
    description=’TODO: Package description’,
    license=’Apache-2.0′,
    tests_require=[‘pytest’],
    entry_points={
        ‘console_scripts’: [
        ‘talker = py_pubsub.pypubsub:main’,
        ],
    },
)

 

Kuunda hati ya pili ya python

Hati hii mpya tunayopaswa kuunda itatumika kujaribu ya awali ili kuhakikisha kwamba mchapishaji na anayejisajili wanaendesha vyema.

Unda faili mpya kama hapo awali iliitwa test.py

Nakili na ubandike msimbo ufuatao

import rclpy
from rclpy.node import Node
import math

from std_msgs.msg import Float32


class MinimalPublisher(Node):

    def __init__(self):
        super().__init__(‘minimal_publisher’)
        self.publisher_ = self.create_publisher(Float32, ‘input_topic’, 10)
        timer_period = 0.5  # seconds
        self.timer = self.create_timer(timer_period, self.timer_callback)
        self.i = 0.0

    def timer_callback(self):
        msg = Float32()
        msg.data =  self.i
        self.publisher_.publish(msg)
        self.get_logger().info(‘Publishing: “%s”‘ % msg.data)
        if(self.i > math.pi):
            self.i = 0
        self.i += 0.01


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

    minimal_publisher = MinimalPublisher()

    rclpy.spin(minimal_publisher)

    # Destroy the node explicitly
    # (optional – otherwise it will be done automatically
    # when the garbage collector destroys the node object)
    minimal_publisher.destroy_node()
    rclpy.shutdown()


if __name__ == ‘__main__’:
    main()

Hati hii hutumia kipima muda baada ya kila sekunde 0.5 ili kuchapisha ujumbe kwa digrii kwenye mada inayoitwa input_topic.

Ongeza amri ifuatayo kwa setup.py yako

‘test =  py_pubsub.test:main’,

 

Faili yako ya setup.py sasa inapaswa kuonekana kama hii

from setuptools import setup

package_name = ‘py_pubsub’

setup(
    name=package_name,
    version=’0.0.0′,
    packages=[package_name],
    data_files=[
        (‘share/ament_index/resource_index/packages’,
            [‘resource/’ + package_name]),
        (‘share/’ + package_name, [‘package.xml’]),
    ],
    install_requires=[‘setuptools’],
    zip_safe=True,
    maintainer=’user’,
    maintainer_email=’user@todo.todo’,
    description=’TODO: Package description’,
    license=’Apache-2.0′,
    tests_require=[‘pytest’],
    entry_points={
        ‘console_scripts’: [
        ‘talker = py_pubsub.py_pubsub:main’
        ‘test =  py_pubsub.test:main’,
        ],
    },
)

 

Ongeza mabadiliko yafuatayo kwenye package.xml yako

 

  <exec_depend>rclpy</exec_depend>
  <exec_depend>std_msgs</exec_depend>

 

Sasa kifurushi chako.xml kinapaswa kuwa kama ifuatavyo

<?xml version=“1.0”?>
<?xml-model href=“http://download.ros.org/schema/package_format3.xsd” schematypens=“http://www.w3.org/2001/XMLSchema”?>
<package format=“3”>
  <name>py_pubsub</name>
  <version>0.0.0</version>
  <description>TODO: Package description</description>
  <maintainer email=“user@todo.todo”>user</maintainer>
  <license>Apache-2.0</license>

  <test_depend>ament_copyright</test_depend>
  <test_depend>ament_flake8</test_depend>
  <test_depend>ament_pep257</test_depend>
  <test_depend>python3-pytest</test_depend>
  <exec_depend>rclpy</exec_depend>
  <exec_depend>std_msgs</exec_depend>

  <export>
    <build_type>ament_python</build_type>
  </export>
</package>

 

Kuunda vifurushi vyetu vya ros2

Ingiza amri ifuatayo kwenye terminal

cd
cd ros2_ws


Ingiza amri zifuatazo

colcon build
source install/setup.bash

Kujaribu nodi mbili

Katika terminal ya kwanza kukimbia

ros2 run py_pubsub talker

 

 

Katika terminal ya pili endesha amri zifuatazo

cd ros2_ws
source install/setup.bash
ros2 run py_pubsub test


Unaweza basi katika kukimbia kwa terminal ya tatu 

ros2 topic list
ros2 topic echo /output_topic


Pamoja na hayo, tumethibitisha kwamba nodi mbili zinafanya kazi, Hapa kuna kiunga cha rosject https://app.theconstructsim.com/Desktop 

 

 

Kozi & Mafunzo Husika

Ikiwa unataka kujifunza zaidi kuhusu ROS na ROS2, tunapendekeza kozi zifuatazo:

Video Tutorial

Como crear publicador y suscriptor para turtlebot 3 – Spanish ROS Tutorial

Como crear publicador y suscriptor para turtlebot 3 – Spanish ROS Tutorial

This tutorial is created by Rosbotics Ambassador 025 Miguel

Rosbotics Ambassador Program https://www.theconstruct.ai/rosbotics-ambassador/)

Que vamos a aprender:

  1. Como crear un paquete en ROS 1
  2. Como escribir un publicador para el robot Turtlebot 3
  3. Como escribir un suscriptor en el mismo código

Lista de recursos usados en este post

  1. Usa este rosject: https://app.theconstructsim.com/l/5e643001/
  2. The construct: https://app.theconstructsim.com
  3. Cursos de ROS 1:
  1. Fundamentos de ROS en 5 días (Python): https://app.theconstructsim.com/courses/55
  2. Navegación ROS en 5 días: https://app.theconstructsim.com/courses/57

Descripción

Turtlebot 3 es uno de los robots compatibles con ros mas usados hoy en día en universidades y por personas del común para aprender el funcionamiento de ROS y el stack de Navegación. En este post, vamos a aprender como crear un nodo de ROS1, el cual nos va a permitir crear un teleop casero para entender como crear un suscriptor y publicador en el mismo código.

Abriendo el rosject

Para poder seguir al pie de la letra este tutorial, necesitamos tener ROS 1 Noetic instalado en nuestro sistema, e idealmente un workspace para crear los paquetes en él. Para facilitarnos el proceso, ya hemos preparado un rosject para esto: https://app.theconstructsim.com/l/5e643001/

Solo copiando el rosject (Abriendo el enlace anterior), tendremos un entorno previamente configurado.

Después de que el rosject se haya copiado correctamente en tu entorno, debemos presionar el botón Ejecuta para ejecutar e inicializar el entorno del rosject.

Crear un paquete de ROS 1 con geometry_msgs

Para poder crear nuestro paquete de ROS 1, necesitamos situarnos en el workspace, y para eso, necesitamos la terminal.

Abramos una terminal oprimiendo el botón de abrir una nueva terminal:

Una vez dentro de la terminal vamos a movernos al catkin/src y creamos nuestro paquete:
cd ~/catkin_ws/src
catkin_create_pkg turtlebot_publisher_subscriber geometry_msgs

Una vez creado nuestro paquete ingresamos a él y por convención creamos la carpeta scripts:
cd turtlebot_publisher_suscriber
mkdir scripts

Ahora vamos a abrir el editor de código para crear nuestro nodo. Para abrir el editor de código oprimimos el botón de editor de código:

 

Nos situamos en catkin_es/src/turtlebot_publisher_susbriber/scripts y oprimimos clic derecho New File y le damos el nombre de turtlebot.py para crear nuestro código


Primero vamos a importar las librerías, inicializar nuestro nodo, y crear el listener con su respectivo callback:

Para entenderlo mejor vamos a desglosar el código:

El primer rectángulo nos permite observar que estamos usando el entorno de Python 3, e importamos la librería de rospy para crear los nodos y geometry_msgs.msg Twist que es el tipo de dato Twist ya que este es el que usa /cmd_vel para comunicarse.

En el segundo rectángulo estamos creando un mensaje de tipo Twist, creamos la función listener la cual se suscribe de manera anónima a al tópico cmd_vel que usa como tipo de dato Twist, y por último cuando recibe un mensaje hace un llamado al callback que usando un loginfo imprime en pantalla el contenido del mensaje, este mensaje es la velocidad angular y lineal del turtlebot 3.

Por último en el tercer rectángulo inicializamos el nodo llamado publisher_suscriber e informamos por terminal que el nodo se inicializó correctamente.

Ahora vamos a crear el nodo publicador:

Como podemos observar creamos la función talker que recibe un mensaje como parámetro, ahora nos suscribimos al tópico /cmd_vel y publicamos el mensaje

Ahora vamos a crear una función que use el teclado para mover al turtlebot:

 

Lo que hace la función keyInput, esta nos pide ingresar una tecla, si se oprime w cambiamos el valor lineal de x para mover el robot hacia adelante, si se oprime s cambia el valor lineal a negativo para moverse hacia atrás, si se oprime a cambia el valor angular de z para girar hacia la izquierda y d gira hacia la derecha. 

Por último, vamos a hacer llamados continuos a estas funciones añadiendo un ciclo while al código inicial:

 

Acá lo que hacemos es crear un ciclo while para que esté constantemente solicitando una tecla, imprimiendo la velocidad del turtlebot 3, y cambiando la velocidad del turtlebot.

Para probar el código vamos a movernos a nuestro workspace, y compilamos el entorno:
cd ~/catkin_ws
catkin_make
source ~/catkin_ws/devel/setup.bash

Y si no tuvimos ningún error podemos correr el código y revisar si funciona

 

Video Tutorial

 

 

 

 

Como efetivamente combinar publisher e subscriber no mesmo arquivo Python em ROS – Portuguese ROS Tutorial

Como efetivamente combinar publisher e subscriber no mesmo arquivo Python em ROS – Portuguese ROS Tutorial

This tutorial is created by Rosbotics Ambassador 014 Anderson 

Rosbotics Ambassador Program https://www.theconstruct.ai/rosbotics-ambassador/)

O que nós vamos aprender:

  1. Como utilizar a plataforma ROS Development Studio e um rosject público
  2. Como lançar uma simulação já preparada com o robô Turtlebot3
  3. Como identificar tópicos, tipos e mensagens importantes
  4. Como estruturar um arquivo Python que combina publisher e subscriber

Lista de recursos usados neste post:

  1. Use este rosject: https://app.theconstructsim.com/l/5e54e304/
  2. The Construct: https://app.theconstructsim.com/
  3. ROS Courses: ROS Basics in 5 Days (Python) https://app.theconstructsim.com/Course/55

Panorama
Uma dúvida recorrente de desenvolvedores ROS iniciantes é como combinar publisher e subscriber no mesmo arquivo. Neste exemplo, vamos utilizar um dos robôs mais famosos, TurtleBot3, para fazer uma demonstração virtual.

Abrindo o rosject
Para seguir este tutorial, será útil e conveniente usar um rosject (que a grosso modo é um projeto ROS configurado para rodar um exemplo).
Acesse o link:
https://app.theconstructsim.com/l/5e2b6017
Clique no botão vermelho “RUN”:

Lançando a simulação exemplo:
Abra um terminal clicando no ícone indicado na figura:

Na janela do primeiro terminal, insira o comando:

roslaunch realrobotlab main.launch

Você será apresentado à uma janela do Gazebo como esta:

Você pode sempre revisitar a janela do Gazebo clicando em “Open Gazebo”:

Nesta janela, você tem a visualização da sua simulação com o TurtleBot3 presente.

Identificando os tópicos importantes:
Num segundo terminal (clique no botao “+” para criar abas diferentes), insira o comando:

rostopic list

Você verá algo como isto:

user:~$ rostopic list/clock
/cmd_vel/cv_camera/camera_info
/cv_camera/image_raw
/cv_camera/image_raw/compressed
/cv_camera/image_raw/compressed/parameter_descriptions
/cv_camera/image_raw/compressed/parameter_updates
/cv_camera/image_raw/compressedDepth
/cv_camera/image_raw/compressedDepth/parameter_descriptions
/cv_camera/image_raw/compressedDepth/parameter_updates
/cv_camera/image_raw/theora
/cv_camera/image_raw/theora/parameter_descriptions
/cv_camera/image_raw/theora/parameter_updates
/cv_camera/parameter_descriptions
/cv_camera/parameter_updates
/gazebo/link_states
/gazebo/model_states
/gazebo/parameter_descriptions
/gazebo/parameter_updates
/gazebo/performance_metrics
/gazebo/set_link_state
/gazebo/set_model_state
/imu
/joint_states
/odom
/overlord/camera/camera_info
/overlord/camera/image_raw
/overlord/camera/image_raw/compressed
/overlord/camera/image_raw/compressed/parameter_descriptions
/overlord/camera/image_raw/compressed/parameter_updates
/overlord/camera/image_raw/compressedDepth
/overlord/camera/image_raw/compressedDepth/parameter_descriptions
/overlord/camera/image_raw/compressedDepth/parameter_updates
/overlord/camera/image_raw/theora
/overlord/camera/image_raw/theora/parameter_descriptions
/overlord/camera/image_raw/theora/parameter_updates
/overlord/camera/parameter_descriptions
/overlord/camera/parameter_updates
/rosout
/rosout_agg
/scan
/tf
/tf_static

Esta é a listagem de todos os tópicos da simulação. Serão de especial importância para nós o tópico /scan, pois queremos ler o scanner do robô e o tópico /cmd_vel, pois queremos alterar a velocidade do robô.
No mesmo terminal, rode o comando:

rostopic type /scan

que apresentará:

sensor_msgs/LaserScan

esta informação é importante para compor o arquivo Python.
Abra a janela da IDE clicando no ícone indicado na figura:

Você pode encontrar o arquivo move_file.py na correta estrutura de pastas. Tome um minuto para entender onde o arquivo deve ser criado dentro do seu workspace para uma melhor organização geral.
A informação obtida anteriormente com respeito ao tópico /scan é utilizada em:

from sensor_msgs.msg import LaserScan

e

sub = rospy.Subscriber('/scan', LaserScan, callback)

Importante: aqui, você é capaz de diferenciar onde deve entrar com o nome do tópico e seu tipo no método subscriber.
Agora, tendo em mente o nosso publisher, o mesmo procedimento deve ser empregado. Rode o comando:

rostopic type /cmd_vel

que produzirá:

geometry_msgs/Twist

esta informação é utilizada em:

from geometry_msgs.msg import Twist

e

pub = rospy.Publisher('/cmd_vel', Twist)

A variável que nós criamos, chamada “move”, também deve ser do tipo “Twist”. Por isso temos:

move = Twist()

A função “callback” é chamada pelo subscriber e toda vez que isso acontece um determinado feixe do scanner será lido. Qual deles? Bem, isso depende do que você selecionar. Vejamos exemplos:
Rode o comando:

rosmsg show sensor_msgs/LaserScan

Reparou no uso do tipo descoberto anteriormente aqui também?
Você deve ver:

std_msgs/Header header
uint32 seq
time stamp
string frame_id
float32 angle_min
float32 angle_max
float32 angle_increment
float32 time_increment
float32 scan_time
float32 range_min
float32 range_max
float32[] ranges
float32[] intensities

De fato, os valores que queremos ler estão em “ranges”. Para ter exemplos de leitura do scanner, você pode rodar:

rostopic echo /scan

Não se assuste com esse comando, sua tela ficará cheia de dados provenientes do scanner. Com o comando Ctrl+C você para de printar esses dados na tela. Então, pode verificar o que nos interessa, ou seja, as informacoes contidas em “ranges”. Cada posição desse array corresponde a um feixe do scanner (por exemplo, o 360 está na frente do robô).
Raciocínio semelhante pode ser aplicado ao publisher. Rode o comando:

rosmsg show geometry_msgs/Twist

Para obter:

geometry_msgs/Vector3 linear
float64 x
float64 y
float64 z
geometry_msgs/Vector3 angular
float64 x
float64 y
float64 z

Baseando-se nesses valores, nós sabemos onde ler e onde escrever as informações.

Aplicando uma lógica simples de movimentação
Vamos imaginar que se o robô detecta um obstáculo à sua frente ele muda a direção. Caso contrário, continua em linha reta. Isso é feito muito facilmente lendo o valor do feixe de interesse e alterando as velocidades linear e angular do robô. Assim, o arquivo Python deve conter em sua função callback:

if msg.ranges[360] < 0.5:
move.linear.x = 0.05
move.angular.z = 0.4
else:
move.linear.x = 0.1
move.angular.z = 0.0

Imaginando que esse é seu primeiro pacote, navegue até o diretório do seu worspace:

roscd
cd..

Compile:

catkin_make
source devel/setup.bash

Para facilitar sua vida, já existe um arquivo de launch preparado neste rosject que você pode rodar inserindo:

roslaunch basic_project move_launcher.launch

Na janela do Gazebo, você deve ver o robô se comportando como esperado. Nada nos dá mais satisfação do que ver o robô fazendo o que deveria fazer.
Nós esperamos que este post seja útil para você!

Vídeo no YouTube
Este foi o post de hoje. Lembre-se que nós temos uma versão deste post em vídeo no YouTube.

Se você gostou do conteúdo, por favor, considere se inscrever no nosso canal do YouTube. Estamos publicando novos conteúdos quase todos os dias.

Continue avançando no seu aprendizado de ROS.

How to use C++ and Python in the same ROS 2 package –  English ROS 2 Tutorial

How to use C++ and Python in the same ROS 2 package – English ROS 2 Tutorial

What we are going to learn:

  1. How to set up the package architecture to accommodate C++ and Python in the same package
  2. How to configure this package (by modifying package.xml and CMakeLists.txt)
  3. How to compile and run Python and C++ nodes from this package

If you want to learn ROS 2 Python in a practical, hands-on way, check out the course
ROS 2 Basics in 5 Days: https://app.theconstruct.ai/courses/132

In this course, you’ll cover the foundational concepts needed to start working with ROS 2, as well as more advanced topics, all while engaging in hands-on practice.

Opening the rosject

In order to follow this tutorial, we need to have ROS2 installed in our system, and ideally a ros2_ws (ROS2 Workspace). To make your life easier, we have already prepared a rosject for that: https://app.theconstructsim.com/l/5e01d324/

Just by copying the rosject (clicking the link above), you will have a setup already prepared for you.

After the rosject has been successfully copied to your own area, you should see a Run button. Just click that button to launch the rosject ( see this example).

After pressing the Run button, you should have the rosject loaded. Now, let’s head to the next section to get some real practice.

In order to interact with ROS2, we need a terminal.

Let’s open a terminal by clicking the Open a new terminal button.

Open a new Terminal

 

Setup the package architecture

Create a standard C++ package


With dependencies on rclpy and rclcpp:

With dependencies on rclpy:

cd ~/ros2_ws/src/
ros2 pkg create cpp_py_pkg –build-type ament_cmake –dependencies rclpy rclcpp

Run the “tree . command to see the folder structure. If you don’t have the command installed, you can install it using:

sudo apt-get update
sudo apt-get install -y tree

You should be able to see this structure which you are already familiar with:

cpp_py_pkg/
├── CMakeLists.txt
├── include
│ └── cpp_py_pkg
├── package.xml
└── src

Add a C++ node and header

cd cpp_py_pkg/
touch src/cpp_node.cpp
touch include/cpp_py_pkg/cpp_header.hpp

In order to compile the package later, we need at least a main function in the C++ node. For this tutorial for simplicity, we can just add this minimal code to the cpp_node.cpp file:

#include “rclcpp/rclcpp.hpp”
// Include your header file to use it
#include “cpp_py_pkg/cpp_header.hpp”
int main(int argc, char **argv)
{
// Initiate ROS communications
    rclcpp::init(argc, argv);
// Instantiate the node
    auto node = std::make_shared<rclcpp::Node>(“my_node_name”);
// Make the node spin
    rclcpp::spin(node);
// Shutdown ROS communications
    rclcpp::shutdown();
    return 0;
}


Add a Python node and module to import

For Python, we need to create additional folders first:

mkdir cpp_py_pkg
touch cpp_py_pkg/__init__.py
mkdir scripts

Then we can add the files:

touch cpp_py_pkg/module_to_import.py
touch scripts/py_node.py


You have to add a shebang line first thing in the py_node.py file otherwise you will get an error when trying to run the node:

#!/usr/bin/env python3
import rclpy
from rclpy.node import Node
# Import a specific function/class from your module
# from cpp_py_pkg.module_to_import import …
def main(args=None):
# Initiate ROS communications
    rclpy.init(args=args)
# Instantiate the node
    node = Node(‘my_node_name’)
# Make the node spin
    rclpy.spin(node)
# Shutdown ROS communications
    rclpy.shutdown()
if __name__ == ‘__main__’:
    main()

 

Final package architecture

Run the “tree . command to see the folder structure. I have added additional comments and files to make it clearer:

cpp_py_pkg/
# –> package info, configuration, and compilation
├── CMakeLists.txt
├── package.xml
# Python stuff
# –> empty init file & any python library or module files we want to import
├── cpp_py_pkg
│ ├── __init__.py
│ └── module_to_import.py
│ └── another_module_to_import.py
# –> python executables/nodes
├── scripts
│ └── py_node.py
# Cpp stuff
# –> cpp header files
├── include
│ └── cpp_py_pkg
│ └── cpp_header.hpp
│ └── another_cpp_header.hpp
# –> cpp executables/nodes
└── src
└── cpp_node.cpp

The CMakeLists.txt and package.xml will be shared by Python and C++, which is what we will edit in the next section to configure the package for both Python and C++.

Configure the package

package.xml


Add a buildtool_depend tag for ament_cmake_python:

<buildtool_depend>ament_cmake_python</buildtool_depend>

So your package.xml should look like this:

<?xml version=”1.0″?>
<?xml-model href=”http://download.ros.org/schema/package_format3.xsd” schematypens=”http://www.w3.org/2001/XMLSchema”?>
<package format=”3″>
<name>cpp_py_pkg</name>
<version>0.0.0</version>
<description>TODO: Package description</description>
<maintainer email=”user@todo.todo”>user</maintainer>
<license>TODO: License declaration</license>

<buildtool_depend>ament_cmake</buildtool_depend>
<buildtool_depend>ament_cmake_python</buildtool_depend>

<depend>rclpy</depend>
<depend>rclcpp</depend>

<test_depend>ament_lint_auto</test_depend>
<test_depend>ament_lint_common</test_depend>

<export>
<build_type>ament_cmake</build_type>
</export>
</package>

cd ~/ros2_ws/
colcon build –packages-select py_pkg

 

CMakeLists.txt

Add this external dependency:

find_package(ament_cmake_python REQUIRED)

Add this for C++:

# Include Cpp “include” directory
include_directories(include)

# Create Cpp executable and link with dependencies
add_executable(cpp_executable src/cpp_node.cpp)
ament_target_dependencies(cpp_executable rclcpp)

# Install Cpp executables in the ros2_ws/install/cpp_py_pkg/lib/cpp_py_pkg/ folder
install(TARGETS
cpp_executable
DESTINATION lib/${PROJECT_NAME}
)

Add this for Python:

# Install Python modules
ament_python_install_package(${PROJECT_NAME})

# Install Python executables in the ros2_ws/install/cpp_py_pkg/lib/cpp_py_pkg/ folder
install(PROGRAMS
scripts/py_node.py
DESTINATION lib/${PROJECT_NAME}
)

So your CMakeLists.txt should look like this:

source ~/.bashrc # . ~/.bashrc

So your CMakeLists.txt should look like this:

cmake_minimum_required(VERSION 3.8)
project(cpp_py_pkg)

if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES “Clang”)
add_compile_options(-Wall -Wextra -Wpedantic)
endif()

# find dependencies
find_package(ament_cmake REQUIRED)
find_package(rclpy REQUIRED)
find_package(rclcpp REQUIRED)
find_package(ament_cmake_python REQUIRED)

# Include Cpp “include” directory
include_directories(include)

# Create Cpp executable and link with dependencies
add_executable(cpp_executable src/cpp_node.cpp)
ament_target_dependencies(cpp_executable rclcpp)

# Install Cpp executables in the ros2_ws/install/cpp_py_pkg/lib/cpp_py_pkg/ folder
install(TARGETS
cpp_executable
DESTINATION lib/${PROJECT_NAME}
)

# Install Python modules
ament_python_install_package(${PROJECT_NAME})

# Install Python executables in the ros2_ws/install/cpp_py_pkg/lib/cpp_py_pkg/ folder
install(PROGRAMS
scripts/py_node.py
DESTINATION lib/${PROJECT_NAME}
)

if(BUILD_TESTING)
find_package(ament_lint_auto REQUIRED)
# the following line skips the linter which checks for copyrights
# comment the line when a copyright and license is added to all source files
set(ament_cmake_copyright_FOUND TRUE)
# the following line skips cpplint (only works in a git repo)
# comment the line when this package is in a git repo and when
# a copyright and license is added to all source files
set(ament_cmake_cpplint_FOUND TRUE)
ament_lint_auto_find_test_dependencies()
endif()

ament_package()

Compile package, then run C++ node and Python node

cd ~/ros2_ws/
colcon build –packages-select cpp_py_pkg

Source ROS2 environment and start C++ node in one terminal:

source ~/ros2_ws/install/setup.bash
ros2 run cpp_py_pkg cpp_executable

Source ROS2 environment and start Python node in another terminal:

source ~/ros2_ws/install/setup.bash
ros2 run cpp_py_pkg py_node.py

That’s it! If there are no errors when you run the nodes then it means that it was successful (remember that our nodes do not do anything except spin).

Congratulations. You now know how to use C++ and Python in the same ROS 2 package.

To learn more about ROS 2, have a look at the course below:

We hope this post was really helpful to you.

This tutorial is created by Robotics Ambassador Ernest.

Video Tutorial

Comment créer des bibliothèques avec ROS2 Python – ROS French Tutorial

Comment créer des bibliothèques avec ROS2 Python – ROS French Tutorial

This tutorial is created by RA 023 Enzo

Rosbotics Ambassador Program https://www.theconstruct.ai/rosbotics-ambassador/)
Cours: ROS2 Baiscs in 5 Days Python: https://app.theconstructsim.com/courses/132

Introduction

Le but de ce tutoriel est d’apprendre à créer et utiliser des bibliothèques dans les packages ROS2 Python. Lors du développement d’un projet, il est essentiel de garder son code structuré pour assurer un développement efficace. L’utilisation de bibliothèque (ou library) custom est indispensable pour cela car cela permet de regrouper les codes sources en fonction de leurs usages et donc de séparer des fonctionnalités distinctes. La création de bibliothèques est donc essentielle pour rendre votre code plus structuré, modulaire et réutilisable. Nous allons donc voir ensemble comment déclarer et faire appel une custom library dans les packages ROS2 Python.
Pré-requis
Pour lancer et tester le code, vous devez lancer la simulation du turtlebot3 sur gazebo. Si vous voulez effectuer le tutoriel sur votre installation local, vous devez avoir ROS2 installé (https://docs.ros.org/en/humble/Installation.html), avoir configuré un workspace (https://docs.ros.org/en/humble/Tutorials/Beginner-Client-Libraries/Creating-A-Workspace/Creating-A-Workspace.html) et avoir installé le turtlebot3.

# pour installer tous les packages du turtlebot3
# remplacez humble par votre distro ROS2
sudo apt-get install ros-humble-turtlebot3*
# n'oubliez pas d'exporter le modèle de Turtlebot3 que vous souhaitez utiliser
export TURTLEBOT3_MODEL=waffle_pi

Si vous effectuez ce tutoriel en utilisant un Rosject vous pouvez directement enter les commandes suivantes dans le terminal:

# Declare le model de turtlebot3 à simuler
export TURTLEBOT3_MODEL=waffle_pi
# Lance la simulation du turtlebot dans gazebo
ros2 launch turtlebot3_gazebo turtlebot3_world.launch.py

Une fois la simulation du turtlebot3 lancée, celle-ci va publier sur le topic /odom que nous allons utiliser dans le code exemple.
Après avoir exécuté ces commandes, appuyez sur le bounton de l’interface gazebo et selectionnez Open Gazebo.


Vous devriez obtenir le résultat suivant.

Part 1: Créer un package qui va contenir le source code de la library

Nous allons commencer par créer le package python qui va servir de bibliothèque. Ouvrez un terminal et executez les commandes suivantes:

cd ~/ros2_ws/src
ros2 pkg create --build-type ament_python custom_library

Maintenant que le package est initialisé, nous allons créer le fichier qui va contenir le source code de la library. Pour faire cela, ouvrez un terminal et executez les commandes suivantes:

cd ~/ros2_ws/src/custom_library/custom_library
touch odom_toolbox.py

Affichez l’éditeur de code et ouvrez le fichier odom_toolbox.py. Ajouter ensuite le code suivant:

from geometry_msgs.msg import Point
class OdometryToolbox:
    def point_from_odom_offset_init(actual_odom, init_odom):
   
        point_with_offset = Point()
        point_with_offset.x = actual_odom.pose.pose.position.x - init_odom.pose.pose.position.x
        point_with_offset.y = actual_odom.pose.pose.position.y - init_odom.pose.pose.position.y
        point_with_offset.z = actual_odom.pose.pose.position.z - init_odom.pose.pose.position.z
        return point_with_offset

Ce code d’exemple déclare une class contenant une méthode permettant de soustraire terme à terme la position d’une odom avec une autre et de retourner le point obtenu.
Vous pouvez compiler le package pour tester que tout fonctionne.

cd ~/ros2_ws
colcon build
source install/setup.bash

Part 2: Créer un package qui va utiliser la library créée précédemment

Nous allons créer un package python qui va utiliser la bibliothèque créee dans la partie une. Ouvrez un terminal et executez les commandes suivantes:

cd ~/ros2_ws/src
ros2 pkg create --build-type ament_python my_package

Une fois le package créer, nous allons créer un fichier main.py qui contiendra le node exemple.

cd ~/ros2_ws/src/my_package/my_package
touch main.py

Collez ensuite le code ci-dessous dans le fichier main.py.

# main.py
import rclpy
from rclpy.node import Node
from geometry_msgs.msg import Point
from nav_msgs.msg import Odometry
# importer la custom library
from custom_library.odom_toolbox import OdometryToolbox
class OdomToPointNode(Node):
    def __init__(self):
        super().__init__('odom_to_point_node')
        # Initialiser le subscriber sur le topic odom du turtlebot3
        self.odom_subscription = self.create_subscription(
            Odometry,
            'odom',
            self.odom_callback,
            10
        )
        self.odom_subscription
        # Initialiser le publisher du point
        self.point_publisher = self.create_publisher(Point, 'point_topic', 10)
       
        self.odom_init = Odometry()
        self.isOdomInit = False
       
    def odom_callback(self, msg):
       
        if self.isOdomInit == False:
            # Recuperer la valeur initial de la premiere odometry
            self.odom_init = msg
            self.isOdomInit = True
       
        point_msg = Point()
        # Utilser la method declaree dans la custom_library
        point_msg = OdometryToolbox.point_from_odom_offset_init(msg, self.odom_init)
        # Publier le point obtenu
        self.point_publisher.publish(point_msg)
        print(f'Point Published: {point_msg.x}, {point_msg.y}, {point_msg.z}')
def main(args=None):
    rclpy.init(args=args)
    odom_to_point_node = OdomToPointNode()
    rclpy.spin(odom_to_point_node)
    odom_to_point_node.destroy_node()
    rclpy.shutdown()
if __name__ == '__main__':
    main()

Pour pouvoir utiliser votre library custom dans votre package, vous devez mettre à jour le setup.py du package.

# setup.py
from setuptools import setup
package_name = 'my_package'
setup(
    name=package_name,
    version='0.0.0',
    packages=[package_name],
    data_files=[
        ('share/ament_index/resource_index/packages',
            ['resource/' + package_name]),
        ('share/' + package_name, ['package.xml']),
    ],
    install_requires=[
        'setuptools',
        # ajouter votre library dans les install_requires
        'custom_library'],
    zip_safe=True,
    maintainer='user',
    maintainer_email='user@todo.todo',
    description='TODO: Package description',
    license='TODO: License declaration',
    tests_require=['pytest'],
    entry_points={
        'console_scripts': [
            # Ajouter le node dans les console_scripts
            'odom_to_point_node = my_package.main:main',
        ],
    },
)

Une fois que les fichiers suivants ont été modifiés, vous pouvez build le package.

cd ~/ros2_ws
colcon build
source install/setup.bash

Step 3: Tester le node

Pour lancer le node, lancez la simulation comme indiqué dans les prérequis. Vous devez ensuite exécuter les commandes suivantes dans un terminal:

ros2 run my_package odom_to_point_node

Maintenant que le code est en cours d’exécution, vous devriez avoir un print des coordonnées du robot en ayant pour origine la position du robot au moment du lancement le node.

Merci d’avoir suivi ce poste.

Ressources

• ROS Ignite Academy
• ROS2 Full course for beginner
• Rosject utilisé pour le poste

Feedback

Cet article vous a plu ? Avez-vous des questions sur ce qui est expliqué ? Quoi qu’il en soit, n’hésitez pas à laisser un commentaire dans la section des commentaires ci-dessous, afin que nous puissions interagir et apprendre les uns des autres.

Si vous souhaitez en savoir plus sur d’autres sujets liés à ROS, faites-le nous savoir dans l’espace commentaires et nous ferons une vidéo ou un article à ce sujet.
Topics: ROS Q&A | ros2

Video Tutorial

Pin It on Pinterest