引言
ROS(Robot Operating System,机器人操作系统)是一个开源的机器人软件平台,它为机器人开发者提供了一个强大的工具集,用于构建复杂机器人系统。对于新手来说,ROS的学习曲线可能相对陡峭,但通过本教程,我们将一步步带你轻松掌握ROS的基本操作技巧。
第一部分:ROS基础
1.1 ROS简介
ROS是一个由 Willow Garage 开发,后来被 Open Source Robotics Foundation(OSRF)维护的开源机器人软件平台。它为机器人开发者提供了一个标准化的框架,用于开发、测试和部署机器人应用程序。
1.2 ROS架构
ROS采用分布式架构,它由节点(Nodes)、话题(Topics)、服务(Services)、动作(Actions)和参数服务器(Parameter Server)等核心组件组成。
1.3 安装ROS
安装ROS是开始学习的第一步。以下是在Ubuntu上安装ROS Noetic(最新稳定版)的步骤:
sudo sh -c 'echo "deb http://deb.ros.org/noetic main" > /etc/apt/sources.list.d/ros-noetic.list'
sudo apt-key adv --keyserver 'hkp://keyserver.ubuntu.com:80' --recv-key C1CF6E31E6BADE8868B172B4F42ED6FBAB17C654
sudo apt update
sudo apt install ros-noetic-ros-base
1.4 启动ROS
安装完成后,启动ROS:
roscore
第二部分:ROS工作空间
2.1 创建工作空间
工作空间是存放ROS项目文件的地方。创建工作空间的命令如下:
mkdir -p ~/catkin_ws/src
cd ~/catkin_ws/
catkin_make
2.2 编写CMakeLists.txt
在src目录下创建一个名为CMakeLists.txt的文件,这是ROS项目的构建文件。
cmake_minimum_required(VERSION 3.0.2)
project(my_robot)
find_package(catkin REQUIRED COMPONENTS
roscpp
)
catkin_package(
# catkin_package()
INCLUDE_DIRS include
LIBRARIES my_robot
CATKIN_DEPENDS roscpp
)
include_directories(${catkin_INCLUDE_DIRS})
add_executable(my_robot src/my_robot.cpp)
target_link_libraries(my_robot ${catkin_LIBRARIES})
2.3 编写节点代码
在src目录下创建一个名为my_robot.cpp的文件,编写简单的ROS节点代码:
#include <ros/ros.h>
int main(int argc, char **argv)
{
ros::init(argc, argv, "my_robot_node");
ros::NodeHandle nh;
ROS_INFO("Hello, ROS!");
ros::Rate loop_rate(10);
while (ros::ok())
{
ros::spinOnce();
loop_rate.sleep();
}
return 0;
}
2.4 编译和运行节点
编译工作空间:
cd ~/catkin_ws/
catkin_make
运行节点:
source devel/setup.bash
rosrun my_robot my_robot
第三部分:ROS话题
3.1 话题介绍
ROS中的话题用于节点之间的通信。一个节点可以发布消息到话题,其他节点可以订阅这个话题并接收消息。
3.2 发布和订阅话题
以下是一个简单的发布和订阅话题的例子:
发布者节点:
#include <ros/ros.h>
#include <std_msgs/String.h>
int main(int argc, char **argv)
{
ros::init(argc, argv, "publisher_node");
ros::NodeHandle nh;
ros::Publisher chatter_pub = nh.advertise<std_msgs::String>("chatter", 1000);
while (ros::ok())
{
std_msgs::String msg;
msg.data = "Hello, ROS!";
chatter_pub.publish(msg);
ros::spinOnce();
}
return 0;
}
订阅者节点:
#include <ros/ros.h>
#include <std_msgs/String.h>
void callback(const std_msgs::String::ConstPtr& msg)
{
ROS_INFO("I heard: [%s]", msg->data.c_str());
}
int main(int argc, char **argv)
{
ros::init(argc, argv, "subscriber_node");
ros::NodeHandle nh;
ros::Subscriber sub = nh.subscribe("chatter", 1000, callback);
ros::spin();
return 0;
}
编译并运行发布者和订阅者节点,可以看到消息在两个节点之间传递。
第四部分:ROS服务
4.1 服务介绍
ROS中的服务允许节点之间请求和响应操作。
4.2 创建服务
创建一个名为add_two_ints.srv的服务描述文件:
<service name="add_two_ints">
<request>
<int32 request_a/>
<int32 request_b/>
</request>
<response>
<int32 sum/>
</response>
</service>
4.3 实现服务
创建一个名为add_two_ints_server.cpp的服务实现文件:
#include <ros/ros.h>
#include <add_two_ints/AddTwoInts.h>
bool addTwoInts(add_two_ints::AddTwoInts::Request &req,
add_two_ints::AddTwoInts::Response &res)
{
res.sum = req.request_a + req.request_b;
return true;
}
int main(int argc, char **argv)
{
ros::init(argc, argv, "add_two_ints_server");
ros::NodeHandle nh;
ros::ServiceServer service = nh.advertiseService("add_two_ints", addTwoInts);
ros::spin();
return 0;
}
编译并运行服务,可以通过以下命令请求服务:
rosrun add_two_ints add_two_ints _request_a: 3 _request_b: 4
第五部分:ROS动作
5.1 动作介绍
ROS中的动作用于处理复杂的任务,它由一个客户端和服务器组成。
5.2 创建动作
创建一个名为add_two_ints.action的动作描述文件:
<action name="add_two_ints">
<goal>
<int32 goal_a/>
<int32 goal_b/>
</goal>
<result>
<int32 sum/>
</result>
<feedback>
<int32 progress/>
</feedback>
</action>
5.3 实现动作
创建一个名为add_two_ints_action_server.cpp的动作实现文件:
#include <ros/ros.h>
#include <actionlib/server/action_server.h>
#include <add_two_ints/AddTwoIntsAction.h>
class AddTwoIntsActionServer : public actionlib::ActionServer<add_two_ints::AddTwoIntsAction>
{
public:
AddTwoIntsActionServer(std::string name)
: actionlib::ActionServer<add_two_ints::AddTwoIntsAction>(name, false)
{
start();
}
~AddTwoIntsActionServer()
{
stop();
}
void executeCB(const goalConstPtr &goal, actionlib::GoalConstPtr &goal_handle)
{
int progress = 0;
while (progress < 100)
{
progress += 10;
feedback.progress = progress;
publishFeedback(feedback);
ros::Duration(1.0).sleep();
}
result.sum = goal->goal_a + goal->goal_b;
goal_handle->succeed();
}
private:
actionlib::GoalConstPtr goal_;
add_two_ints::AddTwoIntsFeedback feedback;
add_two_ints::AddTwoIntsResult result;
};
int main(int argc, char **argv)
{
ros::init(argc, argv, "add_two_ints_action_server");
AddTwoIntsActionServer server("add_two_ints");
ros::spin();
return 0;
}
编译并运行动作服务器,可以通过以下命令发送动作:
rosrun add_two_ints add_two_ints _goal_a: 3 _goal_b: 4
总结
通过本教程,你已掌握了ROS的基本操作技巧,包括创建工作空间、编写节点代码、发布和订阅话题、创建服务以及实现动作。ROS是一个功能强大的平台,它可以帮助你开发出各种复杂的机器人系统。继续学习和实践,你将能够开发出更多令人惊叹的机器人应用。