赞
踩
上个文章写了如何采用纯跟踪算法跟踪已知路径的整体项目流程,包括如何采集路径点,算法实现,底层模块通信等等,感兴趣的可以去看看我写的前两个文章,作为学习完C++,ROS不知道怎么入门机器人的同学是一个很好的上手项目。
链接: 无人车采用纯跟踪算法跟随离线路径(ROS,C++实现)第一部分
链接: 无人车采用纯跟踪算法跟随离线路径(ROS,C++实现)第二部分 实车验证
当时在文章中写了一个问题就是我的车必须指向一个位置的时候,它才能获取正确的坐标点,不然数据就会出现反向问题,后面成功完成了问题的定位,现在把这个自动驾驶坐标系转换进行整体梳理一遍。
定位传感器一般式以GPS等进行完成,该传感器获取的数据为经纬度处于WGS84坐标系下,因为网上有很多坐标系的介绍,我就不做多的介绍,只对跟踪离线路径这个项目中出现的问题进行解释,
本次无人车进行运动是以车辆起点为原点的东北天坐标系,所以需要对传感器获得的数据进行处理,转换为东北天坐标系:
之前转换方法:经纬度(LLA)转换成地心地固坐标系(ECEF)的坐标,地心地固坐标系(ECEF)的坐标转换成东北天(ENU)坐标系坐标。
当时完成这个操作后就已经结束了,实际上车辆在坐标系上的定位不仅仅是位置坐标,车辆的偏航角也是很重要的一个部分,东北天坐标实际上是把这个坐标系固定死,不论开头车辆偏航角指向何处,所以就会存在之前的坐标转换出现错误的问题,在进行控制,导航等过程中,是需要将车辆自身的车辆起始前进位置和这个X轴一致,这样就不会存在车辆车头不摆放正确就出现错误的问题。
解决方法:在完成东北天坐标系建立后,获取车辆的初始偏航角,经过旋转矩阵就可以完成修改后的东北天坐标系,后续坐标均在该坐标系下就可以成功完成。
LLA转ENC的C++代码如下 大家可以参考下
void huatcar ::GeoDetic_TO_ENU(double lat, double lon, double h, double lat0, double lon0, double h0, double enu_xyz[3]) { double a, b, f, e_sq; a = 6378137; b = 6356752.3142; f = (a - b) / a;e_sq = f * (2 - f); // 站点(非原点) double lamb, phi, s, N, sin_lambda, cos_lambda, sin_phi, cos_phi, x, y, z; lamb = lat; phi = lon; s = sin(lamb); N = a / sqrt(1 - e_sq * s * s); sin_lambda = sin(lamb); cos_lambda = cos(lamb); sin_phi = sin(phi); cos_phi = cos(phi); x = (h + N) * cos_lambda * cos_phi; y = (h + N) * cos_lambda * sin_phi; z = (h + (1 - e_sq) * N) * sin_lambda; // 原点坐标转换 double lamb0, phi0, s0, N0, sin_lambda0, cos_lambda0, sin_phi0, cos_phi0, x0, y0, z0; lamb0 = lat0; phi0 = lon0; s0 = sin(lamb0); N0 = a / sqrt(1 - e_sq * s0 * s0); sin_lambda0 = sin(lamb0); cos_lambda0 = cos(lamb0); sin_phi0 = sin(phi0); cos_phi0 = cos(phi0); x0 = (h0 + N0) * cos_lambda0 * cos_phi0; y0 = (h0 + N0) * cos_lambda0 * sin_phi0; z0 = (h0 + (1 - e_sq) * N0) * sin_lambda0; // ECEF 转 ENU double xd, yd, zd, t; xd = x - x0; yd = y - y0; zd = z - z0; t = -cos_phi0 * xd - sin_phi0 * yd; enu_xyz[0] = -sin_phi0 * xd + cos_phi0 * yd; enu_xyz[1] = t * sin_lambda0 + cos_lambda0 * zd; enu_xyz[2] = cos_lambda0 * cos_phi0 * xd + cos_lambda0 * sin_phi0 * yd + sin_lambda0 * zd; ROS_INFO("输出转换完成坐标"); cout << "current_x = "<<enu_xyz[0] <<"current_y = "<<enu_xyz[1]<<endl; points.push_back({enu_xyz[0],enu_xyz[1]}); }
后面的坐标转换就是进行一个旋转矩阵的处理,单纯以这个为可能鲁棒性不够,这样顶多是把车跑起来了,但是感觉属于投机取巧。
当时文章中也写到了在做的过程中存在的问题,当时一直没有解决,这段时间看了一套C++和ROS的可成后回过头来再看感觉有了一些思路,以这个课程配上这个项目,对没学C++,ROS和学完不知道做上的同学是非常好的入门项目,并且已知路径下的路径跟踪应用场景也广,如果有同学需要可以私信我一块学习。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。