TX2_ros_RTABMAP_kinect2

ros安装

1
W: GPG error: http://mirrors.ustc.edu.cn/ros/ubuntu xenial InRelease: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY F42ED6FBAB17C654
  • 解决

    1
    sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 2EA8F35793D8809A # 复制上面的key
  • ros 版本导致的opencv 问题 ,orbslam 以及vins 都是基于opencv3 以后的版本,最好使用Ubuntu 16.04

  • TX2 安装好相应的ros配置后,默认是不推荐rviz 的,但是我们可能会用到rviz(arm 下得问题,性能原因,系统会做一些禁止,sefaultment fault)
  • 解决
    1
    2
    3
    4
    5
     unset GTK_IM_MODULE  >> .bashrc   ===>solve the Segmentation fault  
    ## It is not recommended to run rviz on most ARM-based CPUs. They're generally too slow, and the version of OpenGL
    ## that is provided by the software (mesa) libraries it not new enough to start rviz.

    ## 待处理,这个地方我们的设置我忘记是什么了,待我有时间的时候去看下

安装rtabmap

安装kinect 驱动 libfreet2 iai_kinect

1
rosrun tf static_transform_publisher 0 0 0 -1.5707963267948966 0 -1.5707963267948966 camera_link kinect2_link 100
  • 上面是一个tf的静态变换,在tf变换中一般有以下几种,map odom base_link laser_link (camera_link kinect2_link ) …..map 一般就是robot的基础坐标,也就是世界坐标,odom 是里程计坐标 。 base_link 一般是小车的基座,和小车的map坐标系重合。(我们在做move_base 导航的时候最好也是用base_link 或是他的基座,例如我们的camera_link,和map的姿势是相同的)
  • tf 的意义,定义两个刚体之间的位置,以及姿势的关系,
  • 关于参数的定义 rosrun tf static_transform_publisher x y z yawl patich roll father_link child_link period_in_ms(发布间隔)
  • 分别的意义在于 x y z 对应该刚体中心相对于上个link的位置,然后 yawl pitch roll 分别对应于偏航角,俯仰角,翻滚角,这个对应于刚体运动的知识,可以去补充一下相关的知识。
  • 其中注意 yaw pitch roll 不要弄错,可以通过rviz查看, 红色是x , 绿色是y, 蓝色是z
  • 静态发布信息还有一种是四元数的方式发布,不会。。。。我
  • reference https://www.jianshu.com/p/83bbf69ba6d3

  • tf 变换重要么,相当重要,同时我们也需要理解倒tf变换的意义,我,,,真的没有看懂,但是基本也就是知道他们之间怎么看是否重合了,啊哈哈, rviz (我们当时的小车在路径规划完毕后每次都会往一个角度转一个角度,然后再开始运行,没错,就是跑倒另外的地方去了结果自己的跑丢了。)

  • 启动相机

    1
    2
    ```bash
    roslaunch kinect2_bridge kinect2_bridge.launchpublish_tf:=true //启动相机,最后一个参数是为了让相机输出的pointcloud 有坐标
  • 启动建图 //这一块的启动有时候需要参考着官方给的例子来看着,因为很多时候会出现很多奇怪的问题。重启,欸

  • 在rtabmap中有一些相关的service,我们,能够利用service修改rtabmap的导航和建图模式,以及其他的东西,具体可以查看rtabmap_ros 对于他的参数以及服务的定义,,,对了,他的nodelet的意义不是很明确。。。。咱太菜,没得办法。
1
2
3
4
5
6
roslaunch rtabmap_ros rgbd_mapping_kinect2.launch resolution:=qhd localization:=true //定位的方式打开 但是在使用过程种遇到了一些问题,选择放弃这个
# 可见 使用Kinect的 qhd 格式 960*480
roslaunch rtabmap_ros rtabmap2.launch rtabmap_args:="--delete_db_on_start" rgb_topic:=/kinect2/qhd/image_color_rect depth_topic:=/kinect2/qhd/image_depth_rect camera_info_topic:=/kinect2/qhd/camera_info approx_sync:=false

# 建图不可见
roslaunch rtabmap_ros rtabmap.launch rtabmap_args:="--delete_db_on_start" rgb_topic:=/kinect2/qhd/image_color_rect depth_topic:=/kinect2/qhd/image_depth_rect camera_info_topic:=/kinect2/qhd/camera_info approx_sync:=false rtabmapviz:=false
  • 启动可视化界面
    1
    2
    roslaunch rtabmap_ros demo_turtlebot_rviz.launch
    # 在这里面为了得到一个可视化的二维地图,我们可以将map 选项修改为rtabmap/grid_map

导航模块

  • move_base 需要输入的东西 ,odom cloud 然后再move_base还需要一个代价地图得输入。这个代价地图由我们这里输入
  • 先说思路,(导航需要输入)
    1. 假激光,我们使用 depthimage_to_laserscan 包将来自Kinect2 的图像以及深度信息转化为scan 的数据类型。
      (个人看法,我查看一个博主有说过,这个时候,我们可以修改rtabmap的启动参数,把他监听scan数据类型的参数打开,好像是一个 subscirbe_scan = true 就行。。但是感觉如果只是为了一个代价地图的话,假激光再输入给rtabmap的话,没有太大的意义,反而加大了计算机的计算量)
    1. 投影地图法,我们利用kinect2 的Kinect2/qhd/points 接口出来的带有坐标的cloud 信息,经过rtbmap 的 nodelet 转化后生成一个投影地图,作为局部地图的输入,其他的什么都不用修改。
  • reference http://wiki.ros.org/rtabmap_ros/Tutorials/StereoOutdoorNavigation
  • 但是官方给我的例子我没有改出来,但是现在感觉还是有很多可以修改的地方,

  • 代码实现,以及某些参数的意义。

    • 我的实现方式为仅使用Kinect的深度信息,来建图,同时move_base 的输入为来自rtabmap的传入的grid_map 以及Odom 做为输入,同时代价地图为深度信息的points 节点通过rtabmap的转换节点变为投影地图,输入
  • base_local_planner_params.yaml

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    TrajectoryPlannerROS:

    # Current limits based on AZ3 standalone configuration.
    acc_lim_x: 0.75 # x方向的加速度
    acc_lim_y: 0.0 # y方向的加速度,但是因为在二维平面上运动,也就没有必要,故为0
    acc_lim_theta: 4.00
    max_vel_x: 0.500 # x方向的最大速度
    min_vel_x: 0.212 # 最小
    max_rotational_vel: 0.550 # 最大的旋转角速度
    min_in_place_rotational_vel: 0.15
    escape_vel: -0.10 # 逃离速度,在某个时候因为离的太近的时候需要有一个逃离速度
    holonomic_robot: false # 非全向的时候使用,例如 无人机时候开为true

    xy_goal_tolerance: 0.20
    yaw_goal_tolerance: 0.20

    sim_time: 1.7
    sim_granularity: 0.025
    vx_samples: 3
    vtheta_samples: 3
    vtheta_samples: 20

    goal_distance_bias: 0.8
    path_distance_bias: 0.6
    occdist_scale: 0.01
    heading_lookahead: 0.325
    dwa: true

    oscillation_reset_dist: 0.05
    meter_scoring: true

    # 其他参数还没有细细的去了解
  • costmap_common_params.yaml

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    obstacle_range: 2.5
    raytrace_range: 3.0
    footprint: [[ 0.15, 0.15], [-0.15, 0.15], [-0.15, -0.15], [ 0.15, -0.15]]
    footprint_padding: 0.03
    #robot_radius: ir_of_robot
    inflation_radius: 0.55
    transform_tolerance: 1 # 很多时候如果转化由于tf转化是需要时间的,但是我们转化太慢,性能不够的时候,有一个容忍的时间,

    controller_patience: 2.0

    NavfnROS:
    allow_unknown: true

    recovery_behaviors: [
    {name: conservative_clear, type: clear_costmap_recovery/ClearCostmapRecovery},
    {name: aggressive_clear, type: clear_costmap_recovery/ClearCostmapRecovery}
    ]

    conservative_clear:
    reset_distance: 3.00
    aggressive_clear:
    reset_distance: 1.84

    cost_scaling_factor: 10.0
    # observation_sources: scan
    # scan: {sensor_frame: kinect2_link, observation_persistence: 0.0, max_obstacle_height: 0.4, min_obstacle_height: 0.0, data_type: LaserScan, topic: /scan, marking: true, clearing: true}
    # 这是两种代价地图的定义方式,一种是scan 一种是投影地图,我用scan没有出来,,然后换成了pointcloud2 ,还有在双目导航的那个地方,该配置文件的配置位置是不对的,我也不知道,反正我没跑出来。。。哭,然后参考一些其他的文件。

    observation_sources: point_cloud_sensor

    # assuming receiving a cloud from rtabmap_ros/obstacles_detection node
    point_cloud_sensor: {
    sensor_frame: camera_link, # 该帧对应的tf变化坐标,我也不知道了,,反正我都用的基础坐标系作为做关键的坐标系,,
    data_type: PointCloud2,
    topic: planner_cloud,
    expected_update_rate: 0.5,
    marking: true,
    clearing: true,
    min_obstacle_height: -99999.0,
    max_obstacle_height: 99999.0}
  • global_costmap_param.yaml

    1
    2
    3
    4
    5
    6
    7
    global_costmap:
    global_frame: map # 世界坐标系
    robot_base_frame: camera_link # base_link
    update_frequency: 0.5
    publish_frequency: 0.5
    static_map: true
    transform_tolerance: 3
  • local_costmap_params.yaml

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    local_costmap:
    global_frame: odom # 参照的坐标系,odom 作为移动的坐标系
    robot_base_frame: camera_link # 机器人的base link ,我们在静态tf发布的时候有设置base_link为基础坐标系
    update_frequency: 2.0
    publish_frequency: 2.0
    static_map: false #这个地方我们的静态地图选为false ,因为局部地图是随时变化的因为某些东西突然出现需要随时变化,于此同时,全局地图该参数必须与此值相反
    rolling_window: true
    width: 4.0
    height: 4.0
    resolution: 0.025
    origin_x: -2.0
    origin_y: -2.0
    transform_tolerance: 3
    planner_frequency: 1.0
    planner_patiente: 5.0

    # observation_sources: scan
    # scan: {
    # sensor_frame: kinect2_link,
    # data_type: LaserScan,
    # topic: /scan ,
    # expected_update_rate: 0.5,
    # observation_persistence: 0.0,
    # marking: true,
    # clearing: true,
    # min_obstacle_height: -99999.0,
    # max_obstacle_height: 99999.0
    # }
  • 在上述文件中,有用于机器人的大小设置,代价地图的边缘配置,

    上位机和下位机得ros master 设置,

  • 在对于上位机和下位机的配置上,我们使用了最常见的配置方式,网络的方式进行链接(同时又一种是基于arduino 的控制方式,他是基于串口的方式来处理的,同时他对于底部轮子的驱动,在ros中有一些写好的驱动)
  • 上位机 (都在bashrc 中配置,也就是你的shell的配置文件,如果你的默认bash 是zsh 则在zshrc 里面配置就行) export ROS_IP=192.169.137.43 ; export ROS_MASTER_URI=http://192.168.137.43:11311 上位机作为主机
  • 下位机 export ROS_IP=192.168.137.44 ;export ROS_MASTER_URI=http://192.168.137.43:11311

  • 问题,如果配置好了后,source .bashrc 加载进配置,同时假如我直接在下机执行ros的操作的时候,他会去上位机请求roscore 管理信息,但是由于未启动,他会一直等待,故会出现输入ros命令后无法无反应的情况。

  • 解决便是在启动应用前提前将应用的master启动起来。

    下位机对于轮子驱动得设置

  • 轮子的驱动,我们的轮子电机是使用的jtag 370 的电机,没有标转速,但是应该是120的,如果有需要大家可以去店家那里询问,我问了店家没有回我。然后电机的驱动模块。没啥好说的,就是电机驱动,,一共有三个输入,两个控制正传反转的接口,一个控制pwm输入。

  • gpio

  • 然后AIN1 AIN2 控制一个轮子的前进,AIN1=1 AIN2=0 正传,AIN1=0 AIN2=1 反转(同时为零 不转,利用电机的驱动模块来实现,)
  • 代码实现
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    # -*- coding: utf-8 -*-

    import rospy
    from geometry_msgs.msg import Twist # velocity

    from duty_cycle import DutyCycle
    from raspberry_wheel import Raspberry

    cycle = DutyCycle()

    raspberry = Raspberry()


    def callback(msg):
    # INFO 2019/7/11 20:09 liliangbin 设置树莓派引脚的输出 。
    print 'msg.linear.x==>', msg.linear.x, 'z==>', msg.angular.z, '\n'

    left_dc, right_dc = cycle.calculate_pub(msg)
    raspberry.run(left_dc, right_dc)
    # 对数据进行处理,主要是轮子速度的计算,以及转速的修改。代码就补贴了,我把github的项目仍上面

    try:

    rospy.init_node('topic_subscriber')

    sub = rospy.Subscriber('cmd_vel', Twist, callback)
    # 这个地方有一个坑,我github上未修改,就是订阅消息的时候让队列里面的内容缓存只有一个,这样会让数据总是最新的数据,避免出现消息和内容不同步的情况,明明消息已经发送完毕了,同时叫他停止了,但是由于消息未处理完,让车还在运行,qune_size=1
    rospy.spin()

    except KeyboardInterrupt:

    raspberry.stop()

把摄像头得数据传输到网页中,利用网页来进行控制,(robotwebtools, 一个组织,专门是来做这一块的,虽然有很多的坑)

  • 一言难尽,这个地方最恶心的就是他给的代码里面相关的js代码不能用的情况,但是在视频上传上还是可以的。
  • 代码我后期再上传一波。

代码部分: