ROS小车(持续更新中---)

无中生有:ROS无人小车

    • 一.Nvidia jetson orin nano刷机
    • 二.ROS以及Cartographer安装
    • 三.MQTT通信 (持续更新中---)
    • 四.激光里程计
    • 五.Cartographer之纯定位 (持续更新中---)
    • 六.AMCL及Navigation调试经验 (持续更新中---)
    • 七.路线记录

一.Nvidia jetson orin nano刷机

本人设备:orin nano是8G版,安装NVMe SSD存储卡,VM虚拟机
目前orin nano的教程较少,参考文章:orin nano刷机

按照这个过程下来基本没什么错误,遇到的坑主要集中在第二步:

  1. dev/sda1空间不足 :解决方法是扩展,利用gparted分区编辑器(虚拟机随便扩展)找到/dev/sda1分区,然后在这个分区上右键选择“调整大小”最后确定且保存就好
sudo apt-get install gparted
sudo gparted
  1. 第二步的host机下载资源的时候千万不要有中文路径,否则各种报错
  2. 下载后host机空间瞬间爆炸:安装完之后卸载sdkmanager也挽回不了多少空间,解决方法是直接删除虚拟机

最终刷机是ubuntu20.04版本,目前只有5.1.1的JetPack适用orin nano,按理说可以支持18.04版本的,但是不知道如何安装18.04版本,写了封邮件到nvidia的技术支持(这年代了还用邮件…),目前也没回复,只能说这个技术支持“依托答辩”

如果需要远程控制,尤其想要远程桌面的话,可以看我上一篇jetson nano的介绍安装vino,如果出现的画面是nvidia的图标而不是桌面或无法连接VNC的话,可以参考下面的方法:

# 安装
sudo apt-get install  xserver-xorg-video-dummy
# 添加配置文件,实现开机自启动
sudo vim /usr/share/X11/xorg.conf.d/xorg.conf
# 加入下面内容,设置分辨率为1440x900
Section "Monitor"
  Identifier "Monitor0"
  HorizSync 28.0-80.0
  VertRefresh 48.0-75.0
  # https://arachnoid.com/modelines/
  # 1920x1080 @ 60.00 Hz (GTF) hsync: 67.08 kHz; pclk: 172.80 MHz
  Modeline "1440x900_60.00" 172.80 1920 2040 2248 2576 1080 1081 1084 1118 -HSync +Vsync
EndSection
Section "Device"
  Identifier "Card0"
  Driver "dummy"
  VideoRam 256000
EndSection
Section "Screen"
  DefaultDepth 24
  Identifier "Screen0"
  Device "Card0"
  Monitor "Monitor0"
  SubSection "Display"
    Depth 24
    Modes "1440x900_60.00"
  EndSubSection
EndSection
# 重启后如果不能连接上,可以先用ssh连上之后,通过命令打开vino,然后再连接VNC
/usr/lib/vino/vino-server --display=:0

二.ROS以及Cartographer安装

参考文章:ROS以及Cartographer安装
按照上文的步骤来基本没有错误,ROS版本是Noetic,在安装Cartographer的必备库可以不需要安装protobuf和ceres库

使用cartographer过程中可能遇到以下问题:

1. 串口通信需要用到serial库,Noetic无法通过apt安装这个库,只能通过源码手动安装(源码安装方法)
2. 加载机器人坐标系描述文件,Noetic和之前的ROS版本不一样,加载时可能报错:

<param name="robot_description" command="$(find xacro)/xacro.py '$(arg model)'" />

错误:Invalid <param> tag: Cannot load command parameter[robot_description]: no such command [['/opt/ros/noetic/share/xacro/xacro.py'

解决方式是删除xacro.py的后缀.py即:

<param name="robot_description" command="$(find xacro)/xacro '$(arg model)'" />

3.加载机器人.dae文件遇到报错“Expected end of element" ,这是ubuntu版本的原因,解决方法:
所有左边形式的全部改成右边的形式 :

<author />                ---->             <author > xxx author > 
<copyright />             ---->             <copyright > xxx copyright > 
<source_data />           ---->             <source_data> xxx source_data> 

4. 编译报错:

CMake Error: The following variables are used in this project, but they are set to NOTFOUND.
Please set them or make sure they are set and tested correctly in the CMake files:
GMOCK_LIBRARY (ADVANCED)
linked by target "time_conversion_test" in directory /home/alex/catkin_ws/src/cartographer_ros/cartographer_ros
linked by target "msg_conversion_test" in directory /home/alex/catkin_ws/src/cartographer_ros/cartographer_ros

解决方法:sudo apt install libgmock-dev安装了一个新版本,catkin_make编译成功

三.MQTT通信 (持续更新中—)

1. paho-mqtt.c库安装:

# 一些需要的依赖:
sudo apt-get install build-essential gcc make cmake cmake-gui cmake-curses-gui
sudo apt-get install libssl-dev 
sudo apt-get install doxygen graphviz

git clone https://github.com/eclipse/paho.mqtt.c.git
cd paho.mqtt.c
make
make install

2. paho-mqtt.cpp库安装:

git clone https://github.com/eclipse/paho.mqtt.cpp
cd paho.mqtt.cpp
cmake CMakeList.txt
cmake -Bbuild -H.
make install
sudo ldconfig

四.激光里程计

由于在ROS中ACML定位方法需要用到里程计的数据,而目前我车上的莫名原因导致里程计的数据是错误的,严重造成ACML定位不准,为此必须剔除掉车上的里程计数据。但ACML定位又必须提供里程计的数据,那么怎么解决这种里程计数据缺失或严重不可靠问题呢?在ACML定位里,里程计其实就是提供x轴的加速度和z轴的转向角而已,而这些是可以通过其他传感器模拟的,例如使用imu或者激光雷达,下面提供一种激光雷达模拟里程计数据的方法:
1.下载rf2o_laser_odometry库:
这是一个利用激光雷达模拟里程计数据的功能包,效果还是很好的Github:https://github.com/MAPIRlab/rf2o_laser_odometry
如果不方便github,这里有个人的gitee下载:https://gitee.com/cml-qq/rf2_laser_odometry.git
2.修改launch文件(按需修改):
例如:

<launch>

  <node pkg="rf2o_laser_odometry" type="rf2o_laser_odometry_node" name="rf2o_laser_odometry" output="screen">
    <param name="laser_scan_topic" value="/scan"/>        # 激光雷达话题
    <param name="odom_topic" value="/odom" />              # 发布的里程计话题
    <param name="publish_tf" value="true" />                   # 是否发布tf (base_footprint->odom)
    <param name="base_frame_id" value="/base_footprint"/>     # 机器人底盘坐标系
    <param name="odom_frame_id" value="/odom" />                # 里程计坐标系    
    <param name="init_pose_from_topic" value="" />        # 若空则从(0,0)开始,可以使用有初始坐标的话题,一般为空
    <param name="freq" value="10.0"/>                         # 频率
    <param name="verbose" value="true" />                       # 不变
  </node>
  
</launch>

3.在rf2o_laser_odometry/src/CLaserOdometry2DNode.cpp中126和127行:
按照自己的机器人底盘坐标系和激光雷达的坐标系修改,例如:

tf_listener.waitForTransform("/base_footprint","/laser_link", ros::Time(), ros::Duration(5.0));
tf_listener.lookupTransform("/base_footprint","/laser_link", ros::Time(0), transform);

4.在rf2o_laser_odometry/src/CLaserOdometry2D.cpp中295,319行左右:

 //if (dcenter > 0.f)修改为
 if (std::isfinite(dcenter) && dcenter > 0.f)

5.编译使用,记得先运行激光雷达的launch文件哦!

五.Cartographer之纯定位 (持续更新中—)

由于在ROS中ACML定位方法需要用到里程计的数据,而目前我车上的莫名原因导致里程计的数据是错误的,严重造成ACML定位不准。考虑到Cartographer建图时的定位是很准的,我们是否可以利用Cartographer进行纯定位呢,答案当然是可行的。而且官方也给出了相应的launch文件供我们实验呢,当然还要配置一些参数呢。

六.AMCL及Navigation调试经验 (持续更新中—)

1. AMCL定位调试:Wiki百科介绍AMCL

  • 首先检查使用AMCL定位的前提是否满足,有没有发布AMCL定位需要订阅的下列话题,初始点的话题可以忽略(主要是tf树和odom数据,若没有odom可以参考四、五

ROS小车(持续更新中---)_第1张图片

  • 下面仅标注我觉得比较影响定位效果的参数,其余参数不再介绍,大家可以看Wiki百科或者另寻资料
<launch>
    <node pkg="amcl" type="amcl" name="amcl" clear_params="true">
        <param name="min_particles" value="500"/>
        <param name="max_particles" value="2000"/>
        <param name="update_min_d" value="0.25"/>
        <param name="update_min_a" value="0.2"/>
        <param name="resample_interval" value="1"/>
        <param name="transform_tolerance" value="1.0"/>
        <param name="recovery_alpha_slow" value="0.001"/>
        <param name="recovery_alpha_fast" value="0.001"/>
        <param name="use_map_topic" value="false"/>
        <param name="save_pose_rate"  value="0.5"/>
        <param name="gui_publish_rate" value="10.0"/>
        <param name="first_map_only" value="false"/>
        
        <param name="odom_model_type" value="diff"/>      # 选择自己的odom类型,我的是差分
        <param name="kld_err" value="0.1"/>
        <param name="kld_z" value="0.99"/>
        <param name="odom_alpha1" value="0.1"/>           # 这是设置odom的噪声的,根据自己odom来估计给定,我是使用激光里程计
        <param name="odom_alpha2" value="0.1"/>           # 我主要是平移分量的误差有点大,适当设置3和4的值
        <param name="odom_alpha3" value="0.18"/>          # 1和2是旋转分量的噪声
        <param name="odom_alpha4" value="0.18"/>
        <param name="odom_frame_id" value="odom"/>
        
        <param name="laser_max_beams" value="60"/>
        <param name="laser_min_range" value="-1"/>
        <param name="laser_max_range" value="30"/>
        <param name="laser_z_hit" value="0.5"/>
        <param name="laser_z_short" value="0.05"/>
        <param name="laser_z_max" value="0.05"/>
        <param name="laser_z_rand" value="0.5"/>
        <param name="laser_sigma_hit" value="0.2"/>
        <param name="laser_lambda_short" value="0.1"/>
        <param name="laser_likelihood_max_dist" value="2.0"/>
        <param name="laser_model_type" value="likelihood_field_prob"/>    # 一共有三个选择,这个是效果最好的,可能有些雷达不适用
        
        <remap from="scan" to="scan"/>
    </node>
</launch>

2. Navigation调试:Wiki百科解释Navigation

常规的配置我就不说了,CSDN里也有比较好的文章介绍和配置Move_base
按照博客和一些书籍整个配置下来基本没什么大问题,能跑起来(我是在前人的基础上修改的,没完全根据博客或书籍从零开始,所以上面可能有些问题不在我考虑的范围内)

接下来主要介绍我遇到的严重困扰的问题和调试的过程:

  • 我使用的全局路径规划算法是global_planner/GlobalPlanner,局部路径规划算法是dwa_local_planner/DWAPlannerROS
  • 遇到的问题是全局路径规划成功,但是小车无法跟着全局路径走,且有旋转着走的趋向

调试与分析方法:

  • rosbag的使用,rosbag用来记录场景传感器的数据,方便后续分析定位问题与重现场景,提高调试效率
 mkdir ~/bagfiles
 cd bagfiles
 rosbag record -a    #记录所有的话题数据
 rosbag play xxxx.abg     #内容回放,一些模型是不会存在里面的,所以如果要回访且用rviz显示,记得roslaunch加载模型

七.路线记录

使用脚本记录下车行走的路据点并保存到csv文件中,方便后续让车按照指定路径行驶

#!/usr/bin/python3

import pandas as pd
import rospy
from geometry_msgs.msg import PoseWithCovarianceStamped


def initialize():
    rospy.init_node('way_collect')
    rospy.Subscriber("/amcl_pose", PoseWithCovarianceStamped, point_collect)
    rospy.spin()
        
def point_collect(msg):
    way_point = [msg.pose.pose.position.x, msg.pose.pose.position.y, msg.pose.pose.position.z, 
            msg.pose.pose.orientation.x, msg.pose.pose.orientation.y, msg.pose.pose.orientation.z, msg.pose.pose.orientation.w]
    print("Received way_point: x={}, y={}, z={}".format(msg.pose.pose.position.x, msg.pose.pose.position.y, msg.pose.pose.position.z))
    data = pd.DataFrame([way_point])
    data.to_csv('csv/route_01.csv', mode='a', header=False, index=False)


if __name__ == "__main__":
    print("-----Start collect-----")
    initialize()

你可能感兴趣的:(ROS,ubuntu,机器人)