说明:本文所示多为记忆中步骤,实际安装可能存在小问题,欢迎评论区交流。另autoware部分并未详细说明,最后测试的自动驾驶案例,其gf_global_planner与gf_decision_maker是参照autoware源码自己写的规划与决策节点,官方autoware源码中并不包含。这两部分源码还在完善中,后期会在本专栏中发布源码,欢迎关注。如有错误,欢迎指正。
版本信息: Carla 0.9.11 、Ros melodic、Autoware 1.14
1. Carla安装
这里推荐carla0.9.11,因为0.9.12版本明显比0.9.11版本更加占用电脑资源,而且carla ros bridge目前只更新到0.9.11版本。(carla 与ros bridge版本需要对应)。
下载地址:
最全学习资料 https://gitee.com/studywangkeba/zdjs
AdditionalMap可以不用。
下载完成后,解压,终端执行./CarlaUE4.sh即可运行,但不排除电脑出现缺少依赖的情况,按错误提示下载相应的依赖即可。
2. Carla Ros Bridge安装
官方教程:
CARLA Simulatorcarla.readthedocs.io/projects/ros-bridge/en/latest/
(1) 创建工作空间 https://gitee.com/studywangkeba/zdjs
mkdir -p ~/carla-ros-bridge/catkin_ws/src
(2) 获取ros bridge源码
cd ~/carla-ros-bridge
这里直接去0.9.11版本的源码即可。
https://gitee.com/studywangkeba/zdjs
下载github.com/carla-simulator/ros-bridge/releases
然后把它解压后改文件夹名为ros-bridge,放到~/carla-ros-bridge中,与catkin_ws文件夹并列,然后
cd catkin_ws/src
ln -s ../../ros-bridge
(3) source ros环境
source /opt/ros/melodic/setup.bash
(4) 安装依赖(需要翻墙)
cd ~/carla-ros-bridge/catkin_ws
rosdep update
rosdep install --from-paths src --ignore-src -r
(5) 编译源码
catkin build
(6) 测试:
测试之前要讲carla的egg文件路径加入到.bashrc中:
export PYTHONPATH=$PYTHONPATH:/xxx/xxx/CARLA_0.9.11/PythonAPI/carla/dist/carla-0.9.11-py2.7-linux-x86_64.egg
这个用于选择运行carla ros bridge的python版本,需要和你安装刚才依赖的版本一致,这里推荐2.7版本,因为autoware多基于2.7版本。
首先启动carla
然后进入~/carla-ros-bridge/catkin_ws路径:
source devel/setup.bash
roslaunch carla_ros_bridge carla_ros_bridge_with_example_ego_vehicle.launch
即可启动,可以在rviz中查看各个数据。这时候可能会提示找不到pygame等模块,按照错误提示用pip2 install安装即可。
参考链接:
https://gitee.com/studywangkeba/zdjs
3. 编写Carla-Autoware bridge以及ros bridge源码修改
以下部分秉持尽量不修改Carla ros bridge源码的原则,使用话题转发的方式,将carla中的数据适配到autoware。
下链接为该Carla ros bridge的官方文档。
CARLA Simulatorcarla.readthedocs.io/projects/ros-bridge/en/latest/
(1) carla车载传感器调整:
因为Carla ros bridge中默认添加了全部的传感器 相机、雷达、语义雷达、毫米波雷达、深度相机等等,所以会占用大量的系统资源,修改下相应的代码,只保留需要的传感器可以很有效的提升运行流畅度。
调整方式:定位到carla-ros-bridge/ros-bridge/carla_spawn_objects/config目录下的objects.json文件中的:
"type": "vehicle.tesla.model3",
"id": "ego_vehicle",
"sensors":
这里是传感器的安装位置和配置信息,需保留rgb_view,其余可以自行删减,因为rgb_view的数据会用于pygame的界面显示,删掉pygame就黑屏啦。删减的方式就是直接删除对应的[]元素,不用修改python脚本(注意备份)。各个模块的参数含义不再赘述。
(2) 话题转发
需要进行话题转发的原因是:ros bridge的脚本中对各个传感器话题的frame做了设定,而且各个frame之间的tf关系同样固定,可以通过脚本修改,但是这些源码分布在很多地方,修改不易,更好的选择是进行话题转发的同时,修改frame名称和frame的tf关系。
话题转发包括2个部分,一个是传感器数据的话题转发,另一个是autoware规划后的控制指令geometry::TwistStamped,转换为carla的控制指令。
carla ros bridge中提供了carla twist to contral节点,这个节点用于将geometry::Twist 类型的ros消息转化为carla中车辆的控制指令,但是autoware规划器输出的控制命令为geometry::TwistStamped类型,做一个简单的转换即可。下面是carla twist to contral节点的说明。
该部分源码如下(自己写的):
//
// Created by y on 9/6/21.
//
#include <ros/ros.h>
#include <iostream>
#include "sensor_msgs/Imu.h"
#include "sensor_msgs/PointCloud2.h"
#include "geometry_msgs/TwistStamped.h"
#include "geometry_msgs/Twist.h"
#include <tf/transform_broadcaster.h>
#include <tf/transform_datatypes.h>
//定义发接收者
ros::Subscriber imu_sub;
ros::Subscriber lidar_sub;
ros::Subscriber twist_sub;
//定义发送者
ros::Publisher imu_adv;
ros::Publisher lidar_adv;
ros::Publisher twist_adv;
//定义话题名称
const std::string IMU_TOPIC = "/carla/ego_vehicle/imu";//这些是carla ros bridge发出的ros topic
const std::string LIDAR_TOPIC = "/carla/ego_vehicle/lidar";
const std::string TWIST_TOPIC = "/twist_cmd";//订阅autoware的控制指令,TwistStamped,把它转成carla ros bridge的控制指令Twist
geometry_msgs::Twist m_twist;
void imu_callback(const sensor_msgs::Imu::Ptr &imu_msg)//imu数据回调
{
imu_msg->header.frame_id = "imu";//更换frame名称
imu_msg->header.stamp = ros::Time::now();
imu_adv.publish(*imu_msg);
}
void lidar_callback(const sensor_msgs::PointCloud2::Ptr& lidar_msg)//lidar数据回调
{
lidar_msg->header.frame_id = "lidar";
lidar_msg->header.stamp = ros::Time::now();
lidar_adv.publish(*lidar_msg);
}
//autoware发出的车辆控制指令,需要转化为ros bridge需要的geometry_msgs::Twist类型
void twist_callback(const geometry_msgs::TwistStamped::Ptr& twist_msg)//TwistStamped数据回调
{
m_twist.linear = twist_msg->twist.linear;
m_twist.angular = twist_msg->twist.angular;
twist_adv.publish(m_twist);
}
int main(int argc,char **argv){
ros::init(argc,argv,"Carla_Bridge");
ros::NodeHandle n;
imu_sub = n.subscribe(IMU_TOPIC,10000,imu_callback);
lidar_sub = n.subscribe(LIDAR_TOPIC,10000,lidar_callback);
twist_sub = n.subscribe(TWIST_TOPIC,10,twist_callback);
imu_adv = n.advertise<sensor_msgs::Imu>("/imu_raw", 10000);
lidar_adv = n.advertise<sensor_msgs::PointCloud2>("/points_raw", 10000);
twist_adv = n.advertise<geometry_msgs::Twist>("/carla/ego_vehicle/twist", 10);//ros bridge carla_twist_to_contral节点
ros::spin();
}
frame的tf关系在launch文件中修改:
<launch>
<node pkg="carla_bridge" type="carla_bridge" name="carla_bridge1"/>
<node pkg="tf" type="static_transform_publisher" name="lidar_baselink" args="0 0 1.0 0 0 0 base_link lidar 10" />
<node pkg="tf" type="static_transform_publisher" name="imu_baselink" args="-0.3 0 0.4 0 0 0 base_link imu 100" />
<node pkg="tf" type="static_transform_publisher" name="world_map" args="0 0 0 0 0 0 world map 10" />
</launch>
(3) 注释carla ros bridge 中位置二次初始化模块
原因:
在carla ros bridge中,Carla Spawn Objects节点下提供一项功能,当接收到2D pose initial话题(rviz中的2D Pose Estimate小按钮)后,会按照这个话题的位置和方向信息更新carla中车辆的位置,即使carla提供了点云图,用于rviz中的环境显示,但是carla仿真器与rviz中的坐标并不对应。简言之:在rviz中生成的位姿,很可能会导致carla中车辆从新初始化在不可预测的地方(比如生成在楼顶或者直接脱模)。
其次,在运行autoware中ndt_matching这些lidar定位节点时,需要使用rviz中的2D Pose Estimate进行初始位姿估计,一旦点了这个按钮,会导致carla中车辆位姿二次更新。所以,在没有找到rviz中点云图与carla仿真环境的坐标对应关系之前,还是注释掉位姿二次更新部分比较好。
脚本启动位置:carla_spawn_objects/launch/carla_example_ego_vehicle.launch,注释掉框起的部分即可。
(4) 联合运行
启动carla
启动carla ros bridge
启动autoware
启动 carla autoware bridge(话题转发功能包)
启动autoware中相应的节点(建图、规划等等均可):
在pygame界面关闭手动驾驶模式后,carla车辆即开始自动驾驶,上述内容验证完毕: