赞
踩
主要针对大学生智能车线上仿真赛;
模型使用的是智能车竞赛官方提供的仿真模型:
https://gitee.com/zeende/racecar_sim/tree/noetic/
代码模型实现:
<!-- 设置launch文件的参数 -->
<arg name="paused" default="false"/>
<arg name="use_sim_time" default="true"/>
<arg name="gui" default="true"/>
<arg name="headless" default="false"/>
<arg name="debug" default="false"/>
<!--机器人的起点放置位置-->
<arg name="x_pos" default="-0.5"/>
<arg name="y_pos" default="0"/>
<arg name="z_pos" default="0.0"/>
<!--运行gazebo仿真环境-->
<include file="$(find gazebo_ros)/launch/empty_world.launch">
<arg name="debug" value="$(arg debug)" />
<arg name="gui" value="$(arg gui)" />
<arg name="paused" value="$(arg paused)"/>
<arg name="use_sim_time" value="$(arg use_sim_time)"/>
<arg name="headless" value="$(arg headless)"/>
<arg name="world_name" value="$(find racecar_description)/worlds/racetrack.world"/>
</include>
<!-- 加载机器人模型描述参数 -->
<param name="robot_description" command="$(find xacro)/xacro --inorder '$(find racecar_description)/urdf/racecar.urdf.xacro'"/>
<!-- 在gazebo中加载机器人模型-->
<node name="urdf_spawner" pkg="gazebo_ros" type="spawn_model" respawn="false" output="screen"
args="-urdf -model racecar -param robot_description -x $(arg x_pos) -y $(arg y_pos) -z $(arg z_pos)"/>
用于之后在rviz中显示,以及提供关节接口;
<!--运行joint_state_publisher节点,发布机器人关节状态-->
<node name= "robot_state_publisher" pkg= "robot_state_publisher" type= "robot_state_publisher">
<param name="publish_frequency" type="double" value="20.0" />
<remap from="/joint_states" to="/racecar/joint_states"/>
</node>
此时我们启动launch文件:
roslaunch bringup racecar_gazebo.launch
此时,可能会遇到部分问题;
有些开发者在执行gazebo时,会闪退,并出现如下问题,
[gazebo_gui-3] process has died [pid 7811, exit code 134, cmd /opt/ros/kinetic/lib/gazebo_ros/gzclient __name:=gazebo_gui __log:=/home/ubuntu/.ros/log/4570ac34-0278-11ed-917f-000c298f0f5f/gazebo_gui-3.log].
我们可以通过以下方式进行解决:
方式一:
gazebo启用3D加速选项方面存在一些问题,可从VM设置中禁用设置3D加速选项。禁用该选项后,仿真环境运行会比较缓慢,但可以正常工作。如图所示:
方式二:更改SVGA_VGPU10变量:
先在终端执行:
export SVGA_VGPU10=0
然后再执行roslaunch语句即可。其实,更改SVGA_VGPU10变量是为了告诉系统OpenGL版本。
尝试两种方式,然后看看哪个更适合。如果要使用此选项避免每次启动终端时都设置此变量,只需将此命令添加到.bashrc中即可。
export SVGA_VGPU10=0" >> ~/.bashrc
然后正常roslaunch即可启动仿真环境。
ROS中提供了丰富的机器人应用:SLAM、导航、MoveIt…但是你可能一直有一个疑问,这些功能包到底应该怎么样用到我们的机器人上,也就是说在应用和实际机器人或者机器人仿真器之间,缺少一个连接两者的东西。
ros_control就是ROS为用户提供的应用与机器人之间的中间件,包含一系列控制器接口、传动装置接口、硬件接口、控制器工具箱等等,可以帮助机器人应用快速落地,提高开发效率。
因为联合控制器参数比较多,一般会通过在racecar.launch文件中加载yaml文件进行配置:
<!-- 从yaml文件加载联合控制器的参数 -->
<rosparam file="$(find bringup)/config/ctrl.yaml" command="load"/>
同时需要加载控制器:
<!-- 加载控制器 spawner -->
<node name="controller_manager" pkg="controller_manager" type="spawner"
respawn="false" output="screen" ns="/racecar"
args="left_rear_wheel_velocity_controller right_rear_wheel_velocity_controller
left_front_wheel_velocity_controller right_front_wheel_velocity_controller
left_steering_hinge_position_controller right_steering_hinge_position_controller
joint_state_controller"/>
此处,我们在功能包中增加config文件夹,增加ctrl.yaml文件,用以参数配置:
racecar: # 命名空间 # Publish all joint states --公布所有-------------------- joint_state_controller: type: joint_state_controller/JointStateController publish_rate: 50 # Velocity Controllers ----速度控制器--------------------- left_rear_wheel_velocity_controller: type: effort_controllers/JointVelocityController joint: left_rear_axle pid: {p: 1.5, i: 0.0, d: 0.0, i_clamp: 0.0} right_rear_wheel_velocity_controller: type: effort_controllers/JointVelocityController joint: right_rear_axle pid: {p: 1.5, i: 0.0, d: 0.0, i_clamp: 0.0} left_front_wheel_velocity_controller: type: effort_controllers/JointVelocityController joint: left_front_axle pid: {p: 0.7, i: 0.0, d: 0.0, i_clamp: 0.0} right_front_wheel_velocity_controller: type: effort_controllers/JointVelocityController joint: right_front_axle pid: {p: 0.7, i: 0.0, d: 0.0, i_clamp: 0.0} # Position Controllers ---位置控制器----------------------- left_steering_hinge_position_controller: joint: left_steering_joint type: effort_controllers/JointPositionController pid: {p: 10.0, i: 0.0, d: 0.5} right_steering_hinge_position_controller: joint: right_steering_joint type: effort_controllers/JointPositionController pid: {p: 10.0, i: 0.0, d: 0.5}
注意:此处命名空间要和launch文件中的namespace(ns)一致。
参数args标签中的6个话题名称就是我们用户控制的关节。
至此,机器人就可以实现关节控制。
对于阿克曼结构机器人收到的控制指令是速度和前轮转向角,因此我们应该使用ackermann_msgs/AckermannDriveStamped而不是geometry_msgs/Twist;
此时我们需要安装:
ubuntu@ubuntu:~$ rosmsg show ackermann_msgs/AckermannDriveStamped
std_msgs/Header header
uint32 seq
time stamp
string frame_id
ackermann_msgs/AckermannDrive drive
float32 steering_angle
float32 steering_angle_velocity
float32 speed
float32 acceleration
float32 jerk
而不是:
ubuntu@ubuntu:~$ rosmsg show geometry_msgs/Twist
geometry_msgs/Vector3 linear
float64 x
float64 y
float64 z
geometry_msgs/Vector3 angular
float64 x
float64 y
float64 z
ubuntu@ubuntu:~$ sudo apt install ros-kinetic-slam-gmapping
编写启动建图的launch文件。
<?xml version="1.0"?>
<launch>
<include file="$(find bringup)/launch/gazebo/racecar.launch"></include>
<node name="rviz" pkg="rviz" type="rviz"
args="-d $(find bringup)/rviz/racecar_urdf.rviz" required="true"/>
<node name="gazebo_odometry" pkg="racecar_description" type="gazebo_odometry.py"/>
</launch>
解读:
name="gazebo_odometry"
增加里程计节点;
<?xml version="1.0"?> <launch> <!-- 设置launch文件的参数 --> <arg name="paused" default="false"/> <arg name="use_sim_time" default="true"/> <arg name="gui" default="true"/> <arg name="headless" default="false"/> <arg name="debug" default="false"/> <!--模型车的起点放置位置--> <arg name="x_pos" default="-0.5"/> <arg name="y_pos" default="0"/> <arg name="z_pos" default="0.0"/> <!--运行gazebo仿真环境--> <include file="$(find gazebo_ros)/launch/empty_world.launch"> <arg name="debug" value="$(arg debug)" /> <arg name="gui" value="$(arg gui)" /> <arg name="paused" value="$(arg paused)"/> <arg name="use_sim_time" value="$(arg use_sim_time)"/> <arg name="headless" value="$(arg headless)"/> <arg name="world_name" value="$(find racecar_description)/worlds/racetrack.world"/> <!-- .world文件的地址--> </include> <!-- 加载机器人模型描述参数 --> <param name="robot_description" command="$(find xacro)/xacro --inorder '$(find racecar_description)/urdf/racecar.urdf.xacro'"/> <!--运行joint_state_publisher节点,发布机器人关节状态--> <!--<node name = "robot_state_publisher" pkg = "robot_state_publisher" type = "state_publisher">--> <node name= "robot_state_publisher" pkg= "robot_state_publisher" type= "robot_state_publisher"> <param name="publish_frequency" type="double" value="20.0" /> <remap from="/joint_states" to="/racecar/joint_states"/> </node> <!-- 在gazebo中加载机器人模型--> <node name="urdf_spawner" pkg="gazebo_ros" type="spawn_model" respawn="false" output="screen" args="-urdf -model racecar -param robot_description -x $(arg x_pos) -y $(arg y_pos) -z $(arg z_pos)"/> <!-- 从yaml文件加载联合控制器的参数 --> <rosparam file="$(find bringup)/config/ctrl.yaml" command="load"/> <!-- 加载控制器 spawner --> <node name="controller_manager" pkg="controller_manager" type="spawner" respawn="false" output="screen" ns="/racecar" args="left_rear_wheel_velocity_controller right_rear_wheel_velocity_controller left_front_wheel_velocity_controller right_front_wheel_velocity_controller left_steering_hinge_position_controller right_steering_hinge_position_controller joint_state_controller"/> <!-- 阿克曼的消息类型对应到机器人关节话题的发布 --> <node pkg="racecar_description" type="servo_commands.py" name="servo_commands" output="screen"> </node> </launch>
<launch> <arg name="scan_topic" default="scan" /> <!--雷达话题--> <arg name="base_frame" default="base_footprint"/> <!--小车在底盘的映射坐标--> <arg name="odom_frame" default="odom"/> <!--发布的里程计坐标系--> <param name="use_sim_time" value="false"/> <node pkg="gmapping" type="slam_gmapping" name="slam_gmapping" output="screen"> <param name="base_frame" value="$(arg base_frame)"/> <!--底盘坐标系--> <param name="odom_frame" value="$(arg odom_frame)"/> <!--里程计坐标系--> <!--remap from="scan" to="base_scan"/--> <param name="map_update_interval" value="5.0"/> <!--更新时间(s),每多久更新一次地图,不是频率--> <param name="maxUrange" value="14.0"/> <!--激光雷达最大可用距离,在此之外的数据截断不用--> <param name="sigma" value="0.05"/> <param name="kernelSize" value="1"/> <param name="lstep" value="0.05"/> <param name="astep" value="0.05"/> <param name="iterations" value="5"/> <param name="lsigma" value="0.075"/> <param name="ogain" value="3.0"/> <param name="lskip" value="0"/> <param name="srr" value="0.01"/> <param name="srt" value="0.02"/> <param name="str" value="0.01"/> <param name="stt" value="0.02"/> <param name="linearUpdate" value="0.5"/> <param name="angularUpdate" value="0.218"/> <param name="temporalUpdate" value="5.0"/> <param name="resampleThreshold" value="0.5"/> <param name="particles" value="80"/> <param name="xmin" value="-1.0"/> <param name="ymin" value="-1.0"/> <param name="xmax" value="1.0"/> <param name="ymax" value="1.0"/> <param name="delta" value="0.05"/> <param name="llsamplerange" value="0.01"/> <param name="llsamplestep" value="0.01"/> <param name="lasamplerange" value="0.005"/> <param name="lasamplestep" value="0.005"/> </node> </launch>
在三个终端中运行以下三个 launch:
ubuntu@ubuntu:~$ roslaunch bringup racecar_gazebo_rviz.launch
ubuntu@ubuntu:~/racecar_sim$ rosrun racecar_description keyboard_teleop.py
ubuntu@ubuntu:~$ roslaunch bringup slam_gmapping.launch
运行第一条指令后,会打开gazebo及rviz。
rqt_graph
此时启动第二条指令,开始按键控制;
增加了按键控制节点;
再启动第三条指令,可以看到地图显示由黑色,变成灰色路径;
通过按键控制,将小车从起点移动到终点;此时我们完成的地图的构建;
地图构建完成后,需要保存地图;
此时开启新的终端运行:
ubuntu@ubuntu:~/racecar_sim$ rosrun map_server map_saver -f /home/ubuntu/racecar_sim/src/bringup/map/map
[ INFO] [1657961143.594741695]: Waiting for the map
[ INFO] [1657961143.814344370]: Received a 1184 X 480 map @ 0.050 m/pix
[ INFO] [1657961143.814478020]: Writing map occupancy data to /home/ubuntu/racecar_sim/src/bringup/map/map.pgm
[ INFO] [1657961143.857679615]: Writing map occupancy data to /home/ubuntu/racecar_sim/src/bringup/map/map.yaml
[ INFO] [1657961143.859262512]: Done
此时会在相应路径下生成两个map相关的文件:
其中map.pgm为地图图片;
map.yaml为方便加载的参数文件;
image: /home/ubuntu/racecar_sim/src/bringup/map/map.pgm
resolution: 0.050000
origin: [-12.200000, -12.200000, 0.000000]
negate: 0
occupied_thresh: 0.65
free_thresh: 0.196
image: 表示图片路径;
resolution: 地图分辨率 单位:米/像素;
origin: 图像左下角在地图坐标下的坐标
negate: 是否应该颠倒 白:自由/黑:的语义(阈值的解释不受影响)
occupied_thresh: 占用概率大于此阈值的像素被认为已完全占用
free_thresh: 占用率小于此阈值的像素被认为是完全空闲的
move_base框架主要是为ROS提供导航相关的配置、运行、交互的接口;
方法一:
sudo apt-get install ros-kintic-teb-local-planner (安装包)
rosdep install teb_local_planner(安装依赖)
参考文件:
http://t.zoukankan.com/long5683-p-11404576.html
最好安装整个navigation功能包
因为存在大量的导航配置参数,因此会分类写到各个参数文件内。
参考:
https://hermit.blog.csdn.net/article/details/117669476
teb使用的特点:
导航算法一般针对不通结构会用侧重,例如常规的移动机器人底盘结构设计为差速结构,这样会适用于多数常见算法,如base_local_planner、dwa_local_planner等,单数对于阿克曼结构,它的特点是存在最小转弯半径的限制,这样就导致常见的算法并不合适,由此teb_local_planner比较合适。
teb_local_planner提供了一种car-like的动力学模型,就是像汽车一样存在最小转弯半径限制,这样它就可以完成阿克曼结构的动力学解算。
参数文件说明:
首先查看move_base.launch,里面加载了此处所有的yaml文件。
<launch> <!--启动move_base节点,然后加载参数文件--> <node pkg="move_base" type="move_base" respawn="false" name="move_base" output="screen"> <rosparam file="$(find bringup)/param/costmap_common_params.yaml" command="load" ns="global_costmap" /> <rosparam file="$(find bringup)/param/costmap_common_params.yaml" command="load" ns="local_costmap" /> <rosparam file="$(find bringup)/param/local_costmap_params.yaml" command="load" /> <rosparam file="$(find bringup)/param/global_costmap_params.yaml" command="load" /> <rosparam file="$(find bringup)/param/teb_local_planner_params.yaml" command="load" /> <rosparam file="$(find bringup)/param/move_base_params.yaml" command="load" /> <!--设置局部路径规划器为TeblocalPlanner--> <param name="base_local_planner" value="teb_local_planner/TebLocalPlannerROS" /> <!--<param name="controller_frequency" value="10" /> <param name="controller_patiente" value="15.0"/>--> </node> <node name="map_server" pkg="map_server" type="map_server" args="$(find bringup)/map/map.yaml" output="screen"> <param name="frame_id" value="map"/> </node> <!--<node pkg="tf" type="static_transform_publisher" name="odom_to_map" args="0 0 0 0 0 0 1 /odom /map 100" />--> <!--<include file="$(find bringup)/launch/robot_amcl.launch.xml" />--> <node name="nav_sim" pkg="racecar_description" type="nav_sim.py" > </node> <arg name="use_map_topic" default="True"/> <arg name="scan_topic" default="/scan"/> <arg name="initial_pose_x" default="-0.5"/> <arg name="initial_pose_y" default="0.0"/> <arg name="initial_pose_a" default="0.0"/> <arg name="odom_frame_id" default="odom"/> <arg name="base_frame_id" default="base_footprint"/> <arg name="global_frame_id" default="map"/> <node pkg="amcl" type="amcl" name="amcl"> <param name="use_map_topic" value="$(arg use_map_topic)"/> <!-- Publish scans from best pose at a max of 10 Hz --> <param name="odom_model_type" value="diff"/> <param name="odom_alpha5" value="0.1"/> <param name="gui_publish_rate" value="10.0"/> <param name="laser_max_beams" value="810"/> <param name="laser_max_range" value="-1"/> <param name="min_particles" value="500"/> <param name="max_particles" value="5000"/> <param name="kld_err" value="0.05"/> <param name="kld_z" value="0.99"/> <param name="odom_alpha1" value="0.2"/> <param name="odom_alpha2" value="0.2"/> <!-- translation std dev, m --> <param name="odom_alpha3" value="0.2"/> <param name="odom_alpha4" value="0.2"/> <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_model_type" value="likelihood_field"/> <!-- <param name="laser_model_type" value="beam"/> --> <param name="laser_likelihood_max_dist" value="2.0"/> <param name="update_min_d" value="0.1"/> <param name="update_min_a" value="0.2"/> <param name="odom_frame_id" value="$(arg odom_frame_id)"/> <param name="base_frame_id" value="$(arg base_frame_id)"/> <param name="global_frame_id" value="$(arg global_frame_id)"/> <param name="resample_interval" value="1"/> <!-- Increase tolerance because the computer can get quite busy --> <param name="transform_tolerance" value="1.0"/> <param name="recovery_alpha_slow" value="0.0"/> <param name="recovery_alpha_fast" value="0.0"/> <param name="initial_pose_x" value="$(arg initial_pose_x)"/> <param name="initial_pose_y" value="$(arg initial_pose_y)"/> <param name="initial_pose_a" value="$(arg initial_pose_a)"/> <remap from="/scan" to="$(arg scan_topic)"/> <remap from="/tf_static" to="/tf_static"/> </node> </launch>
解读yaml:
ubuntu@ubuntu:~$ roslaunch bringup racecar_gazebo_rviz.launch
ubuntu@ubuntu:~$ roslaunch bringup move_base.launch
启动2D Nav Goal,开始导航,可以看到绿色为路径规划。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。