Skip to content

junmeng6025/ros_tutorial

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

78 Commits
 
 
 
 

Repository files navigation

ROS tutorial for beginers

Followed the videos on the YouTube channel ROS Tutorials - ROS Noetic For Beginners
and Bilibili channel (in Chinese) 【古月居】古月·ROS入门21讲 | 一学就会的ROS机器人入门教程-哔哩哔哩】.

Run the demo

Our package is named as robot_motion_ctrl.

0) Before anything

cd to the catkin_ws, source the /devel/setup.bash:

$ cd ros_tutorial/catkin_ws/
$ source devel/setup.bash

launch the ros master

$ roscore

run a turtlrsim node to visualize the turtle

$ rosrun turtlesim turtlesim_node

run a keyboard control node

$ rosrun turtlesim turtle_teleop_key

1) Publisher: the turtle draws a circle

  1. run a turtlesim node:
$ rosrun turtlesim turtlesim_node
  1. run a publisher to give the msg /turtle1/cmd_vel to the turtle:
$ rosrun robot_motion_ctrl pub_draw_circle.py

2) Subscriber: plot the pose information of the turtle in the terminal

  1. run a turtlrsim node:
$ rosrun turtlesim turtlesim_node
  1. run the subscriber to get the msg /turtle1/pose:
$ rosrun robot_motion_ctrl sub_pose.py
  1. make the turtle to move using either keyboard cmd:
$ rosrun turtlesim turtle_teleop_key

or draw a circle:

$ rosrun robot_motion_ctrl pub_draw_circle.py

3) Pub+Sub and Service:

make the turtle to cruise within an area, and change the pen color using ros service when crossing the middle.

  1. run a turtlrsim node:
$ rosrun turtlesim turtlesim_node
  1. run the ros node, which publishes velocity command to the turtle, and subscribes pose information from the turtle. In the meanwhile change the pen color using ros service according to the turtle's current pose.
$ rosrun robot_motion_ctrl turtle_ctrl.py

Common-used ROS commands

-1 Check the compute graph:

$ rqt_graph

-2 Check the active topics:

$ rostopic list

-3 Check the properties of rosnode:

$ rosnode info /turtlesim

you will get information about what this node publishes and subscribes.

-4 Publish message to a topic:

by default (hit the tab-key twice to fill automatically):

$ rostopic pub /turtle1/cmd_vel geometry_msgs/Twist "linear:
  x: 0.0
  y: 0.0
  z: 0.0
angular:
  x: 0.0
  y: 0.0
  z: 0.0"

publish the message frequently (e.g at 10 Hz): add -r 10 after pub

$ rostopic pub -r 10 /turtle1/cmd_vel geometry_msgs/Twist "linear:
  x: 1.0
  y: 0.0
  z: 0.0
angular:
  x: 0.0
  y: 0.0
  z: 0.0"

-5 Check the properties (i.e. the structure) of a ros message:

$ rosmsg show geometry_msgs/Twist

-6 Check the active ros services:

$ rosservice list

-7 Create a new turtle using rosservice:

$ rosservice call /spawn "x: 2.0
y: 2.0
theta: 0.0
name:'turtle2'"

get a message in the terminal: name: "turtle2", means that the new turtle is created successfully.

-8 Record and play a rosbag

record a rosbag:

$ rosbag record -a -O cmd_record

the command stream would be saved as cmd_record.bag.

play a rosbag:
launch the ros-master and launch a turtlesim node, then:

$ rosbag play cmd_record.bag

the turtle will start to move from the current position according to what was recorded.

Notes:

Install ROS Noetic

Follow the Ubuntu install of ROS Noetic on the ROS wiki if you are using Ubuntu. For other OS you can also find the corresponding installation guide on ROS wiki.
Tips: there is also a convienent way that can install ROS with a one-line command.

0) Create a workspace and initialize everything

0.1 Create the workspace

First create a project folder to contain all the data as well as the code you would need.
Under the Project folder, create a folder as ROS workspace, e.g. catkin_ws, and then under catkin_ws create a blank folder src to contain the executable code scripts.

create and initialize a workspace

$ mkdir -p~/catkin_ws/src  
$ cd ~/catkin_ws/src  
$ catkin_init_workspace  

the command $ catkin_init_workspace would create a cmake symlink of our workspace to the root ROS-cmake in our OS.

compile the workspace

$ cd ~/catkin_ws/  
$ catkin build  

Hint: There's another command to compile the ROS workspace:

$ catkin_make

ATTENTION
catkin_make and catkin build are of different mechanism. Make sure build a workspace with ONLY one of them all the way, rather than combine them at the same time.
Check out the differences between $ catkin build and $ catkin_make, see this.

set the env-variable

$ source devel/setup.bash

check the env-variable

$ echo $ROS_PACKAGE_PATH

This would return ALL the registered ROS package paths.

0.2 Create ROS packages

cd to catkin_ws/src/ and run

$ catkin_create_pkg robot_motion_ctrl rospy turtlesim

The syntax is
$ catkin_create_pkg <pkg_name> [depend1] [depend2] [depend3] [depend...]
to create a ROS package named robot_motion_ctrl, with the dependencies of rospy and a ROS built-in tutorial project turtlesim.
Each ROS packages can be seen as a sub-APP of the whole APP, which covers certain functionalities.

The ros package would contain two special files: CMakeLists.txt and package.xml, which determine that this folder has the ROS-package property.
Besides, the package folder would also contain an src folder.

Tips:

  1. There COULD NOT be packages of the same name under one workspace.
  2. In different workspaces there COULD be packages of the same name.

0.3 Build the ROS project

cd back to catkin_ws, run $ catkin build to generalize files for ROS communications.

Learning Topic

1) Write your first node: a publisher

In this Tutorial we will get familiar with the topic mechanism. We will learn to write the node in both Python and C++.
Here we created the package named learning_topic instead of robot_motion_ctrl above.
Under the package folder /learning_topic we have the folder /scripts containing the .py scripts and the folder /src containing .cpp scripts.

C++:

Write the node:

$ cd catkin_ws/src/learning_topic/src/
$ touch velocity_publisher.cpp
$ code .

And write your code using VSCode.
Generate the .exe file:
With the finished .cpp file, we need to make it as an executable file and link the required libs.
Go to catkin_ws/src/learning_topic and edit the CMakeLists.txt, add these two lines under the tag ### Build ###:

add_executable(velocity_publisher src/velocity_publisher.cpp)

-> creates an executable file out of the .cpp script, saved in ~/catkin_ws/devel/lib/<pkg_name>/.

target_link_libraries(velocity_publisher ${catkin_LIBRARIES})

-> links the required libs.

Compile and run the Publisher:

$ cd ~/catkin_ws
$ catkin_make
$ source devel/setup.bash
$ roscore                                     # in Sub-Terminal A
$ rosrun turtlesim_node                       # in Sub-Terminal B
$ rosrun learning_topic velocity_publisher    # in Sub-Terminal C

Tips:
Every time we have modified the .cpp scripts we need to rerun catkin_make to update the .exe file. For Python we don't need rerun the catkin_make after modifying the scripts, because the exe file is exactlly the .py file, which was converted by the command

$ chmod +x node.py

Python:

Write the node:

$ cd catkin_ws/src/learning_topic/scripts/
$ touch velocity_publisher.py
$ code .

And write your code using VSCode.
ALWAYS write

#!/use/bin/env python3

at the very begining of the .py script to make sure that it could be compiled by ROS successfully.
Generate the .exe file:

$ cd catkin_ws/src/learning_topic/scripts/
$ chmod +x velocity_publisher.py

Compile and run the Publisher:

$ cd ~/catkin_ws
$ catkin_make
$ source devel/setup.bash
$ roscore                                       # in Sub-Terminal A
$ rosrun turtlesim_node                         # in Sub-Terminal B
$ rosrun learning_topic velocity_publisher.py   # in Sub-Terminal C

For the Python scripts we DO NOT need to rebuild after modifying the code.

2) Write a subscriber

3) Customize a message type 自定义消息类型

Previously we have got familiar with the pre-defined ROS message types like turtlesim::Pose, geometry_msgs::Twist.
Now we try to define a new message type learning_topic::Person basing on our demand to publish the information of a person.

3.1) Define a .msg file Person.msg

# Person.msg
string name
uint8 sex
uint8 age

uint8 unknown = 0
uint8 male    = 1
uint8 female  = 2

3.2) Add package dependencies in package.xml

  • <build_depend>message_generation</build_depend>
  • <exec_depend>message_runtime</exec_depend>

3.3) Add compile options in CMakeLists.txt

  • In bracket find_package()
    find_package(... message_generation)
  • Under ## Declare ROS messages, services and actions ##
    add_message_files(FILES Person.msg)
    generate_messages(DEPENDENCIES std_msgs)
  • In bracket catkin_package()
    catkin_package(CATKIN_DEPENDS... message_runtime)

3.4) Compile and generate the language-related files

This would generate Person.h in /devel/include/<pkg_name=learning_topic>/

3.5) Write the person_publisher.cpp and the peraon_subscriber.cpp

3.6) Configure the CMakeLists.txt

Add

  • add_executable(person_publisher src/person_publisher.cpp
  • target_link_libraries(person_publisher ${catkin_LIBRARIES})
  • add_dependencies(person_publisher ${PROJECT_NAME}_generate_messages_cpp)

below ## Build ## tag, and also for person_subscriber

3.7) Build the project

$ cd ~/catkin_ws
$ catkin_make
$ source devel/setup.bash
$ roscore                                   # in sub-window A
$ rosrun learning_topic person_subscriber   # in sub-window B
$ rosrun learning_topic person_publisher    # in sub-window C

4) Write a node that contains both publisher and subscriber

5) About ROS service

6) Write a node that calls ROS service

Learning Service

In this Tutorial we will get familiar with the service mechanism. We will learn to write the node in both Python and C++. We create a new package named learning_service.

7) Write a Client

With the service mechanism we will try to

  • add another turtle into the turtlesim:
  • Request a srv named /spawn, of type turtlesim::Spawn

7.1) Create new package learning_service

$ cd ~/catkin_ws
$ catkin_create_pkg learning_service roscpp rospy std_msgs geometry_msgs turtlesim

7.2) Write the Client

The basic pipeline for a ROS-Client is:

  • Initialize a ROS node;
  • Create a Client object;
ros::service::waitForService("/spawn");  // LOOP BLOCKING
ros::ServiceClient add_turtle = node.serviceClient<turtlesim::Spawn>("/spawn");
  • Request to call a service;
  • Wait for the result of the Server's response.

Before catkin_make:

  • C++
    Don't forget to add the lines below into the CMakeLists.txt to generate exe file.
add_executable(turtle_spawn src/turtle_spawn.cpp)
target_link_libraries(turtle_spawn ${catkin_LIBRARIES})
  • Python
    Don't forget to set the property of .py script as exe.
$ chmod +x turtle_spawn.py

7.3) Compile and run

$ cd ~/catkin_ws
$ catkin_make
$ source devel/setup.bash
$ roscore
$ rosrun turtlesim turtlesim_node
$ rosrun learning_service turtle_spawn      # exe from .cpp
$ rosrun learning_service turtle_spawn.py   # exe from .py

8) Write a Server

With the service mechanism we will try to

  • switch the turtle to move or stay:
  • Request a srv named /turtle_command, of type std_srvs::Trigger

The basic pipeline for defining a ROS-Server is:

  • Initialize a ROS node;
  • Create a Server object;
  • Wait for a service request. Get into the Callback() when getting request;
  • Implement the server functions in the Callback(), return the Response data.

We skip the common steps mentioned before.
Just don't forget to add the lines in CMakeKists.txt for C++, and to chmod for Python before compiling and running.

Compile and run

$ cd ~/catkin_ws
$ catkin_make
$ source devel/setup.bash
$ roscore
$ rosrun turtlesim turtlesim_node
$ rosrun learning_service turtle_command_server
$ rosservice call /turtle_command "{}"  # "{}" can be completed automatically by hitting TAB twice
                                        # "{}" means this service does not need a request. 

9) Customize a Service type.

In the Chapter 8) we have used a pre-defined Service type std_srvs::Trigger.
Now We try to define a service type learning_service::Person basing on our demands.

9.1) Define a .srv file Person.srv

# Person.srv
string name
uint8 sex
uint8 age

uint8 unknown = 0
uint8 male    = 1
uint8 female  = 2
---
string result

Where above the --- is the Request and below --- is the Response.

# .srv
Req
---
Res

9.2) Add the functional package dependence in package.xml

<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>

9.3) Add the compiling options in CMakeLists.txt

  • find_package(... message_generation)
  • add_service_files(FILES Person.srv)
    generate_messages(DEPENDENCIES std_msgs)
  • catkin_package(CATKIN_DEPENDS... message_runtime)

9.4) Compile to generate all the relevant files

This would generate Person.h, PersonRequest.h and PersonResponse.h in /devel/include/<pkg_name=learning_service>/

9.5) Write the Client and the Server

see pipelines in 7.2) for Client and in 8) for Server.

9.6) Configure the CMakeLists.txt

  • add_executable set the to-be-compiled .cppcfile and the to-be-generated .exe file
  • target_link_libraries set the link libs
  • add_dependencies add the dependencies
add_executable(person_server src/person_server.cpp)
target_link_libraries(person_server ${catkin_LIBRARIES})
add_dependencies(person_server ${PROJECT_NAME}_gencpp)

add_executable(person_client src/person_client.cpp)
target_link_libraries(person_client ${catkin_LIBRARIES})
add_dependencies(person_client ${PROJECT_NAME}_gencpp)

9.7) Compile and run

$ cd ~/catkin_ws
$ catkin_make
$ source devel/setup.bash
$ roscore
$ rosrun learning_service person_server
$ rosrun learning_service person_client

Run the Server first:
The Server waits for the Client's request.
Run the Client first:
The Client would hang om, waiting for the Server to be launched.