ROS2小车学习

项目场景:

ROS2 foxy 小车 传感器融合
*本文编写规则
1、大写斜体 需替换为自定义名称


相关命令

1、节点启动

遥控控制
ros2 launch wheeltec_joy wheeltec_wire_joy.launch.py
动作捕获定位
ros2 launch vrpn_client_ros sample.launch.py
ros2 run fusion Mocap_node
底盘运动+寻磁
ros2 run chassis_control Car_control

ros2 run chassis_magnetic magnetic
ros2 run pid_c pid
ros2 launch ums_fiction_driver ums_fiction_v1.launch.py
寻磁启止
ros2 topic pub /Turn std_msgs/msg/Int8 data:\ 1
ros2 topic pub /Turn std_msgs/msg/Int8 data:\ 0
RFID
ros2 run data_publishing rfid
imu
ros2 run chassis_control car_motion_control
ros2 run data_publishing imu
UWB
ros2 run fusion UWB_node
融合定位
ros2 run fusion fusion_node
轨迹追踪
ros2 run path_track mpc_tracker
ros2 run path_track stanley_tracker
雷达建图
~/map_ws$ ros2 launch sllidar_ros2 sllidar_a1_launch.py

2、ROS2安装配置

(1) ROS2
ros2一键安装:wget http://fishros.com/install -O fishros && . fishros
ros2一键卸载:sudo apt remove ros-foxy-* && sudo apt autoremove
查看ros版本号:rosversion -d

创建工作空间
mkdir -p town_ws/src
cd town_ws/src
创建python功能包
ros2 pkg create <package_name> --build-type ament_python --dependencies rclpy

(2) 工具
1、RQT安装:
sudo apt-get install ros-$ROS_DISTRO-rqt
sudo apt install ros-$ROS_DISTRO-rqt*
2、rviz IMU插件:
sudo apt-get install ros-$ROS_DISTRO-imu-tools
3、python库安装:
pip install pyserial
pip install heapdict

(3) 更新环境变量
更新工作空间环境变量(每次build后都要)
source ./install/setup.bash
将source写入系统全局变量(build后自动source)
echo “source /home/用户名/文件夹/install/setup.bash” >> ~/.bashrc
source ~/.bashrc

(4) 指定源安装
-i https://pypi.tuna.tsinghua.edu.cn/simple some-package

(5) 编译指令
全局编译: colcon build
单独编译: colcon build --packages-select PACKAGE_NAME
python 静态链接编译 :colcon build --symlink-install

(6) 串口绑定
1、查看串口详细信息
$ udevadm info --attribute-walk --name=/dev/ttyUSB1 |grep KERNELS
>>>
KERNELS==“ttyUSB1”
KERNELS==“2-1.2.2:1.0”
KERNELS==“2-1.2.2”
KERNELS==“2-1.2”
KERNELS==“2-1”
KERNELS==“usb2”
KERNELS==“fc880000.usb”
KERNELS==“platform”

2、绑定串口(串口重命名)
$ sudo vim /etc/udev/rules.d/robotbase_port.rules
ACTION==“add”,KERNELS==“2-1.3.1:1.0”,SUBSYSTEMS==“usb”,MODE:=“0777”,SYMLINK+=“com_car”

3、重载串口
$ service udev reload
$ service udev restart
重新拔插串口
( ( 1.78 - 0.455 ) ^ 2 + 1.2 ^ 2 ) ^ ( 0.5 )

(7) 自启服务
sudo systemctl start autobase.service
sudo systemctl stop autobase.service
sudo systemctl restart autobase.service

3、测试

(1) rosbag记录器
记录全部话题 ros2 bag record -a
命名记录文件并挑选记录话题 ros2 bag record -o BAG-NAME /PACKAGE-NAME
播放纪录包并指定话题 ros2 bag play BAG-NAME --topics /PACKAGE-NAME
查看纪录包详情 ros2 bag info BAG-NAME

ros2 bag record -o RosbagRecord /test_car_1 /imu /uwb_distance /rfid_data /car1_Marker3/pose /Fused/pose /Mocap/pose /Fused/path /Mocap/path /Error

(2) 计算器欧式距离公式
((4.2−0.6)2+(4.8−1.2)2+(0.52−0.29)2)0.5

(3) ros系统桌面UI foxglove

1.启动桥:ros2 launch foxglove_bridge foxglove_bridge_launch.xml
2.打开foxglove studio

4、常用指令

(1) 话题相关
查看话题列表: ros2 topic list
查看话题列表及消息类型:ros2 topic list -t
订阅话题:ros2 topic echo TOPIC_NAME
查看话题频率:ros2 topic hz TOPIC_NAME
查看话题详情 (消息类型和发布者/订阅者的数量): ros2 topic info TOPIC_NAME

(2) 消息相关
查看消息定义:ros2 interface show geometry_msgs/msg/PoseStamped

5、ubuntu快捷指令

(1) linux 命令行指令
查看所有历史命令:history
查看包含关键词‘KEYWORD‘历史命令:history |grep KEYWORD
根据序号选择命令并执行:!001
查找包含输入字符的历史命令:ctrl R

(2)主目录查看隐藏文件(.bashrc)
ctrl H


Debug记录


编译问题

Q1、功能包编译 部分代码在install下不更新
python:将python功能包做静态链接 colcon build --symlink-install
c++:删除install 、build文件夹重新编译

Q2、找不到依赖功能包编译失败
方法一:先单独编译依赖功能包再全局编译 编译完后更新环境变量

colcon build --packages-select car_interfaces
colcon build
source ./install/setup.bash
colcon build --symlink-install

方法二:修改功能包的 package.xml 文件和 CMakeLists.txt 文件

在ROS2中,如果一个包(例如B_package)依赖于另一个包(例如A_package),需要在B_package的package.xml和CMakeLists.txt文件中声明这种依赖关系。
1.修改 package.xml 文件
在 package.xml 文件中,你需要添加 标签来声明对 A_package 的依赖。例如:

<package format="3">
  <name>B_package</name>
  <!-- 其他元数据... -->

  <depend>A_package</depend>

  <!-- 其他依赖... -->
</package>

2.修改 CMakeLists.txt 文件
需要在 find_package() 方法中添加 A_package 这个依赖。例如:

cmake_minimum_required(VERSION 3.5)
project(B_package)

# Default to C99
if(NOT CMAKE_C_STANDARD)
 set(CMAKE_C_STANDARD 99)
endif()

# Default to C++14
if(NOT CMAKE_CXX_STANDARD)
 set(CMAKE_CXX_STANDARD 14)
endif()

find_package(ament_cmake REQUIRED)
find_package(A_package REQUIRED) # 添加这行代码

\# 其他的 'find_package' 调用...

\# 剩下的 CMakeLists.txt 内容...

同时,如果你在 B_package 中使用了 A_package 的消息,则还需要在 add_dependencies() 方法中添加目标依赖。例如,如果你创建了一个名为 my_node 的可执行文件,那么应该这样做:

add_executable(my_node src/my_node.cpp)
ament_target_dependencies(my_node A_package) # 添加这行代码

使用这种方法,Ament工具(ROS 2的构建系统)将首先构建A_package,然后再构建B_package。

方法三:使用–packages-up-to命令,找到并编译所有依赖后再编译该包

colcon build --packages-up-to cartographer_ros

Q3、时钟错误编译失败
cmake会先查看文件的最新修改时间,跟log记录的时间比较决定是否进行更新。可以将系统设置为自动更新时间,或者输入命令强制更新时间

sudo date -s ‘2023-11-09 15:47:00’

Q4、python静态链接编译通过却无法rosrun

Traceback (most recent call last):
  File "/home/cat/agv_ws/install/fusion/lib/fusion/testHZ_node", line 33, in <module>
    sys.exit(load_entry_point('fusion', 'console_scripts', 'testHZ_node')())
  File "/home/cat/agv_ws/install/fusion/lib/fusion/testHZ_node", line 22, in importlib_load_entry_point
    for entry_point in distribution(dist_name).entry_points
  File "/usr/lib/python3.10/importlib/metadata/__init__.py", line 969, in distribution
    return Distribution.from_name(distribution_name)
  File "/usr/lib/python3.10/importlib/metadata/__init__.py", line 548, in from_name
    raise PackageNotFoundError(name)
importlib.metadata.PackageNotFoundError: No package metadata was found for fusion
[ros2run]: Process exited with failure 1

colcon build --symlink-install默认不执行soure,需要手动source一下环境。

source ./install/setup.bash



分布式测试问题

Q1、不同设备话题冲突混乱
在同一局域网下域ID可能相同,导致设备能互相接收话题,可以为每一个设备修改域ID

#进入设备用户根目录
vim .bashrc

在bash文件最后输入设置域ID命令,每个设备的ID号都要不一样

export ROS_DOMAIN_ID=XXX

最后更新用户环境变量

source .bashrc

Q2、ROS1和ROS2共存坑

  1. 启动终端选择ROS版本时会默认执行一次 source ~/.bashrc 。因此如果在系统全局变量.bashrc中添加了对ros1工作空间环境的source bash,如:source /home/dn/ROS1_Project/UAV_ws/devel/setup.bash,则会将部分全局变量设置为ROS1环境,导致ROS2运行出问题,反之同理。

Q3、code-server安装
ubuntu 20.04 code-server 安装
1、code-server github上下载deb文件
![架构区别
2、安装

dpkg -i code-server_4.2.0_amd64.deb

3、运行一次,生成配置文件

code-server

4、关闭程序,修改配置文件

vim ~/.config/code-server/config.yaml

bind-addr改为0.0.0.0并设置需要的端口(8080),更改password(abcd)
5、开启服务
sudo systemctl start code-server@username
6、开机自启
sudo systemctl enable --now code-server@$USER

Q4、rqt启动异常
ros/ros2同样的报错:

Traceback (most recent call last):
  File "/opt/ros/noetic/bin/rqt", line 13, in <module>
    sys.exit(main.main())
  File "/opt/ros/noetic/lib/python3/dist-packages/rqt_gui/main.py", line 61, in main
    return super(
  File "/opt/ros/noetic/lib/python3/dist-packages/qt_gui/main.py", line 407, in main
    from python_qt_binding import QT_BINDING
  File "/opt/ros/noetic/lib/python3/dist-packages/python_qt_binding/__init__.py", line 55, in <module>
    from .binding_helper import loadUi, QT_BINDING, QT_BINDING_MODULES, QT_BINDING_VERSION  # @UnusedImport
  File "/opt/ros/noetic/lib/python3/dist-packages/python_qt_binding/binding_helper.py", line 277, in <module>
    _select_qt_binding(
  File "/opt/ros/noetic/lib/python3/dist-packages/python_qt_binding/binding_helper.py", line 111, in _select_qt_binding
    QT_BINDING_VERSION = binding_loader(required_modules, optional_modules)
  File "/opt/ros/noetic/lib/python3/dist-packages/python_qt_binding/binding_helper.py", line 158, in _load_pyqt
    _named_optional_import('PyQt5.%s' % module_name)
  File "/opt/ros/noetic/lib/python3/dist-packages/python_qt_binding/binding_helper.py", line 145, in _named_optional_import
    _named_import(name)
  File "/opt/ros/noetic/lib/python3/dist-packages/python_qt_binding/binding_helper.py", line 136, in _named_import
    module = builtins.__import__(name)
ValueError: PyCapsule_GetPointer called with incorrect name

参考:运行rqt报错PyCapsule_GetPointer called with incorrect name解决办法

1、找到文件位置
ROS :

/opt/ros/noetic/lib/python3/dist-packages/python_qt_binding.binding_helper.py

ROS2:

/opt/ros/foxy/lib/python3.8/site-packages/python_qt_binding.binding_helper.py

2、打开文件
只读文件需要sudo权限才能修改

sudo vim binding_helper.py

3、修改文件
把QtWebKitWidgets注释

#‘QtWebKitWidgets’, # Qt 5.0 - 5.5

4、结果
可以打开rqt 但是仍然会报错 不影响使用

RosPluginProvider.load(qt_gui_cpp/CppPluginProvider) exception raised in __builtin__.__import__(qt_gui_cpp.cpp_plugin_provider, [CppPluginProvider]):
Traceback (most recent call last):
  File "/opt/ros/foxy/lib/python3.8/site-packages/rqt_gui/ros_plugin_provider.py", line 80, in load
    module = __builtin__.__import__(
  File "/opt/ros/foxy/lib/python3.8/site-packages/qt_gui_cpp/cpp_plugin_provider.py", line 33, in <module>
    from .cpp_binding_helper import qt_gui_cpp
  File "/opt/ros/foxy/lib/python3.8/site-packages/qt_gui_cpp/cpp_binding_helper.py", line 43, in <module>
    from . import libqt_gui_cpp_sip
ValueError: PyCapsule_GetPointer called with incorrect name

RecursivePluginProvider.discover() loading plugin "qt_gui_cpp/CppPluginProvider" failed:
Traceback (most recent call last):
  File "/opt/ros/foxy/lib/python3.8/site-packages/qt_gui/recursive_plugin_provider.py", line 60, in discover
    instance = self._plugin_provider.load(plugin_descriptor.plugin_id(), None)
  File "/opt/ros/foxy/lib/python3.8/site-packages/rqt_gui/ros_plugin_provider.py", line 91, in load
    raise e
  File "/opt/ros/foxy/lib/python3.8/site-packages/rqt_gui/ros_plugin_provider.py", line 80, in load
    module = __builtin__.__import__(
  File "/opt/ros/foxy/lib/python3.8/site-packages/qt_gui_cpp/cpp_plugin_provider.py", line 33, in <module>
    from .cpp_binding_helper import qt_gui_cpp
  File "/opt/ros/foxy/lib/python3.8/site-packages/qt_gui_cpp/cpp_binding_helper.py", line 43, in <module>
    from . import libqt_gui_cpp_sip
ValueError: PyCapsule_GetPointer called with incorrect name

ROS2教程

参考:ROS2中python引用自定义py文件

文件架构 (*表示自己创建的文件/文件夹)

workspace (工作空间)
|-> ...
|-> src
      |-> mypackage (python类型功能包)
             |-> mypackage (代码执行区)
                    |-> config                (*参数文件夹,需要被调用)
                           |->__init__.py 
                           |-> settings.py
                    |-> view                 (*功能文件夹,需要调用cofig包)
                           |->__init__.py 
                           |-> plot.py
                    |-> src                   (*主功能文件夹,需要调用cofig包,自身文件夹内部也需要互相调用)
                           |->__init__.py
                           |-> model.py
                           |-> train.py
                    |->__init__.py 
                    |-> main.py               (*功能包下的文件,需要调用cofig包)
             |-> launch                       (*lauch文件夹,批量启动节点)
                    |-> my.launch.py 
             |-> resource
                    |-> ...
             |-> test
                    |-> ...
             |-> package.xml
             |-> setup.cfg
             |-> setup.py  (配置文件 告诉ros文件怎么组织)

文件示例
1、setup.py:向编译器说明功能包的组织架构
参考: python打包分发工具:setuptools

from setuptools import setup
from glob import glob
import os

# 给出python包的路径
package_name = 'mypackage'
src = 'mypackage/src'
cofig = 'mypackage/cofig'
view = 'mypackage/view'

setup(
    name=package_name,
    version='0.0.0',
    packages=[package_name, src, cofig, view],   # 在编译时把这几个文件夹都复制到install/mypackage/..下
    data_files=[
        ('share/ament_index/resource_index/packages',
            ['resource/' + package_name]),
        ('share/' + package_name, ['package.xml']),
        (os.path.join('share', package_name, 'launch'), glob('launch/*.launch.py')), # 给出launch文件路径
    ],
    install_requires=['setuptools'],
    zip_safe=True,
    maintainer='nvidia',
    maintainer_email='xxx@qq.com',
    description='TODO: Package description',
    license='TODO: License declaration',
    tests_require=['pytest'],
    entry_points={
        'console_scripts': [
            "main_node = fusion.main:main",
            "train_node = fusion.src.train:main",
            "view_node = fusion.view.plot:main",
        ],
    },
)

2、导入自定义python包裹

# main.py导入settings.py
from .config import settings

# train.py导入model.py
from . import model

# train.py导入plot.py
from ..view import plot

<think>好的,我现在需要帮助用户了解如何使用ROS2实现小车循迹功能。首先,我得回顾一下用户的问题,他提到了ROS2小车循迹教程或实现方法,并且之前的引用中提到了引用[2]关于基于旭日派的ROS系统小车开发,特别是车辆循迹功能。这可能涉及到摄像头、速度控制以及质心检测等部分。 首先,我需要明确循迹功能的基本流程。通常,循迹分为图像采集、图像处理、控制指令生成三个步骤。ROS2中可能需要使用到摄像头节点、OpenCV处理图像,以及发布控制指令到电机驱动器。 接下来,我需要考虑ROS2的相关工具和包。例如,使用cv_bridge将ROS2的图像消息转换为OpenCV格式,使用rclpy编写节点,可能需要创建发布者和订阅者。图像处理部分可能需要颜色空间转换、轮廓检测或者线条检测算法,比如HSV阈值分割,寻找质心或边缘,然后根据位置偏差调整小车的速度和方向。 然后,我需要参考用户提供的引用[2],其中提到SunriseRobot对象、初始化摄像头,设置速度v_x, v_y, v_z和质心偏离的阈值。这可能意味着在代码中需要定义这些参数,并通过PID控制来调整小车的运动,使其保持在轨迹中心。 此外,用户可能对具体的实现步骤感兴趣,比如如何搭建仿真环境,是否需要使用Gazebo,或者如何在真实硬件上部署。但根据引用[1],用户之前搭建过小车仿真,可能更关注实际代码和节点结构。因此,教程可能需要分步骤说明节点创建、话题订阅与发布、图像处理逻辑、控制算法等。 还需要考虑可能遇到的问题,比如图像延迟、控制参数的调整、PID的稳定性,以及如何测试和调试。在回答中应该提到这些注意事项,帮助用户避免常见错误。 最后,生成相关问题时,要涵盖性能优化、硬件选择、算法改进等方面,确保用户能进一步深入学习。</think>### ROS2小车循迹功能实现步骤 #### 1. 系统架构设计 循迹功能基于**图像反馈-控制决策**的闭环系统,主要包含以下模块: - **摄像头驱动节点**:发布图像数据(`/image_raw`话题) - **图像处理节点**:订阅图像并计算轨迹偏移量 - **运动控制节点**:根据偏移量生成控制指令(`/cmd_vel`话题) - **底盘驱动节点**:执行运动指令 #### 2. 核心代码实现 ```python # 图像处理节点示例 import rclpy from cv_bridge import CvBridge from sensor_msgs.msg import Image from geometry_msgs.msg import Twist class LineTracker(rclpy.Node): def __init__(self): super().__init__('line_tracker') self.bridge = CvBridge() self.cmd_pub = self.create_publisher(Twist, '/cmd_vel', 10) self.sub = self.create_subscription(Image, '/image_raw', self.process_image, 10) # 控制参数 self.Kp = 0.005 # 比例系数 self.center_x = 320 # 图像中心坐标(需根据实际分辨率调整) def process_image(self, msg): cv_image = self.bridge.imgmsg_to_cv2(msg, 'bgr8') mask = self.color_segmentation(cv_image) # 颜色分割 cX = self.find_centroid(mask) # 计算质心 # 生成控制指令 cmd = Twist() error = self.center_x - cX cmd.angular.z = self.Kp * error # 转向控制 cmd.linear.x = 0.2 # 固定前进速度 self.cmd_pub.publish(cmd) def color_segmentation(self, image): hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV) lower = np.array([20, 100, 100]) # 黄色阈值示例 upper = np.array([30, 255, 255]) return cv2.inRange(hsv, lower, upper) def find_centroid(self, mask): M = cv2.moments(mask) if M["m00"] > 0: return int(M["m10"] / M["m00"]) return self.center_x # 丢失目标时返回中心值 ``` #### 3. 关键参数说明 | 参数 | 说明 | 典型值 | |------|------|-------| | Kp | 比例控制系数 | 0.003-0.01 | | v_x | 前进线速度 | 0.1-0.5 m/s | | 图像中心 | 取决于摄像头分辨率 | (320,240)@640x480 | | 颜色阈值 | 根据实际赛道调整 | HSV空间范围 | #### 4. 调试方法 1. **可视化调试**:使用`rqt_image_view`查看处理后的图像效果 2. **参数调节**:通过`ros2 param set`动态调整PID参数 3. **仿真测试**:优先在Gazebo仿真环境中验证算法[^1] 4. **实时曲线**:使用`rqt_plot`显示误差和控制量变化 #### 5. 进阶优化方向 - 加入**积分微分项**改善控制稳定性 $$ u(t) = K_p e(t) + K_i \int_0^t e(\tau)d\tau + K_d \frac{de(t)}{dt} $$ - 使用**深度学习模型**进行复杂路径识别 - 添加**故障恢复**机制(如丢失路线自动旋转搜索)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值