ROS Tutorial Learning

本文档是为我珍视的女孩准备的ROS入门教程。涵盖了安装ROS、查找包、创建catkin工作空间、构建ROS包、理解ROS节点、话题、服务的基本概念和使用方法。详细讲解了如何创建、运行节点,使用rqt_graph、rostopic、rosnode等工具,以及服务的使用。此外,还介绍了简单的消息和服务创建,以及记录和回放数据。

Preface:This article is written for a nifty girl who I cherish.

在这里插入图片描述

(0)General

(0.0)Attribution

Hardware-Operation system-ROS-Application

(0.1)Description

(1)Beginner Level

(1.0)Basic ROS instructions

#install a distribution
sudo apt-get install ros-<distro>-ros-tutorials
#find a package
#rospack find [package_name]
rospack find roscpp
#cd to a specific ros folder
#roscd <package-or-stack>[/subdir]
roscd roscpp/cmake

(1.0)Create a catkin Package

  • Workspace organized frame
workspace_folder         -- WORKSPACE
  |-src                    -- SOURCE SPACE
    |-CMakeLists.txt        -- The 'toplevel' CMake file
    |-package_1
      |-CMakeLists.txt
      |-package.xml
      ...
    |-package_n
      |-CATKIN_IGNORE       -- Optional empty file to exclude package_n from being processed
      |-CMakeLists.txt
      |-package.xml
      ...
  |-build                  -- BUILD SPACE
    |-CATKIN_IGNORE         -- Keeps catkin from walking this directory
  |-devel                  -- DEVELOPMENT SPACE (set by CATKIN_DEVEL_PREFIX)
    |-bin
    |-etc
    |-include
    |-lib
    |-share
    |-.catkin
    |-env.bash
    |-setup.bash
    |-setup.sh
    ...
  |-install                -- INSTALL SPACE (set by CMAKE_INSTALL_PREFIX)
    |-bin
    |-etc
    |-include
    |-lib
    |-share
    |-.catkin             
    |-env.bash
    |-setup.bash
    |-setup.sh
    ...
  • Package organized frame
my_package
  |-CMakeLists.txt
  |-package.xml
  • Basic Instructions
#create a workspace
mkdir -p catkin_ws/src
cd catkin_ws
catkin_make
#create a package
# catkin_create_pkg <package_name> [depend1] [depend2] [depend3]
cd src
catkin_create_pkg beginner_tutorials std_msgs rospy roscpp
#add the workspace to your ROS environment
cd ../devel
. setup.bash
#inspect the dirct dependancies of a package, and these dependancies were declared in package.xml
rospack depends1 beginner_tutorials
#inspect the indirct dependancies of a package
rospack depends1 rospy
#inspect all indirct dependancies of a package
rospack depends beginner_tutorials
  • Customizing the package
    One can customize either the ‘package.xml’ by editing ‘description tag’ ,‘maintainer tags’,‘license tags’ and ‘dependencies tags’ or the ‘CMakeLists.txt’ by add some CMake rules.

(1.1)Build a ROS package

  • Basic instructions
#append source to environment if you didn't conduct
# For melodic for instance
source /opt/ros/melodic/setup.bash             
# In a catkin workspace, catkin_make is a junction of cmake and make, one performs in a folder containning 'src' folder
catkin_make
catkin_make install  # (optionally)
#Source files in a different folder
catkin_make --source my_src
catkin_make install --source my_src  # (optionally)

(1.2)Understanding ROS Nodes

  • General
    Introduces ROS graph concepts and discusses the use of roscore, rosnode, and rosrun commandline tools.
  • ROS graph system
#Nodes: A node is an executable that uses ROS to communicate with other nodes.
#Messages: ROS data type used when subscribing or publishing to a topic.
#Topics: Nodes can publish messages to a topic as well as subscribe to a topic to receive messages.
#Master: Name service for ROS (i.e. helps nodes find each other)
#rosout: ROS equivalent of stdout/stderr
#roscore: Master + rosout + parameter server (parameter server will be introduced later) 
  • Basic instructions
#install a light simulator
# For melodic for instance
sudo apt-get install ros-melodic-ros-tutorials
#enable a roscore service at very first
roscore
#open a new terminal and type to see what running roscore did
rosnode list
#see additional information about a node
rosnode info /rosout
#rosrun, one can directly run a node within a package (without having to know the package path).
#rosrun [package_name] [node_name] 
#for example
rosrun turtlesim turtlesim_node
#or one can boringly run with changed name
rosrun turtlesim turtlesim_node __name:=my_turtle
#ping with rosnode
rosnode ping my_turtle

(1.3)The black box of ROS topics

  • General
    The turtlesim_node and the turtle_teleop_key node are communicating with each other over a ROS Topic. turtle_teleop_key is publishing the key strokes on a topic, while turtlesim subscribes to the same topic to receive the key strokes. Let’s use ‘rqt_graph’ which shows the nodes and topics currently running.
  • Basic instructions
#	install rqt_graph
# For melodic for instance
sudo apt-get install ros-melodic-rqt
sudo apt-get install ros-melodic-rqt-common-plugins
# type to see relation
rosrun rqt_graph rqt_graph
#The rostopic tool allows you to get information about ROS topics.
#seek for help comments
rostopic -h
#echo message
rostopic echo /turtle1/cmd_vel
#This displays a verbose list of topics to publish to and subscribe to and their type. 
rostopic list -v
#View the message type of communication
rostopic type /turtle1/cmd_vel
#messege detail
rosmsg show geometry_msgs/Twist
#send message with command
#rostopic pub [topic] [msg_type] [args]
rostopic pub -1 /turtle1/cmd_vel geometry_msgs/Twist -- '[2.0, 0.0, 0.0]' '[0.0, 0.0, 1.8]'
#-1:only send 1 message
#/turtle1/cmd_vel:name of topic
#geometry_msgs/Twist:This is the message type to use when publishing to the topic
#[2.0, 0.0, 0.0]' '[0.0, 0.0, 1.8]:linear and angula
#endless moving
rostopic pub /turtle1/cmd_vel geometry_msgs/Twist -r 1 -- '[2.0, 0.0, 0.0]' '[0.0, 0.0, -1.8]'
#Using rostopic hz
#see control rate, rostopic hz [topic]
rostopic hz /turtle1/pose
#Using rqt_plot
#open plot,type  /turtle1/pose/x in the blank to see the plot
rosrun rqt_plot rqt_plot

(1.4)ROS Services and Parameters

  • General
    Services are another way that nodes can communicate with each other. Services allow nodes to send a request and receive a response.
  • Service usage list
rosservice list         print information about active services
rosservice call         call the service with the provided args
rosservice type         print service type
rosservice find         find services by service type
rosservice uri          print service ROSRPC uri

(1.5)Creating a ROS msg and srv

Click to view

(1.6)Writing a Simple publisher and subscriber (C++), And compile them

  • First you have to create 2 packages named like beginner_tutorials and beginner_tutorials2 with:
catkin_create_pkg beginner_tutorials std_msgs rospy roscpp
  • mkdir msg in beginner_tutorials and touch an empty file named Num.msg, and mkdir srv in beginner_tutorials and touch an empty file named AddTwoInts.srv. Similarly, perform the same instructions in package beginner_tutorials2.
  • then in beginner_tutorials
touch main.cpp
gedit main.cpp

filling with

#include "ros/ros.h"
#include "std_msgs/String.h"
#include <sstream>
/**
 * This tutorial demonstrates simple sending of messages over the ROS system.
 */
int main(int argc, char **argv)
{
  /**
   * The ros::init() function needs to see argc and argv so that it can perform
   * any ROS arguments and name remapping that were provided at the command line.
   * For programmatic remappings you can use a different version of init() which takes
   * remappings directly, but for most command-line programs, passing argc and argv is
   * the easiest way to do it.  The third argument to init() is the name of the node.
   *
   * You must call one of the versions of ros::init() before using any other
   * part of the ROS system.
   */
  ros::init(argc, argv, "talker");

  /**
   * NodeHandle is the main access point to communications with the ROS system.
   * The first NodeHandle constructed will fully initialize this node, and the last
   * NodeHandle destructed will close down the node.
   */
  ros::NodeHandle n;

  /**
   * The advertise() function is how you tell ROS that you want to
   * publish on a given topic name. This invokes a call to the ROS
   * master node, which keeps a registry of who is publishing and who
   * is subscribing. After this advertise() call is made, the master
   * node will notify anyone who is trying to subscribe to this topic name,
   * and they will in turn negotiate a peer-to-peer connection with this
   * node.  advertise() returns a Publisher object which allows you to
   * publish messages on that topic through a call to publish().  Once
   * all copies of the returned Publisher object are destroyed, the topic
   * will be automatically unadvertised.
   *
   * The second parameter to advertise() is the size of the message queue
   * used for publishing messages.  If messages are published more quickly
   * than we can send them, the number here specifies how many messages to
   * buffer up before throwing some away.
   */
  ros::Publisher chatter_pub = n.advertise<std_msgs::String>("chatter", 1000);

  ros::Rate loop_rate(10);

  /**
   * A count of how many messages we have sent. This is used to create
   * a unique string for each message.
   */
  int count = 0;
  while (ros::ok())
  {
    /**
     * This is a message object. You stuff it with data, and then publish it.
     */
    std_msgs::String msg;

    std::stringstream ss;
    ss << "hello world " << count;
    msg.data = ss.str();

    ROS_INFO("%s", msg.data.c_str());

    /**
     * The publish() function is how you send messages. The parameter
     * is the message object. The type of this object must agree with the type
     * given as a template parameter to the advertise<>() call, as was done
     * in the constructor above.
     */
    chatter_pub.publish(msg);

    ros::spinOnce();

    loop_rate.sleep();
    ++count;
  }
  return 0;
}

editing CMakefiles with:

cmake_minimum_required(VERSION 2.8.3)
project(beginner_tutorials)
## Find catkin and any catkin packages
find_package(catkin REQUIRED COMPONENTS roscpp rospy std_msgs genmsg)
## Declare ROS messages and services
add_message_files(DIRECTORY msg FILES Num.msg)
add_service_files(DIRECTORY srv FILES AddTwoInts.srv)
## Generate added messages and services
generate_messages(DEPENDENCIES std_msgs)
## Declare a catkin package
catkin_package()
#specify the c++ standard
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
add_executable(beginner_tutorials src/main.cpp)
target_link_libraries(beginner_tutorials ${catkin_LIBRARIES})
add_dependencies(beginner_tutorials beginner_tutorials_generate_messages_cpp)
include_directories(include ${catkin_INCLUDE_DIRS} )
  • then in beginner_tutorials2
touch main.cpp
gedit main.cpp

filling main.cpp with:

#include "ros/ros.h"
#include "std_msgs/String.h"
/**
 * This tutorial demonstrates simple receipt of messages over the ROS system.
 */
void chatterCallback(const std_msgs::String::ConstPtr& msg)
{
  ROS_INFO("I heard: [%s]", msg->data.c_str());
}

int main(int argc, char **argv)
{
  /**
   * The ros::init() function needs to see argc and argv so that it can perform
   * any ROS arguments and name remapping that were provided at the command line.
   * For programmatic remappings you can use a different version of init() which takes
   * remappings directly, but for most command-line programs, passing argc and argv is
   * the easiest way to do it.  The third argument to init() is the name of the node.
   *
   * You must call one of the versions of ros::init() before using any other
   * part of the ROS system.
   */
  ros::init(argc, argv, "listener");

  /**
   * NodeHandle is the main access point to communications with the ROS system.
   * The first NodeHandle constructed will fully initialize this node, and the last
   * NodeHandle destructed will close down the node.
   */
  ros::NodeHandle n;

  /**
   * The subscribe() call is how you tell ROS that you want to receive messages
   * on a given topic.  This invokes a call to the ROS
   * master node, which keeps a registry of who is publishing and who
   * is subscribing.  Messages are passed to a callback function, here
   * called chatterCallback.  subscribe() returns a Subscriber object that you
   * must hold on to until you want to unsubscribe.  When all copies of the Subscriber
   * object go out of scope, this callback will automatically be unsubscribed from
   * this topic.
   *
   * The second parameter to the subscribe() function is the size of the message
   * queue.  If messages are arriving faster than they are being processed, this
   * is the number of messages that will be buffered up before beginning to throw
   * away the oldest ones.
   */
  ros::Subscriber sub = n.subscribe("chatter", 1000, chatterCallback);

  /**
   * ros::spin() will enter a loop, pumping callbacks.  With this version, all
   * callbacks will be called from within this thread (the main one).  ros::spin()
   * will exit when Ctrl-C is pressed, or the node is shutdown by the master.
   */
  ros::spin();

  return 0;
}

editing CMakeLists.txt with:

cmake_minimum_required(VERSION 2.8.3)
project(beginner_tutorials2)

## Find catkin and any catkin packages
find_package(catkin REQUIRED COMPONENTS roscpp rospy std_msgs genmsg)

## Declare ROS messages and services
add_message_files(DIRECTORY msg FILES Num.msg)
add_service_files(DIRECTORY srv FILES AddTwoInts.srv)

## Generate added messages and services
generate_messages(DEPENDENCIES std_msgs)

## Declare a catkin package
catkin_package()
#specify the c++ standard
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
add_executable(beginner_tutorials2 src/main.cpp)
target_link_libraries(beginner_tutorials2 ${catkin_LIBRARIES})
add_dependencies(beginner_tutorials2 beginner_tutorials2_generate_messages_cpp)
include_directories(include ${catkin_INCLUDE_DIRS} )
  • compile
#cd to workspace root foleder
roscore
#new a terminal in the same place
source ./devel/setup.bash
rosrun beginner_tutorials beginner_tutorials
#new a terminal in the same place
source ./devel/setup.bash
rosrun beginner_tutorials2 beginner_tutorials2

(1.7)Writing a Simple publisher and subscriber (python), And compile them

  • basic
#create package first
cd src
mkdir scripts
touch scripts/main.py
  • CMakeLists.txt
#append at last line of this file
catkin_install_python(PROGRAMS scripts/main.py 
  DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)

(1.8)Writing a Simple Service and Client , And compile them

click to view

  • remember to edit the AddTwoInts.srv file in beginner_tutorials package

  • run with

rosrun beginner_tutorials add_two_ints_server     #(C++)
rosrun beginner_tutorials add_two_ints_server.py  #(Python) 
rosrun beginner_tutorials add_two_ints_client 1 3     #(C++)
rosrun beginner_tutorials add_two_ints_client.py 1 3  #(Python) 

(1.9)Recording and playing back data

roscore
#new terminal
rosrun turtlesim turtlesim_node
#new terminal
rosrun turtlesim turtle_teleop_key
#new terminal and a specific folder
mkdir bagfiles
cd bagfiles
#start record, use ctrl+c to end record
rosbag record -a
#show info information
rosbag info <your bagfile>
#run
rosbag play <your bagfile>
#and one can also run 2 times fast,or just record 1 pose

(1)Intermediate Level

机器人操作系统 ROS(机器人操作系统,Robot Operating System),是专为机器人软件开发所设计出来的一套电脑操作系统架构。它是一个开源的元级操作系统(后操作系统),提供类似于操作系统的服务,包括硬件抽象描述、底层驱动程序管理、共用功能的执行、程序间消息传递、程序发行包管理,它也提供一些工具和库用于获取、建立、编写和执行多机融合的程序。 ROS的运行架构是一种使用ROS通信模块实现模块间P2P的松耦合的网络连接的处理架构,它执行若干种类型的通讯,包括基于服务的同步RPC(远程过程调用)通讯、基于Topic的异步数据流通讯,还有参数服务器上的数据存储。 1 发展目标 2 ROS的概念 2.1 ROS 的 Filesystem Level 2.2 ROS 的 Computation Graph Level 3 参考文献 4 外部链接 发展目标 ROS的首要设计目标是在机器人研发领域提高代码复用率。ROS是一种分布式处理框架(又名Nodes)。这使可执行文件能被单独设计,并且在运行时松散耦合。这些过程可以封装到数据包(Packages)和堆栈(Stacks)中,以便于共享和分发。ROS还支持代码库的联合系统。使得协作亦能被分发。这种从文件系统级别到社区一级的设计让独立地决定发展和实施工作成为可能。上述所有功能都能由ROS的基础工具实现。 为了实现“共享与协作”这一首要目标,人们制订了ROS架构中的其他支援性目标: “轻便”:ROS是设计得尽可能方便简易。您不必替换主框架与系统,因为ROS编写的代码可以用于其他机器人软件框架中。毫无疑问的,ROS更易于集成与其他机器人软件框架。事实上ROS已完成与OpenRAVE、Orocos和Player的整合。 ROS-agnostic库:【agnostic:不可知论】建议的开发模型是使用clear的函数接口书写ROS-agnostic库。 语言独立性:ROS框架很容易在任何编程语言中执行。我们已经能在Python和C++中顺利运行,同时添加有Lisp、Octave和Java语言库。 测试简单:ROS有一个内建的单元/组合集测试框架,称为“rostest”。这使得集成调试和分解调试很容易。 扩展性:ROS适合于大型实时系统与大型的系统开发项目。 ROS的概念 ROS有三个层次的概念:分别为Filesystem level,Computation graph level, 以及Communication level。 以下内容具体的总结了这些层次及概念。除了这三个层次的概念, ROS也定义了两种名称-- Package资源名称和Graph资源名称。同样会在以下内容中提及。 ROS 的 Filesystem Level 文件系统层概念就是你在碟片里面遇到的资源,例如: Packages:ROS的基本组织,可以包含任意格式文件。一个Package 可以包含ROS执行时处理的文件(nodes),一个ROS的依赖库,一个数据集合,配置文件或一些有用的文件在一起。 Manifests:Manifests (manifest.xml) 提供关于Package元数据,包括它的许可信息和Package之间依赖关系,以及语言特性信息像编译旗帜(编译优化参数)。 Stacks: Stacks 是Packages的集合,它提供一个完整的功能,像“navigation stack” Stack与版本号关联,同时也是如何发行ROS软件方式的关键。 Manifest Stack Manifests: Stack manifests (stack.xml) 提供关于Stack元数据,包括它的许可信息和Stack之间依赖关系。 Message (msg) types: 信息描述, 位置在路径:my_package/msg/MyMessageType.msg, 定义数据类型在ROS的 messages ROS里面。 Service (srv) types: 服务描述,位置在路径:my_package/srv/MyServiceType.srv, 定义这个请求和相应的数据结构 在ROS services 里面。 ROS 的 Computation Graph Level Computation Graph Level(计算图)就是用ROS的P2P(peer-to-peer网络传输协议)网络集中处理所有的数据。基本的Computation Graph的概念包括Node, Master, Parameter Sever,messages, services, topics, 和bags, 以上所有的这些都以不同的方式给Graph传输数据。 Nodes: Nodes(节点)是一系列运行中的程序。ROS被设计成在一定颗粒度下的模块化系统。一个机器人控制系统通常包含许多Nodes。比如一个Node控制激光雷达,一个Node控制车轮马达,一个Node处理定位,一个Node执行路径规划,另外一个提供图形化界面等等。一个ROS节点是由Libraries ROS client library写成的, 例如 roscpp 和 rospy. Master: ROS Master 提供了登记列表和对其他计算图的查找。没有Master,节点将无法找到其他节点,交换消息或调用服务。 Server Parameter Server: 参数服务器使数据按照钥匙的方式存储。目前,参数服务器是主持的组成部分。 Messages:节点之间通过messages来传递消息。一个message是一个简单的数据结构,包含一些归类定义的区。支持标准的原始数据类型(整数、浮点数、布尔数,等)和原始数组类型。message可以包含任意的嵌套结构和数组(很类似于C语言的结构structs) Topics: Messages以一种发布/订阅的方式传递。一个node可以在一个给定的topic中发布消息。Topic是一个name被用于描述消息内容。一个node针对某个topic关注与订阅特定类型的数据。可能同时有多个node发布或者订阅同一个topic的消息;也可能有一个topic同时发布或订阅多个topic。总体上,发布者和订阅者不了解彼此的存在。主要的概念在于将信息的发布者和需求者解耦、分离。逻辑上,topic可以看作是一个严格规范化的消息bus。每个bus有一个名字,每个node都可以连接到bus发送和接受符合标准类型的消息。 Services:发布/订阅模型是很灵活的通讯模式,但是多对多,单向传输对于分布式系统中经常需要的“请求/回应”式的交互来说并不合适。因此,“请求/回应” 是通过services来实现的。这种通讯的定义是一种成对的消息:一个用于请求,一个用于回应。假设一个节点提供了一个服务提供下一个name和客户使用服务发送请求消息并等待答复。ROS的客户库通常以一种远程调用的方式提供这样的交互。 Bags: Bags是一种格式,用于存储和播放ROS消息。对于储存数据来说Bags是一种很重要的机制。例如传感器数据很难收集但却是开发与测试中必须的。 在ROS的计算图中,ROS的Master以一个name service的方式工作。它给ROS的节点存储了topics和service的注册信息。Nodes 与Master通信从而报告它们的注册信息。当这些节点与master通信的时候,它们可以接收关于其他以注册节点的信息并且建立与其它以注册节点之间的联系。当这些注册信息改变时Master也会回馈这些节点,同时允许节点动态创建与新节点之间的连接。 节点之间的连接是直接的; Master仅仅提供了查询信息,就像一个DNS服务器。节点订阅一个topic将会要求建立一个与发布该topics的节点的连接,并且将会在同意连接协议的基础上建立该连接。ROS里面使用最广的连接协议是TCPROS,这个协议使用标准的TCP/IP 接口。 这样的架构允许脱钩工作(decoupled operation),通过这种方式大型或是更为复杂的系统得以建立,其中names方式是一种行之有效的手段。names方式在ROS系统中扮演极为重要的角色: topics, services, and parameters 都有各自的names。每一个ROS客户端库都支持重命名,这等同于,每一个编译成功的程序能够以另一种形似【名字】运行。 例如,为了控制一个北阳激光测距仪(Hokuyo laser range-finder),我们可以启动这个hokuyo_node 驱动,这个驱动可以给与激光仪进行对话并且在"扫描"topic下可以发布sensor_msgs/LaserScan 的信息。为了处理数据,我们也许会写一个使用laser_filters的node来订阅"扫描"topic的信息。订阅之后,我们的过滤器将会自动开始接收激光仪的信息。 注意两边是如何脱钩工作的。 所有的hokuyo_node的节点都会完成发布"扫描",不需要知道是否有节点被订阅了。所有的过滤器都会完成"扫描"的订阅,不论知道还是不知道是否有节点在发布"扫描"。 在不引发任何错误的情况下,这两个nodes可以任何的顺序启动,终止,或者重启。 以后我们也许会给我们的机器人加入另外一个激光器,这会导致我们重新设置我们的系统。我们所需要做的就是重新映射已经使用过的names。当我们开始我们的第一个hokuyo_node时,我们可以说它用base_scan代替了映射扫描,并且和我们的过滤器节点做相同的事。现在,这些节点将会用base_scan的topic来通信从而代替,并且将不再监听"扫描"topic的信息。然后我们就可以为我们的新激光测距仪启动另外一个hokuyo_node。 参考文献 http://www.ros.org/wiki/ros http://bbs.axnzero.com/index.php http://blog.sina.com.cn/digital2image2processing
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值