ROS-新建工作空间、功能包、利用c++、python语言编写发布和订阅通信

1、创建工作空间与功能包

1.1工作空间

1.1.1工作空间的介绍

  • 工作空间是一个存放工程开发相关文件的文件夹。其中包含
    • src:代码空间(用于存放功能包的源代码)
    • build:编译空间(编译过程文件,一般为二进制文件)
    • devel:开发空间
    • install:安装空间

1.1.2创建工作空间

  • 1、创建文件目录存放文件。其中catkin_ws是工作空间的名称,可以改变,但工作空间下面必须有src,不能改变。
mkdir -p ~/catkin_ws/src
  • 2、打开src目录。
cd ~/catkin_ws/src
  • 3、配置好环境变量才能执行catkin_init_worksapce,可以输入catkin_init_worksapce进行尝试。若提示无法需要安装catkin添加环境变量。
echo "source /opt/ros/melodic/setup.bash" >> ~/.bashrc
source ~/.bashrc
  • 4、最后将SRC目录变成空间属性。
catkin_init_worksapce

1.1.3编译工作空间

  • 1、回到工作空间根目录,直接根据SRC目录的makelists文件编译空的工作空间
cd ~/catkin_ws
catkin_make
  • 2、此时已经产生build,devel文件夹。install文件夹需要单独命令进行生成。
catkin_make install
此时产生install文件夹

1.2功能包

1.2.1功能包的介绍

  • 工作空间创建之后可以创建功能包,在一个工作空间可以有多个功能包大部分放在src中。当功能包设计太多是可以根据类型划分多个工作空间。

1.2.1功能包的创建

  • catkin_create_pkg命令
/*
catkin_create_pkg命令会要求你输入package_name,如有需要还可以在后面添加一些需要依赖
的其它软件包:catkin_create_pkg <package_name> [depend1] [depend2] [depend3]
*/

//回到src目录下,创建一个demo的功能包,依赖std_msgs rospy roscpp这几个功能包。
cd ~/catkin_ws/src
catkin_create_pkg demo std_msgs rospy roscpp

/*
此时创建demo文件夹,并在里面生成一下文件夹和文件。
std_msgs是ros一些标准的软件包,如int、bool
rospy可以调用python的接口,进行python编写
roscpp可以调用c++的接口,进行c++编写
*/

1.2.2功能包的编译

  • 功能包的编译和工作空间的编译一样。
//回到工作空间根目录,直接根据SRC目录的makelists文件编译空的工作空间,包括空间下的功能包。
cd ~/catkin_ws
catkin_make

1.2.3功能包中文件的意义

  • include是存放c++的头文件
  • src是存放源代码文件
  • CMakeLists.txt是功能包编译的规则,利用CMAKE语法,编译依赖的功能包、生成可执行文件。
  • package.xml是html语言编译和功能包相关的信息,名称、版本号、描述信息、维护者信息、lincense(开源的许可证)、依赖信息(后期可以修改)

1.2.4设置环境变量

  • 1、首先查看一下环境变量
echo $ROS_PACKAGE_PATH 
/*
结果:
/opt/ros/melodic/share
其中里面并没新建的工作空间的查找的路径,如果没有的话在执行新建的功能包的时候无法进行补全,无法使用roscd等命令。
*/
  • 2、添加工作空间路径
source ~/catkin_ws/devel/setup.bash
  • 3、检测环境变量
echo $ROS_PACKAGE_PATH 
/*
结果:
/home/ubuntu/catkin_ws/src:/opt/ros/melodic/share
*/

2、发布者Publisher的实现

2.1实现的话题模型

  • 主要有两个节点,一个是海龟仿真器、一个是需要实现的Publisher的节点,通过程序实现发布一个话题控制仿真器海龟的移动。
  • Publisher发布一个Message消息类型是geometry_msgs::Twist其中包括线速度和角速度,通过turtle1/cmd_vel话题,然后海龟订阅这个话题,进一步控制仿真器中海龟的位置。

2.2创建功能包并编写代码

  • 1、进入工作空间中src中。
cd ~/catkin_ws/src/
  • 2、创建功能包
$ catkin_create_pkg learning_topic roscpp rospy std_msgs geometry_msgs turtlesim
/*
结果:
rospy std_msgs geometry_msgs turtlesim
Created file learning_topic/package.xml
Created file learning_topic/CMakeLists.txt
Created folder learning_topic/include/learning_topic
Created folder learning_topic/src
Successfully created files in /home/ubuntu/catkin_ws/src/learning_topic. # Please adjust the values in package.xml.
*/
  • 3、进入到新建的功能包。
$ cd ~/catkin_ws/src/learning_topic
/*
里面包含CMakeLists.txt和package.xml文件和 src  include 两个文件夹
*/
  • 4、打开功能包中的src创建cpp文件进行编程。
$ cd src
$ touch velocity_publisher.cpp
$ gedit velocity_publisher.cpp
  • 5、编写内容:
//头文件
#include <ros/ros.h>//相关ros中API的文件,函数定义
#include <geometry_msgs/Twist.h>//线速和角速度的库

//主函数
int main(int argc,char **argv)
{
	//完成节点初始化。velocity_publisher为节点名称
	ros::init(argc,argv,"velocity_publisher");
	//新建节点句柄,管理API的相关资源。
	ros::NodeHandle n;
	//创建publisher,定义一个发布者,节点句柄的advertise<发布的消息类型>(“发布目的的话题名称”,相当于缓存,如果发不出去进行队列存储,若发送速度慢,把旧数据进行清除,保留最新数据)
	//advertise会返回一个ros::Publisher类型的值,利用返回值控制发布消息,发布消息类型不对时拒绝发布
	ros::Publisher turtle_vel_pub = n.advertise<geometry_msgs::Twist>("/turtle1/cmd_vel",10);
	//设置循环频率10hz
	ros::Rate loop_rate(10);
	//进行循环
	while(ros::ok)
	{
		//设置发布的消息类型的初始化及内容
		geometry_msgs::Twist vel_msg;
		vel_msg.linear.x = 0.5;
		vel_msg.angular.z = 0.2;
		
		//发布消息
		turtle_vel_pub.publish(vel_msg);
		//进行打印
		ROS_INFO("Publisher turtle velocity command[%0.2f m/s,%0.2f rad/s]",vel_msg.linear.x,vel_msg.angular.z);
		//进行延时根据设置的频率。
		loop_rate.sleep();
	}
	return 0;
}


/*发布消息总结:

1、初始化ros节点
ros::init(argc,argv,"节点名称");
2、创建节点句柄
ros::NodeHandle n;
3、创建publisher包括发布的消息类型和目的话题及存储大小
ros::Publisher  advertise的返回值= n.advertise<消息类型>("目的话题",队列存储大小);
4、创建消息类型的内容
消息类型初始化及赋值

5、按照一定频率进行发布
ros::Rate loop_rate(10);
while(ros::ok)
{
	advertise的返回值.publish(vel_msg);
	loop_rate.sleep();
}
*/

2.3修改文件并编译

  • 1、修改package.xml。
    • 由于创建功能包时增加了创建的依赖,这里会自动生成,若创建时没有调节依赖或者后面编写程序需要添加其他依赖可以进行修改。
  • 2、修改CMakeLists.txt。添加下面代码
# 将velocity_publisher.cpp编译成velocity_publisher可执行文件
add_executable(velocity_publisher src/velocity_publisher.cpp)
# 可执行文件和ROS的库进行链接
target_link_libraries(velocity_publisher
  ${catkin_LIBRARIES}
)
  • 3、回到工作空间进行编译
$ cd ~/catkin_ws/

2.4运行功能包并查看节点

  • 1、修改环境变量。对用户目录下的.bashrc文件进行修改。
gedit ~/.bashrc
# 打开后添加一下路径
# 第一个应该在安装的时候进行添加的
# 第二条应该在创建工作空间进行添加的。如果都存在就不用添加。
source /opt/ros/melodic/setup.bash
source /home/ubuntu/catkin_ws/devel/setup.bash
# 如果只需要临时添加环境变量可以使用source命令,仅在当前终端有效
# source /home/ubuntu/catkin_ws/devel/setup.bash
  • 2、运行ros系统,和需要的节点
# 创建一个终端运行ros系统
$ roscore
# 再创建一个终端运行海龟的仿真节点
$ rosrun turtlesim turtlesim_node
# 再创建一个终端运行刚刚编写的velocity_publisher节点
$ rosrun learning_topic velocity_publisher
  • 3、现象,海龟根据发送的指令进行移动。
  • 4、查看节点通信状态。
# 再创建一个终端,查看可视化计算图
$ rqt_graph
  • 5、结束出rosout之外的节点,
rosnode kill -a

2.5利用python脚本运行

  • 1、打开功能包创建存放python文件夹和文件,并修改文件权限
$ roscd learning_topic/
$ mkdir scripts
$ cd scripts
$ touch velocity_publisher.py
# 创建后千万记得修改文件权限,否则导致无法编译,找不到节点包
chmod +x velocity_publisher.py
  • 2、编写程序。
$ gedit velocity_publisher.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#确保脚本作为Python脚本执行代码和格式utf-8
import rospy# 利用python必须导入的模块
from geometry_msgs.msg import Twist#需要利用的消息类型的模块

# 定义一个函数
def velocity_publisher():
    # 初始化节点,velocity_publisher作为节点名称,anonymous = True会让名称末尾添加随机数(时间戳),来确保节点具有唯一的名称
    rospy.init_node('velocity_publisher', anonymous=True)
    # /turtle1/cmd_vel是该节点消息类型发布到的话题。Twist该节点发布的消息类型。queue_size在订阅者接收消息的速度不够快的情况下,限制排队的消息数量
    turtle_vel_pub = rospy.Publisher('/turtle1/cmd_vel', Twist, queue_size=10)
    # 速率循环。它的参数是10,即表示希望它每秒循环10次(只要我们的处理时间不超过十分之一秒)!
    rate = rospy.Rate(10) 

    while not rospy.is_shutdown():# 查看is_shutdown()以检查程序是否应该退出(例如有Ctrl+C或其他)
        # 初始化消息类型变量并赋值
        vel_msg = Twist()
        vel_msg.linear.x = 0.5
        vel_msg.angular.z = 0.2

        # 它将一个消息类型的变量发布到目标话题。       
        turtle_vel_pub.publish(vel_msg)
        # loginfo的作用打印消息到屏幕上;把消息写入节点的日志文件中;写入rosout
    	rospy.loginfo("Publsh turtle velocity command[%0.2f m/s, %0.2f rad/s]", vel_msg.linear.x, vel_msg.angular.z)
        # 循环的部分还调用了rate.sleep(),它在循环中可以用刚刚好的睡眠时间维持期望的速率。 
        rate.sleep()

if __name__ == '__main__':
    try:
        #调用函数
        velocity_publisher()
    except rospy.ROSInterruptException:
        pass
  • 4、对工作空间再次编译,对于python可以不需要
$ cd ~/catkin_ws
$ catkin_make
  • 5其运行和c++的基本一样,最后需要调用时使用learning_topic的velocity_publisher.py。
# 若不能运行查找不到,python文件是否修改权限可以被执行
rosrun learning_topic velocity_publisher.py

  • 6、当把python中的节点名不增加时间戳,和c++的名字一样,当两个都需要运行时发现他们会相互把对方挤推出

3、订阅者Subscriber的实现

3.1实现模型

  • 发布者为海龟仿真器,订阅者为需要实现的订阅者,通过/turtle1/pose的节点接收海龟仿真器发送的turtlesim::Pose的消息类型内容。

3.2创建订阅者代码c++

  • 1、打开功能包文件创建文件并编辑
$ cd ~/catkin_ws/src/learning_topic/src
$ touch pose_subscriber.cpp
$ gedit pose_subscriber.cpp

//头文件
#include <ros/ros.h>
#include "turtlesim/Pose.h"

void PoseCallback(const turtlesim::Pose::ConstPtr& msg)
{
    //回调函数不要占用时间太长。
    ROS_INFO("Turtle pose:x:%0.6f,y:%0.6f",msg->x,msg->y);
}
//主函数
int main(int argc,char **argv)
{
    //初始化节点
    ros::init(argc,argv,"posr_subscriber");
    //创建句柄
    ros::NodeHandle n;
    //创建subscribe的订阅者类型,回调函数PoseCallback是当订阅的话题发布时会被调用
    ros::Subscriber pose_sub = n.subscribe("/turtle1/pose",10,PoseCallback);
    //循环等待,不断查看队列,如果有数据就调用上面的调用函数。
    ros::spin();
    //原则上不会执行返回值
    return 0;
}

/*
订阅者:
1、初始化节点ros::init
2、创建句柄ros::NodeHandle
3、回调函数编写PoseCallback(const turtlesim::Pose::ConstPtr& msg)
4、创建订阅者,与ros::spin();配合当有订阅信息调用回调函数
*/
  • 2 修改配置文件
$ gedit ~/catkin_ws/src/learning_topic/CMakeLists.txt
add_executable(pose_subscriber src/pose_subscriber.cpp)
target_link_libraries(pose_subscriber
  ${catkin_LIBRARIES}
)
  • 3运行查看现象
$ roscore
$ rosrun turtlesim turtlesim_node
$ rosrun py_learning_topic py_velocity_publisher.py
$ rosrun learning_topic pose_subscriber

3.3利用python脚本实现

  • 1、打开存放python文件夹和文件,并修改文件权限
$ roscd learning_topic/
$ cd scripts
$ touch pose_subscriber.py
# 创建后千万记得修改文件权限,否则导致无法编译,找不到节点包
chmod +x pose_subscriber.py
  • 2、编写程序。
$ gedit pose_subscriber.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import rospy
from turtlesim.msg import Pose

def poseCallback(msg):
    rospy.loginfo("Turtle pose: x:%0.6f, y:%0.6f", msg.x, msg.y)

def pose_subscriber():
	# ROS节点初始化
    rospy.init_node('pose_subscriber', anonymous=True)
	# 创建一个Subscriber,订阅名为/turtle1/pose的topic,注册回调函数poseCallback
    rospy.Subscriber("/turtle1/pose", Pose, poseCallback)
	# 循环等待回调函数
    rospy.spin()

if __name__ == '__main__':
    pose_subscriber()

  • 4、对工作空间再次编译,对于python可以不需要
$ cd ~/catkin_ws
$ catkin_make
  • 5其运行和c++的基本一样,最后需要调用时使用learning_topic的pose_subscriber.py。
# 若不能运行查找不到,python文件是否修改权限可以被执行
rosrun learning_topic velocity_publisher.py

  • 6、当把python中的节点名不增加时间戳,和c++的名字一样,当两个都需要运行时发现他们会相互把对方挤推出

欢迎关注微信工作号,推送文章更及时。

微信公众号图片

  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值