ros安装
- ros 官网
- 这个时候我们需要修改ros的软件源为国内的软件源
- http://wiki.ros.org/ROS/Installation/UbuntuMirrors#USTC //ros 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
5unset 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
- sudo apt-get install ros-kinetic-rtabmap-ros
- https://github.com/introlab/rtabmap_ros # 或是使用博主官方给我们的链接安装,他里面有例子
安装kinect 驱动 libfreet2 iai_kinect
- 百度吧
- https://blog.csdn.net/weixin_41038905/article/details/80907580
- 或是直接去那俩的github官网查看
- 注意Kinect的时候我们有一个参数叫做 publish_tf 我们把他设置为true的时候发布的pointcloud数据才有坐标值
运行kinect2 跑rtabmap建图
确立基础的坐标变化以及camera_link 和kinect2_link 的位置
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 | roslaunch rtabmap_ros rgbd_mapping_kinect2.launch resolution:=qhd localization:=true //定位的方式打开 但是在使用过程种遇到了一些问题,选择放弃这个 |
- 启动可视化界面
1
2roslaunch rtabmap_ros demo_turtlebot_rviz.launch
# 在这里面为了得到一个可视化的二维地图,我们可以将map 选项修改为rtabmap/grid_map
导航模块
- move_base 需要输入的东西 ,odom cloud 然后再move_base还需要一个代价地图得输入。这个代价地图由我们这里输入
- 先说思路,(导航需要输入)
- 假激光,我们使用 depthimage_to_laserscan 包将来自Kinect2 的图像以及深度信息转化为scan 的数据类型。
(个人看法,我查看一个博主有说过,这个时候,我们可以修改rtabmap的启动参数,把他监听scan数据类型的参数打开,好像是一个 subscirbe_scan = true 就行。。但是感觉如果只是为了一个代价地图的话,假激光再输入给rtabmap的话,没有太大的意义,反而加大了计算机的计算量)
- 投影地图法,我们利用kinect2 的Kinect2/qhd/points 接口出来的带有坐标的cloud 信息,经过rtbmap 的 nodelet 转化后生成一个投影地图,作为局部地图的输入,其他的什么都不用修改。
- 假激光,我们使用 depthimage_to_laserscan 包将来自Kinect2 的图像以及深度信息转化为scan 的数据类型。
- 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
32TrajectoryPlannerROS:
# 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
40obstacle_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
7global_costmap:
global_frame: map # 世界坐标系
robot_base_frame: camera_link # base_link
update_frequency: 0.5
publish_frequency: 0.5
static_map: true
transform_tolerance: 3local_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
28local_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输入。
- 然后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代码不能用的情况,但是在视频上传上还是可以的。
- 代码我后期再上传一波。
代码部分:
- movebase—> https://github.com/liliangbin/move_base_rtab-map
- twist_to_wheel_speed —-> https://github.com/liliangbin/twist-to-wheel-speed
- 欢迎大家来玩耍啊,,,,