ROS Tutorial
Paul Buzaud
Robotic imply:
How to manage the communication between these differents systems?
How does this work:
Core of ros is the ROSMASTER, it don’t own but register all the ros component on the local/remote network:
Basic tutorial:
Advanced tutorial (don‘t have to remember it for now):
Rosmaster registered 3 topics/address:
One ROS publisher communicate some float to one ros subscriber on the “/temperature” topic/address
Example:
The switch subscriber connected to the “/temperature” topic don’t get any data because the rosmessage type is wrong (Can’t parse data)
The forecast subscriber will receive data from the thermometer 1 and 2
Topics:
Let’s implement this in Python:
Publisher.py side:
#!/usr/bin/env python or #!/usr/bin/env python3 if noetic
import rospy
from std_msgs.msg import Float64
# Define this script as a rosnode/rosexecutable which
#will be register in the rosmaster
rospy.init_node('publisher', anonymous=True)
#initialize the publisher with the topics/address "/temperature",
# message type is a Float64
pub = rospy.Publisher('/temperature', Float64, queue_size=10)
# basic while loop which check if the rosmaster is alive
while not rospy.is_shutdown():
#create a temperature msg as a float64
temperature_msg = Float64()
#set the temperature published to 72 fahrenheit
temperature_msg.data = 72.
#publish the message on the "/temperature" address through the publisher
pub.publish(temperature_msg)
#wait 1 second until sending the new message
rospy.sleep(1)
Subscriber.py side:
#!/usr/bin/env python or #!/usr/bin/env python3 if noetic
import rospy
from std_msgs.msg import Float64
#function triggered by the subscriber
def temperature_callback(msg):
#print the msg data receive by the subscriber in the terminal
print(msg.data)
# Define this script as a rosnode/ros executable which will be register in the rosmaster
rospy.init_node('subscriber', anonymous=True)
#initialize the subscriber whith the topics/address "/temperature", message type is a Float64
# whenever a new message will ne published on the "/temperature" topic,
#the temperature_callback function will be triggered
rospy.Subscriber("/temperature", Float64, temperature_callback)
# spin() simply keeps python from exiting until this node is stopped
#and keeps the subscriber callback running
rospy.spin()
Exercice:
The scripts should work properly if you have a clean installation of ros. If not, check also if in your bashrc, you have got the line: “source /opt/ros/{$distro can be melodic or kinetic or noetic….}/setup.bash”
Things to remember:
Exercice:
Rosnodes and catkin workspace
Rosnode = Python/C++ executable
How to setup a proper ros environment and create a ros package?
> mkdir -p ~/whatevername_ws/src
> echo 'source /opt/ros/{your_distro}/setup.bash' >> ~/.bashrc
How to setup a proper ros environment and create a ros package?
> cd ~/whatevername_ws/src
> catkin_create_pkg ros_thermometer
How to setup a proper ros environment and create a ros package?
> cd ~/whatevername_ws/src/ros_thermometer
> mkdir -p ~/whatevername_ws/src/ros_thermometer/scripts
How to setup a proper ros environment and create a ros package?
Take a look at the package xml
Nothing is really important in this as it is still empty beside:
As our scripts use rospy libraries and std_msgs for type like float64/String/Bool, we add these dependencies with the <depend> tag
Take a look at the CMakeLists.txt
without all the comments
Cmake_minimum_required -> version of cmake required for the compilation
project()->name of your ros package
find _package -> prevent the compilation if some dependencies are not solved
First of all find_package permits to avoid to generate the building if some of your dependency listed are not present. We added the std_msgs and the rospy dependency in this.
Our CMake doesn’t require a lot of things because python is interpreted not compiled. C++ required a lot of others modifications to generate the executable
> chmod +x ~/whatevername_ws/src/ros_thermometer/scripts/publisher.py
> chmod +x ~/whatevername_ws/src/ros_thermometer/scripts/subscriber.py
> cd ~/whatevername_ws/
> catkin build (you will need to install catkin-tools first)
Or
> catkin_make (default compilation system)
Run your node !
> source devel/setup.bash
Run your node !
What did we do here?
Is there a easier way to run nodes ?
What is roslaunch?
How does it look like?
> mkdir -p ~/whatevername_ws/src/ros_thermometer/launch
How does a launch file look like?
Exercice:
source ~/whatevername_ws/devel/setup.bash
roslaunch ros_thermometer basic.launch
Exercice:
What if we want to add some parameter to a rosnode/process ?
<launch>
<node name="thermometer_subscriber" pkg="ros_thermometer" type="subscriber.py" output="screen"/>
<node name="thermometer_publisher" pkg="ros_thermometer" type="publisher.py" output="screen">
<remap from="/temperature" to="test_remap"/>
</node>
</launch>
This is a one line node definition
This is a two line node definition, the remap is inside the node definition
What if we want to add some parameter to a rosnode/process ?
roslaunch ros_thermometer basic.launch
Rostopic list
What happened?
By using the remapping tag inside the
publisher node, we change the
topic address of publication to /test_remap
All the messages are published on the /test_remap
The subscriber don’t get any message because it is still subscribed to the /temperature topic
What happened?
rospy.Publisher('/temperature', Float64, queue_size=10)
rospy.Publisher('/test_remap', Float64, queue_size=10)
Exercice
What if we want to add some parameter to a rosnode/process ?
Loading rosparameter in a rosnode through roslaunch
<param name="unit" value="Fahrenheit"/>
Loading rosparameter in a rosnode through roslaunch
<launch>
<param name="unit" value="Fahrenheit"/>
<node name="thermometer_publisher" pkg="ros_thermometer" type="publisher.py" output="screen">
</node>
<node name="thermometer_subscriber" pkg="ros_thermometer" type="subscriber.py" output="screen"/>
</launch>
Loading rosparameter in a rosnode through roslaunch
roslaunch ros_thermometer parameter_testing.launch
Rosparam list
Loading rosparameter in a rosnode through roslaunch
Rosparam get /unit
variable = rospy.get_param(“/unit”)
Exercice
Formula is: (0°C × 9/5) + 32 = 32°F
Things to remember:
<param name="unit" value="Fahrenheit"/>
variable = rospy.get_param(“/unit”)
Getting the value of one parameter on the rosmaster in python
Loading rosparameter on the rosmaster throught launch file
Loading rosparameter on the rosmaster throught terminal
Rosparam get /unit
Getting rosparameter on the rosmaster throught terminal
Rosparam set /unit Celsius
Rosparameter namespace
Rosparam list
<launch>
<param name="unit" value="Celsius"/>
<node name="thermometer_publisher" pkg="ros_thermometer" type="publisher.py" output="screen">
<param name="unit" value="Fahrenheit"/>
</node>
<node name="thermometer_subscriber" pkg="ros_thermometer" type="subscriber.py" output="screen"/>
</launch>
Rosparameter namespace
variable = rospy.get_param(“/unit”) # the “/” before unit represents the absolute path
Rosparameter namespace
variable = rospy.get_param(“~unit”) # the “~” before unit represents the relative private path
Rosparameter namespace
Rosparam list
<launch>
<group ns="test">
<param name="unit" value="Celsius"/>
<node name="thermometer_publisher" pkg="ros_thermometer" type="publisher.py" output="screen">
<param name="unit" value="Fahrenheit"/>
</node>
<node name="thermometer_subscriber" pkg="ros_thermometer" type="subscriber.py" output="screen"/>
</group>
</launch>
Rosparam namespace
variable = rospy.get_param(“/unit”) variable = rospy.get_param(“unit”)
Things to remember !
Things to remember !
<group ns=”test”>
</group>
Multiple parameters loading
mkdir -p ~/whatevername_ws/src/ros_thermometer/params
touch ~/whatevername_ws/src/ros_thermometer/params/basic_params.yaml
Multiple parameters loading
is_sim: true,
test_yaml: {
x_gain: 0.8,
y_gain: 0.1,
z_gain: 0.4,
center_point: [0.1,0.4,0.3]
}
<rosparam command="load" file="$(find ros_thermometer)/params/basic_params.yaml"/>
Multiple parameters loading
<launch>
<group ns ="test">
<rosparam command="load" file="$(find ros_thermometer)/params/basic_params.yaml"/>
<param name="unit" value="Celsius"/>
<node name="thermometer_publisher" pkg="ros_thermometer" type="publisher.py" output="screen">
<param name="unit" value="Fahrenheit"/>
</node>
<node name="thermometer_subscriber" pkg="ros_thermometer" type="subscriber.py" output="screen"/>
</group>
</launch>
Multiple parameters loading
Rosparam list
Conclusion
Git clone http://192.168.1.101/infrastructure/ros_python_package_template
You will have to rename the project name in the CMakelist.txt and package.xml, the python class, the name of the executable and the import to your convenience. Easiest way to do it is to open it inside pycharm,
Use the Ctrl+Shift +R shortcut and replace all the ros_python_package_template occurence to your package name. Then rename the scripts/executables files
Ros network and ros tools
Ros network
Ros network: pinging part
ifconfig
wlo1: represents here my wifi port on the
Local machine
Inet below it: 192.168.1.241 represents my
IP address on my wifi network
Ros network: pinging part
Ping YOUR_ROSMASTER_IP_ADDRESS
Do the same from all the others robots to the rosmaster or from the rosmaster to all the others robots. Using the ifconfig to get their IP address
Ros Network: environment of the nodes
Ros Network: environment of the nodes
export ROS_IP=xxx.www.zzzz.aaa (ip of computer on the network)
Here the ip of my rosmaster is 192.168.1.241, so:
export ROS_IP=192.168.1.241 (ip of computer on the network)
I will add this line in my ~/.bashrc. You can open this file using: gedit ~/.bashrc or nano ~/.bashrc in a terminal
Ros Network: environment of the nodes
export ROS_MASTER_URI=http://xxx.www.zzzz.aaa:11311 (ip of the remote master on the network)
export ROS_IP=xxx.www.zzzz.aaa (ip of the current robot on the network)
Here the ip of my rosmaster is 192.168.1.241, so:
export ROS_MASTER_URI=http://192.168.1.241:11311 (ip of the remote master on the network)
export ROS_IP=xxx.www.zzzz.aaa (ip of the robot on the network depending on the ifconfig result on this robot can be whatever 192.168.1.XXX)
I will add these two lines in their ~/.bashrc. You can open this file using: gedit ~/.bashrc or nano ~/.bashrc in a terminal
Ros Network: environment of the nodes
source ~/.bashrc
Exercise