ros2 特点
ROS1的核⼼是⼀个基于master中⼼节点的匿名发布-订阅通信中间层,相⽐之下,ROS2采⽤基于RTSP(Real-Time Publish-Subscribe)协议的DDS作为中间层,DDS(Data-Distribution Service)是⼀种⽤于实时和嵌⼊式系统发布-订阅式通信的⼯业标准,这种点到点的通信模式类似于ROS1的中间层,但是DDS不需要像ROS1那样借由master节点来完成两个节点间通信,这使得系统更加容错和灵活,DDS 被⼴泛应⽤于关键系统中,包括战舰、⼤型基础设施(如⽔电站)、⾦融系统、空间系统、航空系统等场景,这些⽤例也证实了DDS的可靠性。
安装ros2
locale # check for UTF-8
apt update && apt install locales
locale-gen en_US en_US.UTF-8
update-locale LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8
export LANG=en_US.UTF-8
locale # verify settings
apt install software-properties-common
add-apt-repository universe
apt update && apt install curl -y
curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2/ubuntu $(. /etc/os-release && echo $UBUNTU_CODENAME) main" | tee /etc/apt/sources.list.d/ros2.list > /dev/null
apt update
apt upgrade
apt install -y ros-humble-ros-base ros-dev-tools
echo 'source /opt/ros/humble/setup.bash' >> ~/.bashrc
. ~/.bashrc
echo "export ROS_DOMAIN_ID=<your_domain_id>" >> ~/.bashrc
检查是否安装成功
printenv | grep -i ROS
启动发布和订阅节点
create pubsub's publisher and listener
mkdir -p ~/ros2_ws/src
cd ~/ros2_ws/src
ros2 pkg create --build-type ament_python --license Apache-2.0 py_pubsub
cd ~/ros2_ws/src/py_pubsub/py_pubsub
wget https://raw.githubusercontent.com/ros2/examples/rolling/rclpy/topics/minimal_publisher/examples_rclpy_minimal_publisher/publisher_member_function.py
cat publisher_member_function.py
wget https://raw.githubusercontent.com/ros2/examples/rolling/rclpy/topics/minimal_subscriber/examples_rclpy_minimal_subscriber/subscriber_member_function.py
add depend package
cd ~/ros2_ws/src/py_pubsub
nano package.xml
<?xml version="1.0"?>
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3">
<name>py_pubsub</name>
<version>0.0.0</version>
<description>TODO: Package description</description>
<maintainer email="3140618@163.com">root</maintainer>
<license>Apache-2.0</license>
<exec_depend>rclpy</exec_depend>
<exec_depend>std_msgs</exec_depend>
<test_depend>ament_copyright</test_depend>
<test_depend>ament_flake8</test_depend>
<test_depend>ament_pep257</test_depend>
<test_depend>python3-pytest</test_depend>
<export>
<build_type>ament_python</build_type>
</export>
</package>
This declares the package needs rclpy and std_msgs when its code is executed.
add console_scripts talker and listener in setup.py
cd ~/ros2_ws/src/py_pubsub
nano setup.py
from setuptools import find_packages, setup
package_name = 'py_pubsub'
setup(
name=package_name,
version='0.0.0',
packages=find_packages(exclude=['test']),
data_files=[
('share/ament_index/resource_index/packages',
['resource/' + package_name]),
('share/' + package_name, ['package.xml']),
],
install_requires=['setuptools'],
zip_safe=True,
maintainer='root',
maintainer_email='3140618@163.com',
description='TODO: Package description',
license='Apache-2.0',
tests_require=['pytest'],
entry_points={
'console_scripts': [
'talker = py_pubsub.publisher_member_function:main',
'listener = py_pubsub.subscriber_member_function:main',
],
},
)
check setup.cfg
cd ~/ros2_ws/src/py_pubsub
cat setup.cfg
[develop]
script_dir=$base/lib/py_pubsub
[install]
install_scripts=$base/lib/py_pubsub
This is simply telling setuptools to put your executables in lib, because ros2 run will look for them there.
build
cd ~/ros2_ws
rosdep install -i --from-path src --rosdistro humble -y
colcon build --packages-select py_pubsub
run talker
cd ~/ros2_ws
source install/setup.bash
ros2 run py_pubsub talker
run listener
cd ~/ros2_ws
source install/setup.bash
ros2 run py_pubsub listener
启动服务端和客户端节点
create py_srvcli service and client
mkdir -p ~/ros2_ws/src
cd ~/ros2_ws/src
ros2 pkg create --build-type ament_python --license Apache-2.0 py_srvcli --dependencies rclpy example_interfaces
cd ~/ros2_ws/src/py_srvcli/py_srvcli
nano service_member_function.py
from example_interfaces.srv import AddTwoInts
import rclpy
from rclpy.node import Node
class MinimalService(Node):
def __init__(self):
super().__init__('minimal_service')
self.srv = self.create_service(AddTwoInts, 'add_two_ints', self.add_two_ints_callback)
def add_two_ints_callback(self, request, response):
response.sum = request.a + request.b
self.get_logger().info('Incoming request\na: %d b: %d' % (request.a, request.b))
return response
def main():
rclpy.init()
minimal_service = MinimalService()
rclpy.spin(minimal_service)
rclpy.shutdown()
if __name__ == '__main__':
main()
nano client_member_function.py
import sys
from example_interfaces.srv import AddTwoInts
import rclpy
from rclpy.node import Node
class MinimalClientAsync(Node):
def __init__(self):
super().__init__('minimal_client_async')
self.cli = self.create_client(AddTwoInts, 'add_two_ints')
while not self.cli.wait_for_service(timeout_sec=1.0):
self.get_logger().info('service not available, waiting again...')
self.req = AddTwoInts.Request()
def send_request(self, a, b):
self.req.a = a
self.req.b = b
self.future = self.cli.call_async(self.req)
rclpy.spin_until_future_complete(self, self.future)
return self.future.result()
def main():
rclpy.init()
minimal_client = MinimalClientAsync()
response = minimal_client.send_request(int(sys.argv[1]), int(sys.argv[2]))
minimal_client.get_logger().info(
'Result of add_two_ints: for %d + %d = %d' %
(int(sys.argv[1]), int(sys.argv[2]), response.sum))
minimal_client.destroy_node()
rclpy.shutdown()
if __name__ == '__main__':
main()
check depend package
cd ~/ros2_ws/src/py_srvcli
cat package.xml
<?xml version="1.0"?>
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3">
<name>py_srvcli</name>
<version>0.0.0</version>
<description>TODO: Package description</description>
<maintainer email="3140618@163.com">root</maintainer>
<license>Apache-2.0</license>
<depend>rclpy</depend>
<depend>example_interfaces</depend>
<test_depend>ament_copyright</test_depend>
<test_depend>ament_flake8</test_depend>
<test_depend>ament_pep257</test_depend>
<test_depend>python3-pytest</test_depend>
<export>
<build_type>ament_python</build_type>
</export>
</package>
add console_scripts talker and listener in setup.py
cd ~/ros2_ws/src/py_srvcli
nano setup.py
from setuptools import find_packages, setup
package_name = 'py_pubsub'
setup(
name=package_name,
version='0.0.0',
packages=find_packages(exclude=['test']),
data_files=[
('share/ament_index/resource_index/packages',
['resource/' + package_name]),
('share/' + package_name, ['package.xml']),
],
install_requires=['setuptools'],
zip_safe=True,
maintainer='root',
maintainer_email='3140618@163.com',
description='TODO: Package description',
license='Apache-2.0',
tests_require=['pytest'],
entry_points={
'console_scripts': [
'service = py_srvcli.service_member_function:main',
'client = py_srvcli.client_member_function:main',
],
},
)
check setup.cfg
cd ~/ros2_ws/src/py_srvcli
cat setup.cfg
[develop]
script_dir=$base/lib/py_srvcli
[install]
install_scripts=$base/lib/py_srvcli
This is simply telling setuptools to put your executables in lib, because ros2 run will look for them there.
build
cd ~/ros2_ws
rosdep install -i --from-path src --rosdistro humble -y
colcon build --packages-select py_srvcli
run service
cd ~/ros2_ws
source install/setup.bash
ros2 run py_srvcli service
run client
cd ~/ros2_ws
source install/setup.bash
ros2 run py_srvcli client 2 3