本文主要介绍如何使用ROS2。基于ROS2 Humble版本,介绍如何在Ubuntu22下安装和使用ROS2和ROS2的开发工具.
更多内容,访问专栏目录获取实时更新。
在Ubuntu中安装ROS2和开发工具
当前作者的Ubuntu版本:
在安装ROS前推荐先安装一些依赖工具:
- Terminator: 可以帮助开发者更方便的操作多个命令行
- Visual Studio Code: 开发IDE
- Gedit: 文本编辑工具
sudo apt install terminator
sudo apt install gedit
安装ROS则推荐参考官方文档,ROS2 Humble Installation Wiki。
或者执行:
sudo apt install ros-humble-desktop
安装完成之后,可以分别在两个命令行运行talker和listener程序,检查已经成功完成了安装:
ros2 run demo_nodes_cpp talker
ros2 run demo_nodes_cpp listener
在每次启动一个新的命令行工具时,我们都需要执行:
source /opt/ros/humble/setup.bash
(不同的ROS版本路径基本一致,如foxy版本的路径为/opt/ros/foxy/setup.bash)
为了后期使用方便,这里建议将该指令加入到.bashrc文件中
gedit ~/.bashrc # 编辑.bashrc文件
# 在最后一行添加
source /opt/ros/humble/setup.bash
下一步则是安装ROS2的编译工具colcon,参考ROS Wiki。
colcon是一个命令行工具,用于改进构建、测试和使用多个软件包的工作流程
sudo apt install python3-colcon-common-extensions
安装完成后我们需要启动colcon的自动补全配置:
cd /usr/share/colcon_argcomplete/hook/
ls # 找到配置文件的位置
将下面的指令加入到.bashrc文件的最后:
source /usr/share/colcon_argcomplete/hook/colcon-argcomplete.bash
创建Workspace和Package
Workspace是一个包含了多个Package的文件夹,在使用ROS之前,建议先在命令行里source你的工作空间从而获取相应的工作包。
创建工作空间:
mkdir ros2_ws
cd ros2_ws
mkdir src
colcon build
ls
上述的指令是在根目录下创建了一个文件夹ros2_ws,然后在ros2_ws目录下创建了一个src文件夹,然后执行colcon build
将当前的文件夹初始化为一个工作空间,最后你将在该目录下发现新生成了install, build和log三个新的文件夹。
为了能够获取到当前工作空间里的全部工作包,我们source该工作空间里install/setup.bash文件到.bashrc
source ~/ros2_ws/install/setup.bash
创建Python工作包:
cd ~/ros2_ws/src
ros2 pkg create my_py_pkg --build-type ament_python --dependencies rclpy
这里我们在ros2_ws/src文件夹下创建了一个名为my_py_pkg的工作包,并为它设置了编译类型和工作包依赖。
然后返回到ros2_ws目录下执行colcon build
编译该工作包。
当你在工作空间里有很多工作包时,可以指定编译某个工作包来节省时间:
colcon build --package-select my_py_pkg
创建C++工作包:
cd ~/ros2_ws/src
ros2 pkg create my_cpp_pkg --build-type ament_cmake --dependencies rclcpp
回到ros2_ws目录下执行colcon build
。
ROS2 Node
Node(节点)是ROS包(应用程序)中的一个子程序,它使用ROS的客户端库和其他节点进行通信,Node能够发布或订阅主题,以及提供或使用服务,是ROS中最基本的通信方式。
创建Python节点
在’my_py_pkg’工作包下创建节点文件:
my_first_node.py
#!/usr/bin/env python3
import rclpy
from rclpy.node import Node
def main(args=None):
rclpy.init(args=args) # initialize ROS communication
node = Node("py_test") # create a Node named py_test
node.get_logger().info("Hello ROS2") # let the node print something
rclpy.spin(node) # execute the program and block it
rclpy.shutdown() # shutdown communication
if __name__ == "__main__":
main()
创建完Node文件后,我们更新setup.py文件,将该节点加入到工作包中:
这里我们给节点赋了别名first_py_node,在使用它时就可以调用这个名字,=后面则是节点文件的路径和将要执行的函数名
然后回到Workspace目录(ros2_ws)下执行colcon build
,并执行source ~/.bashrc
。(再次确认你已经在该文件中加入了source ~/ros2_ws/install/setup.bash)
启动我们新创建的Python节点:
优化Python节点
my_first_node.py
#!/usr/bin/env python3
import rclpy
from rclpy.node import Node
class MyNode(Node):
def __init__(self):
super().__init__("py_test") # create a Node named py_test
self.get_logger().info("Hello ROS2") # let the node print something
self.counter = 0
self.create_timer(1, self.timer_callback) # call timer_callback() every 1 second
def timer_callback(self):
self.counter += 1
self.get_logger().info("Hello" + str(self.counter))
def main(args=None):
rclpy.init(args=args) # initialize ROS communication
node = MyNode()
rclpy.spin(node) # execute the program and block it
rclpy.shutdown() # shutdown communication
if __name__ == "__main__":
main()
创建C++节点
创建C++文件
cd ~/ros2_ws/src/my_cpp_pkg/src
touch my_first_node.cpp
如果我们直接开始引用头文件,会提示引用路径错误,这里需要更改引用路径
在VS Code中同时按下Ctrl+Shift+P,
会自动生成c_cpp_properties.json文件,更改其中的includePath:
my_first_node.cpp
#include "rclcpp/rclcpp.hpp"
int main(int argc, char **argv)
{
rclcpp::init(argc, argv);
auto node = std::make_shared<rclcpp::Node>("cpp_test"); // create a shared pointer for node named cpp_test
RCLCPP_INFO(node->get_logger(), "Hello CPP node"); // node print Hello content
rclcpp::spin(node);
rclcpp::shutdown();
return 0;
}
然后更新CMakeLists.txt
之后执行编译并运行:
优化C++节点
my_first_node.cpp
#include "rclcpp/rclcpp.hpp"
class MyNode: public rclcpp::Node
{
public:
MyNode(): Node("cpp_test"), counter(0)
{
RCLCPP_INFO(this->get_logger(), "Hello CPP node"); // node print Hello content
timer = this->create_wall_timer(
std::chrono::seconds(1),
std::bind(&MyNode::timerCallback, this)
);
}
private:
void timerCallback()
{
counter++;
RCLCPP_INFO(this->get_logger(), "Hello %d", counter);
}
rclcpp::TimerBase::SharedPtr timer;
int counter;
};
int main(int argc, char **argv)
{
rclcpp::init(argc, argv);
auto node = std::make_shared<MyNode>();
rclcpp::spin(node);
rclcpp::shutdown();
return 0;
}
ROS2 库
rcl - ros client library,包含了ROS开发过程中各种编程语言的依赖包,如:
- rclcpp
- rclpy
- rclnodejs
- rcljava
- rcl…
ROS工具
重命名节点
在运行多个相同节点时,我们会希望给Node起一个独特的名字用于区分,否则将会出现下面的问题:
在左侧两个命令行里启动了相同的Node,使用ros2 node list
查看当前节点列表时,可以看到提示有同名的节点,这也不利于后面节点间建立通信。
在启动节点时,可以添加参数做重映射,从而不需要在程序中做任何改动:
ros2 run <package_name> <node_name> --ros-args --remap __node:=<new_node_name>
Colcon
colcon是文章中我们一直在使用的编译工具,但是每次修改了文件之后,如果不执行colcon build
,修改是不会生效的。但是如果我们执行下面的指令,将会解决这个问题,从而避免经常编译:
colcon build --packages-select my_py_pkg --symlink-install
rqt_graph
分别在两个命令行中启动节点:
ros2 run demo_nodes_py talker
ros2 run demo_nodes_py listener
在另一个命令行中执行rqt_graph
,可以看到如下的界面,以图形话的方式显示节点间的联系:
Tutlesim
安装turtlesim包:
sudo apt install ros-humble-turtlesim
source ~/.bashrc
运行:
ros2 run turtlesim turtlesim_node
将会打开一个2D可视化界面:
使用下面的命令运行turtle的控制节点:
ros2 run turtlesim turtle_teleop_key
如有错误,欢迎留言或来信指正:hbin6358@163.com