Halo
发布于 2024-04-24 / 117 阅读 / 0 评论 / 0 点赞

ros2 编程简介

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

评论