ROS basic tutorial
ROS Basic#
Publisher & Subscriber#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| # Node initilization
rospy.init_node(noe_name, anonymous=True, disable_signals=True)
# Create a publisher and publish data
pub = rospy.Publisher(topic_name, data_class)
pub.publish(data)
# Publish at a rate (Hz)
r = rospy.Rate(20)
while not rospy.is_shutdown():
pub.publish(data)
r.sleep()
# Create a subscriber, callback_function will be automatically called when data is published on this topic
rospy.Subscriber(topic_name, data_class, callback_function)
|
Publisher can’t publish immediately after it is created. Need rospy.sleep(1)
or use latch
.
Messages#
1
2
3
4
5
| # With latch=True, new subscriber always gets the last message that was published even if the message was published before the subscriber was connected.
pub = rospy.Publisher(topic_name, data_class, latch=True)
# Wait unitl receive message with given datatype in given topic
rospy.wait_for_message(topic_name, data_class)
|
Create a msg#
Make msg
directory inside ROS package, create Test.msg
file with datatype content, for example:
1
2
3
| string a
string b
uint8 c
|
Add the following two lines to package.xml
1
2
| <build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>
|
Change CMakeList.txt
as follows:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| find_package(catkin REQUIRED COMPONENTS
rospy
std_msgs
message_generation
)
catkin_package(
CATKIN_DEPENDS message_runtime ...
)
add_message_files(
FILES
Test.msg
)
generate_messages(
DEPENDENCIES
std_msgs
)
|
It can be imported by from [package].msg import Test
Service#
1
2
| # Create a Service
rospy.Service(name, service_class, callback_function)
|
Create a srv#
Similar to msg, create Test.srv
in srv/
; change package.xml
and CMakeLists.txt
, the difference is:
1
2
3
4
| add_service_files(
FILES
AddTwoInts.srv
)
|
It can be imported by from [package].srv import Test
Frames are published on the tf
topic.
1
2
3
4
5
6
7
| # Find transforms between coordinate frames, rospy.Time(0) will give the latest available transform
tfl = tf.TransformListener()
trans, rot = tfl.lookupTransform(frameid_1, frameid_2, rospy.Time(0))
# Create transforms between frames
pub_tf = tf.TransformBroadcaster()
pub_tf.sendTransform((trans_x, trans_y), quat, rospy.Time.now(), frameid_1, frameid_2)
|
Launch File & Parameter#
1
2
3
4
5
6
7
8
9
10
11
12
13
| <launch>
<!-- Use include to run launch files -->
<include file='$(find [package])/[launch]' />
<!-- Define arguments for later use -->
<arg name='arg1' default='true' />
<!-- Run nodes -->
<node pkg='[package]' name='[node_name]' type='[python file]' output='screen'>
<!-- param can be used in file -->
<param name='arg1' value='$(arg arg1)' />
</node>
</launch>
|
Parameters will be in name
domain, for example, the above launch file will create a /node_name/arg1
parameter.
In the python file, arg1
can be read by
1
| arg1 = rospy.get_param('~arg1')
|
~
means in current node name domain.
Visualization#
Messages#
Visualize messages (values) using MarkerArray
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
| from visualization_msgs.msg import Marker, MarkerArray
import matplotlib.colors as colors
self.pub = rospy.Publisher([topic], MarkerArray, queue_size=50)
# Generate color map and scale by values
norm = colors.Normalize(clip=True)
norm.autoscale(values)
color_map = cm.get_cmap()
markers = MarkerArray()
# Add markers in markerarray
for i, (points, values) in enumerate(zip(points, values)):
marker = Marker()
marker.header.stamp = rospy.Time.now()
marker.header.frame_id = 'map'
# marker.ns = [namespace]
marker.id = i # ids are differenct so they won't replace each other
marker.type = Marker.LINE_STRIP
# marker.action = Marker.ADD
# Here we use points for visualization so that pose and orientation are not required
marker.pose.position.x = 0
marker.pose.position.y = 0
marker.pose.position.z = 0
marker.pose.orientation.x = 0
marker.pose.orientation.y = 0
marker.pose.orientation.z = 0
marker.pose.orientation.w = 1.0
marker.scale.x = 0.02
color = color_map(norm(values))
marker.color.r = color[0]
marker.color.g = color[1]
marker.color.b = color[2]
marker.color.a = color[3]
# Points are only used for markers of type Points, Line strips, and Line/Cube/Sphere lists. It's also used for the Arrow type, if you want to specify the arrow start and end points.
for point in points:
p = Point()
p.x, p.y = point[0], point[1]
marker.points.append(p)
markers.markers.append(marker)
self.pub.publish(markers)
|
Rviz#
Running rviz
without parameter will load the config in ~/.rviz/default.rviz
Save rviz config file and use rviz -d [config]
will launch Rviz and load the specified config file. This can be integrated in the launch file:
1
2
3
| <launch>
<node pkg="rviz" type="rviz" name="rviz" args="-d $(find [package])/[config.rviz]"/>
</launch>
|
Command Line#
File System#
1
2
3
4
5
6
7
| # Find package location
rospack find [package]
# cd into a package folder
roscd [package]
# cd into ros log files folder
roscd log
|
Package#
Use Catkin Command Line Tools to replace ROS built-in catkin tool.
1
2
3
4
5
6
7
| # Build/Clean the entire workspace
catkin build
catkin clean
# List the first-order/all dependencies
rospack depends1 [package]
rospack depends [package]
|
Run#
1
2
3
4
| # Run a single node
rosrun [package] [node]
# Run launch file
roslaunch [package] [launch]
|
Running Info#
- Nodes are just executable files within a ROS package, which can publish/subscribe to Topics or provide/use Services.
- Topics are for nodes to exchange messages.
- Services are similar to topics but for RPC (Remote procedure call) request.
- Messages are simple data structures.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
| # List all the nodes running
rosnode list
# List infos about a node, such as Publications, Subscriptions and Services
rosnode info [node]
# Clean useless nodes
rosnode cleanup
# Show a dynamic graph of nodes and topics
rosrun rqt_graph rqt_graph
# List all the topics
rostopic list
# Print data published on a topic
rostopic echo [topic]
# List infos about a topic, such as message type, Publishers and Subscribers
rostopic info [topic]
# Show message datatype
rosmsg show/info [msg]
# List all the services
rosservice list
# Call a service
rosservice call [service] [args]
# List all params
rosparam list
# Get/Set params
rosparam get [param]
rosparam set [param] [value]
# See all frames and the nodes publishing them
rosrun tf tf_monitor
# View the connection between frames
rosrun tf view_frames
|
Rosbag#
Filter a recorded rosbag by time:
1
| rosbag filter input.bag output.bag "t.secs >= 1531425960 and t.secs <= 1531426140"
|
Export certain topic from a rosbag to csv/txt:
1
| rostopic echo -b [bag_file] -p [topic_name] >> [output_file_name]
|