ubuntu16.0+ROS+入门

1、创建工作空间

$ mkdir -p workspace/src
$ cd workspace
$ catkin_make
$ source devel/setup.bash
$ echo $ROS_PACKAGE_PATH
包含刚刚创建的目录 /home/xiao/workspace/src

2、Package程序包的文件结构

workspace/build
devel
src / CMakeLists.txt #package的编译规则(创建工作空间时建立)
package.xml #package的描述信息
src/ #源代码文件
include/ #c++头文件
scripts/ #可执行脚本
msg/ #自定义消息
srv/ #自定义服务
models/ #3D模型文件
urdf/ #urdf文件
launch/ #launch文件

3、创建Package ROS程序包

包一定要在工作空间src文件夹内建立;
xiao@xiao:~/workspace/src$ catkin_create_pkg beginner_tutorials std_msgs rospy roscpp
xiao@xiao:~/workspace/src$ cd … #返回上一级-工作空间
xiao@xiao:~/workspace$ catkin_make #重新编译
如果还想编译一次: catkin_make --force-cmake
将看如下显示:
– +++ processing catkin package: ‘beginner_tutorials’
– ==> add_subdirectory(beginner_tutorials)

4、ROS节点操作

rosrun [package_name] [node_name]
例:rosrun turtlesim turtlesim_node

rosnode命令的详细作用列表如下:
rosnode命令 作用
rosnode list 列出当前运行的node信息
rosnode info node_name 显示出node的详细信息
rosnode kill node_name 结束某个node
rosnode ping node_name 测试连接节点
rosnode machine 列出在特定机器或列表机器上运行的节点
rosnode cleanup 清除不可到达节点的注册信息
或rosnode help
Commands:
rosnode ping test connectivity to node
rosnode list list active nodes
rosnode info print information about node
rosnode machine list nodes running on a particular machine or list machines
rosnode kill kill a running node
rosnode cleanup purge registration information of unreachable nodes

5、topic操作

我们应该熟悉topic的几种使用命令,下表详细的列出了各自的命令及其作用。
命令 作用
rostopic list 列出当前所有的topic
rostopic info topic_name 显示某个topic的属性信息
rostopic echo topic_name 显示某个topic的内容
rostopic pub topic_name … 向某个topic发布内容
rostopic bw topic_name 查看某个topic的带宽
rostopic hz topic_name 查看某个topic的频率
rostopic find topic_type 查找某个类型的topic
rostopic type topic_name 查看某个topic的类型(msg)

6、service操作

在实际应用中,service通信方式的命令时 rosservice,具体的命令参数如下表:
rosservice 命令 作用
rosservice list 显示服务列表
rosservice info 打印服务信息
rosservice type 打印服务类型
rosservice uri 打印服务ROSRPC uri
rosservice find 按服务类型查找服务
rosservice call 使用所提供的args调用服务
rosservice args 打印服务参数
我们对比一下这两种最常用的通信方式,加深我们对两者的理解和认识,具体见下表:
名称 Topic Service
通信方式 异步通信 同步通信
实现原理 TCP/IP TCP/IP
通信模型 Publish-Subscribe Request-Reply
映射关系 Publish-Subscribe(多对多) Request-Reply(多对一)
特点 接受者收到数据会回调(Callback) 远程过程调用(RPC)服务器端的服务
应用场景 连续、高频的数据发布 偶尔使用的功能/具体的任务
举例 激光雷达、里程计发布数据 开关传感器、拍照、逆解计算

7、msg的结构与数据类型

基本的msg包括bool、int8、int16、int32、int64(以及uint)、float、float64、string、time、duration、header、可变长数组array[]、固定长度数组array[C]。那么具体的一个msg是怎么组成的呢?我们用一个具体的msg来了解,例如上例中的msg sensor_msg/image,位置存放在sensor_msgs/msg/image.msg里,它的结构如下:
std_msg/Header header
uint32 seq
time stamp
string frame_id
uint32 height
uint32 width
string encoding
uint8 is_bigendian
uint32 step
uint8[] data

8、rqt

rqt_graph
rqt_graph是来显示通信架构,也就是内容节点、主题等等,当前有哪些
Node和topic在运行,消息的流向是怎样,都能通过这个语句显示出来。此命令由于能显示系
统的全貌,所以非常的常用。
rqt_plot
rqt_plot将一些参数,尤其是动态参数以曲线的形式绘制出来。当我们在开发时查看机器人的
原始数据,我们就能利用rqt_plot将这些原始数据用曲线绘制出来,非常的直观,利于我们分
析数据。
rqt_console
rqt_console里存在一些过滤器,我们可以利用它方便的查到我们需要的日志。

rosrun rqt_graph rqt_graph
rosrun rqt_topic rqt_topic
rosrun rqt_plot rqt_plot
rosrun rqt_publisher rqt_publisher
rosrun rqt_console rqt_console
rosrun rqt_logger_level rqt_logger_level

9、例子

例:
topic_demo/msg/gps.msg
string state #工作状态
float32 x #x坐标
float32 y #y坐标
以上就定义了一个gps类型的消息,你可以把它理解成一个C语言中的结构体,类似于
struct gps
{
string state;
float32 x;
float32 y;
}

查看package.xml, 确保它包含一下两条语句:
message_generation
message_runtime

打开CMakeLists.txt文件
find_package(catkin REQUIRED COMPONENTS
roscpp
rospy
std_msgs
message_generation)

catkin_package(

CATKIN_DEPENDS message_runtime
…)

add_message_files(
FILES
gps.msg
)

generate_messages(
DEPENDENCIES
std_msgs
)

include_directories(include ${catkin_INCLUDE_DIRS})

add_executable(talker src/talker.cpp)
target_link_libraries(talker ${catkin_LIBRARIES})
add_executable(listener src/listener.cpp)
target_link_libraries(listener ${catkin_LIBRARIES})

add_executable(add_two_ints_server src/add_two_ints_server.cpp)
target_link_libraries(add_two_ints_server ${catkin_LIBRARIES})
add_dependencies(add_two_ints_server beginner_tutorials_gencpp)

add_executable(add_two_ints_client src/add_two_ints_client.cpp)
target_link_libraries(add_two_ints_client ${catkin_LIBRARIES})
add_dependencies(add_two_ints_client beginner_tutorials_gencpp)

要在代码中使用自定义消息类型,只要 #include ,然后声明,按照对结
构体操作的方式修改内容即可。
topic_demo::gps mygpsmsg;
mygpsmsg.x = 1.6;
mygpsmsg.y = 5.5;
mygpsmsg.state = “working”;

创建 service_demo/Greeting.srv文件,内容包括:
string name #短横线上边部分是服务请求的数据
int32 age
— #短横线下面是服务回传的内容。
string feedback
srv格式的文件创建后,也需要修改 CMakeLissts.txt,在其中加入
add_service_files(
FILES Greeting.srv
)
其余与添加msg的改动一样。然后进行 catkin_make ,系统就会生成在代码中可用的Greeting
类型。在代码中使用,只需要 #include ,然后即可创建该类型的srv。
service_demo::Greeting grt; //grt分为grt.request和grt.response两部分
grt.request.name = “HAN”; //不能用grt.name或者grt.age来访问
grt.request.age = “20”;

新生成的Greeting类型的服务,其结构体的风格更为明显,可以这么理解,一个Greeting服务
结构体中嵌套了两个结构体,分别是请求和响应:
struct Greeting
{
struct Request
{
string name;
int age;
}request;

struct Response
{
string feedback;
}response;
}

10 时钟

Time与Duration
ROS里经常用到的一个功能就是时钟,比如计算机器人移动距离、设定一些程序的
等待时间、设定计时器等等。roscpp同样给我们提供了时钟方面的操作。
具体来说,roscpp里有两种时间的表示方法,一种是时刻(ros::Time),一种是时长
(ros::Duration)。无论是Time还是Duration都具有相同的表示方法:
···
int32 sec
int32 nsec
···
Time/Duration都由秒和纳秒组成。
要使用Time和Duration,需要 #include 和#include
ros::Time begin = ros::Time::now(); //获取当前时间
ros::Time at_some_time1(5,20000000); //5.2s
ros::Time at_some_time2(5.2); //同上,重载了float类型和两个uint类型的构造函数
ros::Duration one_hour(60*60,0); //1h
double secs1 = at_some_time1.toSec();//将Time转为double型时间
double secs2 = one_hour.toSec();//将Duration转为double型时间
Time和Duration表示的概念并不相同,Time指的是某个时刻,而Duration指的是某个时段,尽
管他们的数据结构都相同,但是用在不同的场景下。
ROS为我们重载了Time、Duration类型
之间的加减运算,比如:
ros::Time t1 = ros::Time::now() - ros::Duration(5.5); //t1是5.5s前的时刻,Time加减Duratio
n返回都是Time
ros::Time t2 = ros::Time::now() + ros::Duration(3.3);//t2是当前时刻往后推3.3s的时刻
ros::Duration d1 = t2 - t1;//从t1到t2的时长,两个Time相减返回Duration类型
ros::Duration d2 = d1 - ros::Duration(0,300);//两个Duration相减,还是Duration
以上是Time、Duration之间的加减运算,要注意没有Time+Time的做法。

通常在机器人任务执行中可能有需要等待的场景,这时就要用到sleep功能,roscpp中提供了
两种sleep的方法:

ros::Duration(0.5).sleep(); //用Duration对象的sleep方法休眠
ros::Rate r(10); //10HZ
while(ros::ok())
{
r.sleep();//定义好sleep的频率,Rate对象会自动让整个循环以10hz休眠,即使有任务执行占用了时间
}

Timer
Rate的功能是指定一个频率,让某些动作按照这个频率来循环执行。与之类似的是ROS中的
定时器Timer,它是通过设定回调函数和触发时间来实现某些动作的反复执行,创建方法和
topic中的subscriber很像。
void callback1(const ros::TimerEvent&)
{
ROS_INFO(“Callback 1 triggered”);
}
void callback2(const ros::TimerEvent&)
{
ROS_INFO(“Callback 2 triggered”);
}
int main(int argc,char **argv)
{
ros::init(argc,argv,“talker”);
ros::NodeHandle n;
ros::Timer timer1 = n.createTimer(ros::Duration(0.1),callback1);
//timer1每0.1s触发一次callback1函数
ros::Timer timer2 = n.createTimer(ros::Duration(1.0),callback2);
//timer2每1.0s触发一次callback2函数
ros::spin(); //千万别忘了spin,只有spin了才能真正去触发回调函数
return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_41536025/article/details/85565190