In questo tutorial verrà mostrata un’implementazione di un nodo subscriber in grado di leggere messaggi di diverso tipo e provenienti da molteplici topic, gestiti attraverso una singola funzione di callback.
Nel caso non si volesse installare ROS Noetic sul proprio sistema e fare il set up dell’ambiente di sviluppo, è possibile utilizzare i Rosject offerti da The Construct per poter testare i contenuti del tutorial o per seguirlo passo passo.
Per fare ciò sarà sufficiente seguire il link indicato nelle risorse e cliccare su “Run”. In questo modo si avrà accesso a una copia del
Rosject utilizzato all’interno del tutorial.
Aprire terminal e IDE
Per aprire un nuovo terminale e avere accesso all’IDE forniti dal Rosject, sarà possibile utilizzare la console in basso a destra.
Prerequisiti
Per poter seguire il tutorial passo passo sarò necessario avere il nodo publisher, che pubblica su diversi topic, attivo e creare un package dove poter inserire il codice per il subscriber.
Per iniziare eseguiamo il nodo publisher. Sarà sufficiente aprire il terminale dalla console (vedi Risorse) e inserire i seguenti comandi nelle rispettive schede del terminale:
Terminale 1: roscore Terminale 2: cd catkin_ws
rosrun publisher publisher.py
Quindi è possibile verificare il corretto funzionamento del nodo aprendo una seconda finestra al’interno del terminale e osservando l’output del comando rostopic list.
L’output previsto è il seguente:
Terminale 3: rostopic list
/chatter0
/chatter1
/chatter2
/rosout
/rosout_agg
Procediamo quindi a creare il package per il subscriber:
Terminale 3: cd src
catkin_create_pkg multiple_subscriber rospy std_msgs
mkdir multiple_subscriber/script
Situazione di partenza
Al momento abbiamo eseguito il nodo publisher che pubblica su 3 topic messaggi di vario tipo. In particolare:
/chatter0 pubblica messaggi di tipo String
/chatter1 pubblica messaggi di tipo Float64
/chatter2 pubblica messaggi di tipo Bool
Vediamo quindi come possiamo gestire tutti e tre i topic, creando un subscriber in grado di leggere i messaggi dai chatter e di gestirli con una singola funzione di callback, differenziando il risultato di quest’ultima sfruttando l’uso di parametri.
Creazione del file multiple_sub.py
Proseguiamo creando il file necessario a definire il nostro subscriber e tutte le sue funzioni.
Terminale 3: touch multiple_sub/script/multiple_subscriber.py # Crea il file
chmod +x multiple_sub/script/multiple_subscriber.py # Garantisce i permessi di esecuzione
cd ..
catkin_make
Implementazione del subscriber
Partiamo quindi dallo specificare un interprete per il nostro codice in Python, dall’importare i moduli necessari (rospy e in questo caso std_msgs/String, std_msgs/Float64, std_msgs/Bool) e dallo scrivere un main che inizializzi il nodo e invochi rospy.spin() per poter eseguire le callback del nostro subscriber.
main
multiple_subscriber.py import rospy
from std_msgs.msg import String, Float64, Bool
if __name__=="__main__":
rospy.init_node("multiple_subscriber")
topics = {"chatter0": [String, "Argomento passato da chatter0"], "chatter1": [Float64, "Argomento passato da chatter1"], "chatter2": [Bool, "Argomento passato da chatter2"]}
multiple_subscribe()
rospy.spin()
All’interno della funzione abbiamo definito anche topics, un dizionario contenente le specifiche dei topic che vogliamo andare a leggere, seguendo la seguente struttura: {"nome_topic": [Tipo, Argomento]}
Per ogni chiave topic abbiamo quindi definito una lista contente il tipo del messaggio inviato dal topic e un argomento (in questo caso una stringa che esplicita di essere l’argomento passato per lo specifico topic) .
multiple_subscribe
La funzionemultiple_subscribe() sarà definita perché il nodo possa seguire i 3 topic e perché i messaggi pubblicati possano innescare la callback.
Il nodo segue quindi ciascuno dei topic definiti nel dizionario, aspettandosi messaggi del relativo tipo, invocando una funzione callback e passando il relativo argomento tramite il parametro callback_args.
callback
Vediamo una semplice implementazione della callback per poter gestire i tre topic.
multiple_subscriber.py def callback(data, args):
rospy.loginfo(f"Ricevuto: {data.data}")
print(args)
print('\n')
In questo caso andiamo a stampare come info di ROS il contenuto del messaggio arrivato alla callback e stampiamo l’argomento passato corrispondente. Entrambi dipenderanno da quale topic ha innescato la callback e perciò a questo livello il messaggio può essere gestito a seconda del parametro ad esso associato, potendo implementare in qualche modo un’esecuzione “su misura” della funzione di callback.
Test del subscriber
Siamo pronti per poter eseguire il nostro subscriber!
Ciò che ci aspettiamo è che vengano stampati allo stesso tempo il messaggio e l’argomento relativi alla callback innescata dall’arrivo di un messaggio dal singolo topic. L’output dovrebbe quindi essere di questo tipo:
[INFO] [***.***]: Ricevuto: Questo pubblica una stringa
Argomento passato da chatter0
[INFO] [***.***]: Ricevuto: 0.42
Argomento passato da chatter1
[INFO] [***.***]: Ricevuto: True
Argomento passato da chatter2
Possiamo osservare come gli output si alternano ogni secondo a rotazione, ma questo è dovuto alla singola implementazione del publisher (che è possibile trovare all’interno del Rosject, vedi Risorse).
In ogni caso per ogni topic viene ricevuto, gestito e stampato un messaggio specifico relativo ad esso, e l’elaborazione del relativo parametro, con diverso risultatononostante l’utilizzo della medesima funzione di callback.
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/5e6f9418/
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.
Setup the package architecture
Create a standard ROS2 package using ament_python
With dependencies on rclpy:
cd ~/ros2_ws/src/
ros2 pkg create py_pkg –build-type ament_python –dependencies rclpy
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:
Add custom Python module(s) that you want to import
You will need to add module files under the directory with the same name as the package (in this case py_pkg):
cd py_pkg/py_pkg
touch module_to_import.py
For this tutorial for simplicity, we can just add this minimal function to the module_to_import.py file that just prints “hello world”:
def function_to_import():
print(“hello world”)
Create a ‘scripts’ directory for your Python node(s)
Specify the directory as a Python package by creating an empty__init__.pyfile (essential for the folder to be recognized by Python as a package), then add a Python node:
cd ..
mkdir scripts
touch scripts/__init__.py
touch scripts/py_node.py
Here is a simple node implementation (to paste in py_node.py) that imports and uses the function from the module we just created:
import rclpy
from rclpy.node import Node
# Import a specific function/class from your module
from py_pkg.module_to_import import function_to_import
class MyPythonNode(Node):
def __init__(self):
super().__init__(“my_node_name”)
# Run the imported function
function_to_import()
def main(args=None):
# Initiate ROS communications
rclpy.init(args=args)
# Instantiate the node
node = MyPythonNode()
# Make the node spin
rclpy.spin(node)
# Destroy the node object
node.destroy_node()
# Shutdown ROS communications
rclpy.shutdown()
if __name__ == ‘__main__’:
main()
Final package architecture
Run the “tree.” command to see the folder structure inside py_pkg:
This is so that later when you build with colcon, ROS2 knows to put the Python packages here ~/<workspace_name>/install/<package_name>/lib/<python_version>/site-packages/<package_name> (in our case <workspace_name> is ros2_ws, <python_version> ispython3.10, and <package_name> is py_pkg).
If there is no warning then that’s great, but don’t worry if you get it as it is just a warning (not an error) and you will still be able to build successfully.
As of the time of writing this tutorial, the developers hope to have it fixed for Jazzy in May 2024, but for now, there are workarounds to remove the warning. The original workaround was to downgrade the version of setuptools that is currently installed by doing pip install setuptools==58.2.0 in the terminal. However, that is not recommended. Instead you should use the PYTHONWARNINGS environment variable to suppress that particular warning by adding this to the ~/.bashrc file:
PYTHONWARNINGS=”ignore:setup.py install is deprecated::setuptools.command.install”; export PYTHONWARNINGS
You could do this by entering this into the terminal:
echo “PYTHONWARNINGS=\”ignore:setup.py install is deprecated::setuptools.command.install\”; export PYTHONWARNINGS” >> ~/.bashrc
Don’t forget to source the .bashrc in the terminal before compiling the package to register the changes:
source ~/.bashrc # . ~/.bashrc
You should now be able to compile the package without the warning.
cd ~/ros2_ws/
colcon build –packages-select py_pkg
Run the node
In the terminal, source the ROS2 environment and start the Python node:
source ~/ros2_ws/install/setup.bash
ros2 run py_pkg py_node_executable
If you get the following output, that means it was successful!
hello world
Congratulations. You now know how to import custom Python3 modules in a ROS 2 package.
To learn more about ROS 2, have a look at the course below:
In this post, we will see how to implement Real Time in ROS2, using the ROS2 Pendulum Real Time demo.
Step 1: Grab a copy of the ROS Project containing the code
Click here to get your own copy of the project (PS: If you don’t have an account on the ROS Development Studio, you would need to create one. Once you create an account or log in, we will copy the project to your workspace).
That done, open the project using the Run button. This might take a few moments, please be patient.
You should now see a notebook with detailed instructions. This post includes a summary of these instructions and some other tips.
Step 2: Start the Simulation
Start a web shell from the bottom bar of the screen as shown above and run the following command:
cd ~/ros2_ws
source install/local_setup.bash
ros2 launch pendulum_bringup pendulum_bringup.launch.py rviz:=True
See the robot by clicking on the Graphical Tools icon on the bottom bar:
You should now see something like this (if you cannot see it, please ensure the ros2 launch command is still running and restart it if necessary):
You might need to drag the window into focus and then maximize it.
Move the robot by executing the following in a new terminal:
If you want to run the simulation on your local PC, then you need to run the commands given in the Setup section.
Step 3: Explore the source code using the IDE
Open the IDE by clicking on the icon as shown above. You should now see something similar to the image below:
All the files used in the simulation are in the ros2_ws/src directory. Explore the files. Double-click to open a file in the editor. You will refer back to some of the files later on.
Step 4: Watch the video to understand how the simulation implemented Real Time in ROS2 with the Pendulum
Here you go:
Step 5: Consolidate your learning
Do you understand how to implement Real Time in ROS2 after watching the video? If not, have you gone over the video again?
Can you try to implement the simulation on your local PC?
Did you like this post? Do you have any questions about the explanations? Whatever the case, please leave a comment on the comments section below, so we can interact and learn from each other.
If you want to learn about other ROS2 topics, please let us know in the comments area and we will do a video or post about it.
In this post, we will see how to implement Gazebo joints control in ROS2. The way this is done has changed a bit from ROS1.
Step 1: Grab a copy of the ROS Project containing the code
Click here to get your own copy of the project (PS: If you don’t have an account on the ROS Development Studio, you would need to create one. Once you create an account or log in, we will copy the project to your workspace).
That done, open the project using the Run button. This might take a few moments, please be patient.
You should now see a notebook with detailed instructions. This post includes a summary of these instructions and some other tips.
Step 2: Start the Simulation and get the robot moving
Start a web shell from the bottom bar of the screen as shown above and run the following command:
ros2 launch box_car_gazebo box_bot_launch.py
Start another tab in the web shell, run the following command:
ros2 run teleop_twist_keyboard teleop_twist_keyboard --ros-args --remap cmd_vel:=/box_bot/cmd_vel
See the robot by clicking on the Gazebo icon on the bottom bar:
You should now see something like this (if you cannot see it, please ensure the ros2 launch command is still running and restart it if necessary):
Put the Gazebo window and the shell window with the teleop command side by side, focus on the shell and move the robot with the keyboard. You should see the robot run off. PS: use the z key to reduce the speed before moving the robot forward or backward, otherwise it runs off too quickly!
Step 3: Explore the source code using the IDE
Open the IDE by clicking on the icon as shown above. You should now see something similar to the image below:
All the files used in the simulation are in the ros2_ws/src directory. Explore the files. Double-click to open a file in the editor. You will refer back to some of the files later on.
Step 4: Watch the video to understand how we implemented gazebo joints control in ROS2
Here you go:
Step 5: Consolidate your learning
Do you understand how to implement gazebo joints control in ROS2 after watching the video? If not, have you gone over the video again?
If you are familiar with ROS1 control, can you see how it’s different from ROS control?
Did you like this post? Do you have any questions about the explanations? Whatever the case, please leave a comment on the comments section below, so we can interact and learn from each other.
If you want to learn about other ROS2 topics, please let us know in the comments area and we will do a video or post about it.
In this post, we will see how to make a robot follow another robot. We’ll make the iRobot follow the big turtle all around the world when it moves, using ROS TF broadcaster and listener nodes.
PS:This ROS project is part of our ROS Mini Challenge series, which gives you an opportunity to win an amazing ROS Developers T-shirt! This challenge is already solved. For updates on future challenges, please stay tuned to our Twitter channel.
Step 1: Grab a copy of the ROS Project containing the code for the challenge
Click here to get your own copy of the project. If you don’t have an account on the ROS Development Studio, you will need to create one. Once you create an account or log in, we will copy the project to your workspace. That done, open your ROSject using the Open button. This might take a few moments, please be patient.
You should now see a notebook with detailed instructions about the challenge. This post includes a summary of these instructions as well as the solution to the challenge.
PS: Please ignore the Claim your Prize! section because…well…you are late the party 🙂
Step 2: Start the Simulation and get the robots moving
Click on the Simulations menu and then Choose launch file… . In the dialog that appears, select rotw7.launchunder turtle_tf_3d package. Then click the Launchbutton. You should see a Gazebo window popup showing the simulation.
Get the robots moving. Pick a Shell from the Tools menu and run the following commands:
At this point, you should already see the iRobot moving towards the big turtle.
Nothing happened? Heck, we gotta fix this! Let’s do that in the next section.
Step 3: Let’s find the problem
So the robots didn’t move as we expected. And we had this error message:
[INFO] [1580892397.791963, 77.216000]: Retrieveing Model indexes
[INFO] [1580892397.860043, 77.241000]: Robot Name=irobot, is NOT in model_state, trying again
The error message above says it cannot find the model name specified in the code, so let’s check that up. Fire up the IDE from the Tools menu and browse to the directory catkin_ws/src/rotw7_pkg/scripts. We have two Python scripts in there:
turtle_tf_broadcaster.py
turtle_tf_listener.py
The robot model names are specified on line 19 of turtle_tf_broadcaster.py:, in the publisher_of_tf function:
robot_name_list = ["irobot","turtle"]
Let’s check if we can find these robots in the simulation, using a Gazebo service:
But, which of the turtles is the follower, and what is the correct topic for its “cmd_vel”? We have a hint from the launch file irobot_follow_turtle.launch:
So the follower is turtle2. Now, let’s check what it’s “cmd_vel” topic is. It’s specified as /cmd_vel in the code, but is this true? Let’s check the list of topics:
user:~$ rostopic list
#...
/turtle1/cmd_vel
/turtle2/cmd_vel
Probably, it’s /turtle2/cmd_vel. How do we know? Let’s publish to both /cmd_vel and /turtle2/cmd_vel and see which works.
You should now see the iRobot moving towards the big turtle. Now you can start moving the Turtle using the keyboard. Pick another Shell from the Tools menu and run the following command:
Move the big turtle around with the keyboard, and you should see that the iRobot follows it. Done, that’s an example of how to make a robot follow another robot.
Extra: Video of this post
We made a video showing how we solved this challenge and made the iRobot follow another robot. If you prefer “sights and sounds” to “black and white”, here you go:
Did you like this post? Do you have any questions about the explanations? Whatever the case, please leave a comment on the comments section below, so we can interact and learn from each other.
If you want to learn about other ROS or ROS2 topics, please let us know in the comments area and we will do a video or post about it.