古月居ROS入门21讲-编程基础(1)

  • Post author:
  • Post category:其他


视频链接:bilibili 搜

古月居


源代码:关注古月居公众号,回复ROS入门21讲



1 创建工作空间和功能包



1.1 工作空间

  1. 工作空间(workspace)是一个存放工程开发相关文件的文件夹,包括:

    src:代码空间,存放功能包代码、配置文件、launch文件等

    build:编译空间,编译过程中产生的中间文件

    devel:开发空间,编译生成的可执行文件、库、脚本等

    install:安装空间,install指令安装的默认文件夹,包括最终生成的可执行文件

  2. 创建工作空间

1.创建工作空间
mkdir -p ~/catkin_ws/src
cd ~/catkin_ws/src
catkin_init_workspace  //将当前文件夹变成ROS工作空间的属性
2.编译工作空间
cd ~/catkin_ws/    //编译时需要造工作空间根目录相当于此处catkin_ws
catkin_make
3.设置环境变量
source devel/setup.bash  //方便系统找到编译生成的可执行文件
4.检查环境变量
echo $ROS_PACKAGE_PATH



1.2 功能包

  1. 创建功能包

    同一个工作空间下,不允许存在同名功能包

    不同工作空间下,允许存在同名功能包
catkin_create_pkg<package_name> [depend1][depend2][depend3]
//后面的depend是指编译时需要依赖ROS中其他的功能包名
1.创建功能包
cd ~/catkin_ws/src
catkin_create_pkg test_pkg std_msgs rospy roscpp
2.编译功能包
cd ~/catkin_ws
catkin_make
source ~/catkin_ws/devel/setup.bash   //添加环境变量

创建生成的功能包下有两个文件夹,以及两个功能包中必须存在的文件:


文件夹



include用于放置头文件;

src用于放功能包代码;


文件



package.xml:包括功能包基本信息,编译和运行功能包所需的依赖信息

cmakelists.txt:描述编译规则以及编译的设置



2 发布者Publisher的编程实现

通过话题的发布与订阅实现小海龟的运动控制



2.1 创建功能包

cd ~/catkin_ws/src
catkin_create_pkg learning_topic roscpp rospy std_msgs geometry_msgs turtlesim 



2.2 创建发布者代码(C++)

cpp文件代码放在创建的功能包对应src目录下



2.2.1 代码

/***********************************************************************
Copyright 2020 GuYueHome (www.guyuehome.com).
***********************************************************************/

/**
 * 该例程将发布turtle1/cmd_vel话题,消息类型geometry_msgs::Twist,该消息用来控制海龟运动
 */
 
#include <ros/ros.h>
#include <geometry_msgs/Twist.h>

int main(int argc, char **argv)
{
	// ROS节点初始化,ROS中节点不能重名
	ros::init(argc, argv, "velocity_publisher");

	// 创建节点句柄,用来管理ROS相关API资源,
	ros::NodeHandle n;

	// 创建一个Publisher,发布名为/turtle1/cmd_vel的topic,消息类型为geometry_msgs::Twist,队列长度10
	ros::Publisher turtle_vel_pub = n.advertise<geometry_msgs::Twist>("/turtle1/cmd_vel", 10);

	// 设置循环的频率
	ros::Rate loop_rate(10);

	// while循环实现:封装数据,发布数据,等待至下一次循环
	int count = 0;
	while (ros::ok())
	{
	    // 初始化geometry_msgs::Twist类型的消息
		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("Publsh turtle velocity command[%0.2f m/s, %0.2f rad/s]", 
				vel_msg.linear.x, vel_msg.angular.z);

	    // 按照循环频率延时
	    loop_rate.sleep();
	}

	return 0;
}



2.2.2 配置CMakeLists.txt中的编译规则

将下面两句话添加到功能包cmakelist.txt文件中对应的build位置下

1.设置需要编译的代码和生成的可执行文件
add_executable(velocity_publisher src/velocity_publisher.cpp)
// 将src/velocity_publisher.cpp代码编译成可执行文件velocity_publisher
2.将可执行文件链接到ROS相关库
target_link_libraries(velocity_publisher ${catkin_LIBRARIES})



2.2.3 编译并运行发布者

1.编译
cd ~/catkin_ws
catkin_make
2.添加路径
source devel/setup.bash
3.终端1
roscore
4.终端2
rosrun turtlesim turtle_node
5.在catkin_ws目录下打开终端3
rosrun learning_topic velocity_publisher

如果想省略输入source devel/setup.bash指令,则打开【主文件夹】,按下【ctrl+h】显示隐藏文件,打开【.bashrc】文件,将【source /home/yao/catkin_ws/devel/setup.bash】(一定要是完整路径)指令添加到bashrc的末端,保存退出,重新启动终端生效。采用该方法时,上述步骤5的终端可以在任意位置打开。



2.3 创建发布者代码(Python)

创建与功能包下src同级文件夹scripts,py文件代码放于此



2.3.1 代码

#!/usr/bin/env python
# -*- coding: utf-8 -*-

########################################################################
####          Copyright 2020 GuYueHome (www.guyuehome.com).          ###
########################################################################

# 该例程将发布turtle1/cmd_vel话题,消息类型geometry_msgs::Twist

import rospy
from geometry_msgs.msg import Twist

def velocity_publisher():
	# ROS节点初始化
    rospy.init_node('velocity_publisher', anonymous=True)

	# 创建一个Publisher,发布名为/turtle1/cmd_vel的topic,消息类型为geometry_msgs::Twist,队列长度10
    turtle_vel_pub = rospy.Publisher('/turtle1/cmd_vel', Twist, queue_size=10)

	#设置循环的频率
    rate = rospy.Rate(10) 

    while not rospy.is_shutdown():
		# 初始化geometry_msgs::Twist类型的消息
        vel_msg = Twist()
        vel_msg.linear.x = 0.5
        vel_msg.angular.z = 0.2

		# 发布消息
        turtle_vel_pub.publish(vel_msg)
    	rospy.loginfo("Publsh turtle velocity command[%0.2f m/s, %0.2f rad/s]", 
				vel_msg.linear.x, vel_msg.angular.z)

		# 按照循环频率延时
        rate.sleep()

if __name__ == '__main__':
    try:
        velocity_publisher()
    except rospy.ROSInterruptException:
        pass

设置py文件属性:右击py文件,选择【属性】,点击【权限】,将【允许作为可执行文件】打勾



2.3.2 运行发布者

1.终端1
roscore
2.终端2
rosrun turtlesim turtle_node
3.在catkin_ws文件所在目录下打开终端3
source devel/setup.bash
rosrun learning_topic velocity_publisher.py



3 订阅者Subscriber的编程实现



3.1 创建订阅者代码(C++)



3.1.1 代码

/***********************************************************************
Copyright 2020 GuYueHome (www.guyuehome.com).
***********************************************************************/

/**
 * 该例程将订阅/turtle1/pose话题,消息类型turtlesim::Pose
 */
 
#include <ros/ros.h>
#include "turtlesim/Pose.h"

// 接收到订阅的消息后,会进入消息回调函数,回调函数不嵌套,需高效运行
// msg以一个常指针的形式指向turtlesim::Pose的所有数据内容
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节点
    ros::init(argc, argv, "pose_subscriber");

    // 创建节点句柄
    ros::NodeHandle n;

    // 创建一个Subscriber,订阅名为/turtle1/pose的topic,注册回调函数poseCallback
    // 此处队列为10,相当于是一个缓冲器
    // 当订阅者发现有/turtle1/pose话题的数据进来时,调用回调函数做处理
    ros::Subscriber pose_sub = n.subscribe("/turtle1/pose", 10, poseCallback);

    // 循环等待回调函数
    //有消息进来时转到回调函数,无消息时spin自身做死循环
    ros::spin();

    return 0;
}



3.1.2 配置订阅者代码编译规则

将下面两句话添加到功能包cmakelist.txt文件中对应的build位置下

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

编译

1.编译
cd ~/catkin_ws
catkin_make
2.添加路径
source devel/setup.bash
3.终端1
roscore
4.终端2
rosrun turtlesim turtle_node
5.在catkin_ws目录下打开终端3
rosrun learning_topic pose_subscriber
6.在catkin_ws目录下打开终端4
source devel/setup.bash
rosrun learning_topic velocity_publisher

当采用【source devel/setup.bash】添加路径时,每次打开终端时都需要先链接路径,才能索引到功能包



3.2 创建订阅者代码(python)



3.2.1 代码

#!/usr/bin/env python
# -*- coding: utf-8 -*-

########################################################################
####          Copyright 2020 GuYueHome (www.guyuehome.com).          ###
########################################################################

# 该例程将订阅/turtle1/pose话题,消息类型turtlesim::Pose

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()



3.2.2 运行订阅者

1.终端1
roscore
2.终端2
rosrun turtlesim turtle_node
3.在catkin_ws文件所在目录下打开终端3
source devel/setup.bash
rosrun learning_topic pose_subscriber.py



4 话题消息的定义与使用

视频第

十二讲第5分钟



4.1 自定义话题消息

  1. 定义msg文件
# 在learning_topic下新建msg文件夹,文件夹内新建Person.msg文件
# 文件内输入:
string name
uint8 sex
uint8 age

uint8 unknown = 0
uint8 male = 1
uint8 female = 2 
  1. 在package.xml中添加功能包依赖

    添加到末尾
<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>
  1. cmakelist添加编译选项
find_package(... message_generation)
add_message_files(FILES Person.msg)
generate_messages(DEPENDENCIES std_mags)
catkin_package(... message_runtime)
  1. 编译
catkin_make



4.2 创建Publisher和Subscriber(C++)

Publisher代码

/***********************************************************************
Copyright 2020 GuYueHome (www.guyuehome.com).
***********************************************************************/

/**
 * 该例程将发布/person_info话题,自定义消息类型learning_topic::Person
 */
 
#include <ros/ros.h>
#include "learning_topic/Person.h"

int main(int argc, char **argv)
{
    // ROS节点初始化
    ros::init(argc, argv, "person_publisher");

    // 创建节点句柄
    ros::NodeHandle n;

    // 创建一个Publisher,发布名为/person_info的topic,消息类型为learning_topic::Person,队列长度10
    ros::Publisher person_info_pub = n.advertise<learning_topic::Person>("/person_info", 10);

    // 设置循环的频率
    ros::Rate loop_rate(1);

    int count = 0;
    while (ros::ok())
    {
        // 初始化learning_topic::Person类型的消息
    	learning_topic::Person person_msg;
		person_msg.name = "Tom";
		person_msg.age  = 18;
		person_msg.sex  = learning_topic::Person::male;
		//采用定义的宏赋值

    // 发布消息
		person_info_pub.publish(person_msg);

    ROS_INFO("Publish Person Info: name:%s  age:%d  sex:%d", 
				  person_msg.name.c_str(), person_msg.age, person_msg.sex);

    // 按照循环频率延时
    loop_rate.sleep();
    }

    return 0;
}

Subscriber代码

/***********************************************************************
Copyright 2020 GuYueHome (www.guyuehome.com).
***********************************************************************/

/**
 * 该例程将订阅/person_info话题,自定义消息类型learning_topic::Person
 */
 
#include <ros/ros.h>
#include "learning_topic/Person.h"
// 自己定义的头文件
// 接收到订阅的消息后,会进入消息回调函数
void personInfoCallback(const learning_topic::Person::ConstPtr& msg)
{
    // 将接收到的消息打印出来
    ROS_INFO("Subcribe Person Info: name:%s  age:%d  sex:%d", 
			 msg->name.c_str(), msg->age, msg->sex);
}

int main(int argc, char **argv)
{
    // 初始化ROS节点
    ros::init(argc, argv, "person_subscriber");

    // 创建节点句柄
    ros::NodeHandle n;

    // 创建一个Subscriber,订阅名为/person_info的topic,注册回调函数personInfoCallback
    ros::Subscriber person_info_sub = n.subscribe("/person_info", 10, personInfoCallback);

    // 循环等待回调函数
    ros::spin();

    return 0;
}

cmakelist.txt添加语句

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

add_executable(person_subscriber src/person_subscriber.cpp)
target_link_libraries(person_subscriber ${catkin_LIBRARIES})
add_dependencies(person_subscriber ${PROJECT_NAME}_generate_messages_cpp)
//用于和自定义生成的头文件进行链接

运行publisher和subscriber

1.打开终端1
roscore
2.catkin_ws下打开终端2
source devel/setup.bash
rosrun learning_topic person_publisher
3.catkin_ws下打开终端3
source devel/setup.bash
rosrun learning_topic person_subscriber



4.3 创建Publisher和Subscriber(Python)

Publisher代码

#!/usr/bin/env python
# -*- coding: utf-8 -*-

########################################################################
####          Copyright 2020 GuYueHome (www.guyuehome.com).          ###
########################################################################

# 该例程将发布/person_info话题,自定义消息类型learning_topic::Person

import rospy
from learning_topic.msg import Person

def velocity_publisher():
	# ROS节点初始化
    rospy.init_node('person_publisher', anonymous=True)

	# 创建一个Publisher,发布名为/person_info的topic,消息类型为learning_topic::Person,队列长度10
    person_info_pub = rospy.Publisher('/person_info', Person, queue_size=10)

	#设置循环的频率
    rate = rospy.Rate(10) 

    while not rospy.is_shutdown():
		# 初始化learning_topic::Person类型的消息
    	person_msg = Person()
    	person_msg.name = "Tom";
    	person_msg.age  = 18;
    	person_msg.sex  = Person.male;

		# 发布消息
        person_info_pub.publish(person_msg)
    	rospy.loginfo("Publsh person message[%s, %d, %d]", 
				person_msg.name, person_msg.age, person_msg.sex)

		# 按照循环频率延时
        rate.sleep()

if __name__ == '__main__':
    try:
        velocity_publisher()
    except rospy.ROSInterruptException:
        pass

Subscriber代码

#!/usr/bin/env python
# -*- coding: utf-8 -*-

########################################################################
####          Copyright 2020 GuYueHome (www.guyuehome.com).          ###
########################################################################

# 该例程将订阅/person_info话题,自定义消息类型learning_topic::Person

import rospy
from learning_topic.msg import Person

def personInfoCallback(msg):
    rospy.loginfo("Subcribe Person Info: name:%s  age:%d  sex:%d", 
			 msg.name, msg.age, msg.sex)

def person_subscriber():
	# ROS节点初始化
    rospy.init_node('person_subscriber', anonymous=True)

	# 创建一个Subscriber,订阅名为/person_info的topic,注册回调函数personInfoCallback
    rospy.Subscriber("/person_info", Person, personInfoCallback)

	# 循环等待回调函数
    rospy.spin()

if __name__ == '__main__':
    person_subscriber()

运行publisher和subscriber

1.打开终端1
roscore
2.catkin_ws下打开终端2
source devel/setup.bash
rosrun learning_topic person_publisher.py
3.catkin_ws下打开终端3
source devel/setup.bash
rosrun learning_topic person_subscriber.py



版权声明:本文为Summer_crown原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。