使用evo评估cartographer使用多线雷达和imu的纯定位精度

gps的定位原始数据的消息结构为vd_msgs::GpsRaw
将其转换为gps里程计,作为groundtruth

#include <deque>
#include <mutex>
#include <ros/ros.h>
#include <sensor_msgs/NavSatFix.h>
#include <sensor_msgs/Imu.h>
#include <nav_msgs/Odometry.h>
#include <geometry_msgs/Twist.h>
#include <tf/transform_broadcaster.h>
#include <tf/transform_datatypes.h>
#include "GeographicLib/LocalCartesian.hpp"
#include <vd_msgs/GpsRaw.h>

GeographicLib::LocalCartesian geo_converter;
ros::Publisher  odom_pub_;
ros::Publisher imu_pub_;
vd_msgs::GpsRaw gps_raw;

double lat = 0;
double lon = 0;
double alt = 0;
bool enable_z = false;


void gpsRawCalback(const vd_msgs::GpsRaw msg)
{
  gps_raw = msg;

  nav_msgs::Odometry real_gps_odom;

  real_gps_odom.header.stamp = gps_raw.header.stamp;
  real_gps_odom.header.frame_id = "odom";
  real_gps_odom.child_frame_id  = "gps_link_compare";

  geometry_msgs::Quaternion catch_orientation;

  catch_orientation = tf::createQuaternionMsgFromRollPitchYaw
                            (gps_raw.Vector.x, gps_raw.Vector.y, gps_raw.Vector.z);
/*   catch_orientation = tf::createQuaternionMsgFromRollPitchYaw
                            (0, 0, gps_raw.Vector.z); */
  real_gps_odom.pose.pose.orientation = catch_orientation;

  double local_E = 0;
  double local_N = 0;
  double local_U = 0;
  geo_converter.Forward(gps_raw.Latitude, gps_raw.Longitude, gps_raw.Altitude, local_E, local_N, local_U);

  real_gps_odom.pose.pose.position.x = local_E;
  real_gps_odom.pose.pose.position.y = local_N;
  if(enable_z) {
    real_gps_odom.pose.pose.position.z = local_U;
  } else {
    real_gps_odom.pose.pose.position.z = 0;
  }
  

  real_gps_odom.twist.twist.linear.x = gps_raw.Vv;
  real_gps_odom.twist.twist.linear.y = 0;
  real_gps_odom.twist.twist.linear.z = 0;
  // 应该是角速度,非角度,还需要修改
  // real_gps_odom.twist.twist.angular = gps_raw.Imu.angular;  

  odom_pub_.publish(real_gps_odom);

  sensor_msgs::Imu imu_data;

  imu_data.header.stamp = gps_raw.header.stamp;
  imu_data.header.frame_id = "imu_link";

  imu_data.orientation = catch_orientation;

/*   imu_data.angular_velocity.x = 0;
  imu_data.angular_velocity.y = 0;
  imu_data.angular_velocity.z = gps_raw.Imu.linear.z* M_PI / 180.0;

  imu_data.linear_acceleration.x = gps_raw.Imu.angular.x;
  imu_data.linear_acceleration.y = gps_raw.Imu.angular.y;
  imu_data.linear_acceleration.z = gps_raw.Imu.angular.z; */

  imu_data.angular_velocity.x = gps_raw.Imu.linear.x* M_PI / 180.0;
  imu_data.angular_velocity.y = gps_raw.Imu.linear.y* M_PI / 180.0;
  imu_data.angular_velocity.z = gps_raw.Imu.linear.z* M_PI / 180.0;

  imu_data.linear_acceleration.x = gps_raw.Imu.angular.x;
  imu_data.linear_acceleration.y = gps_raw.Imu.angular.y;
  imu_data.linear_acceleration.z = gps_raw.Imu.angular.z;

  imu_pub_.publish(imu_data);

}

int main(int argc, char* argv[]) 
{
  ros::init(argc, argv, "odom_gps_dy");
  ros::NodeHandle nh;

  ros::Subscriber gps_raw_sub_ = nh.subscribe("/navsat_dy/gps_raw", 100, gpsRawCalback);
  odom_pub_    = nh.advertise<nav_msgs::Odometry>("/odom/by_gps", 100);
  imu_pub_ = nh.advertise<sensor_msgs::Imu>("/imu/data", 100);

  nh.param("/odom_gps_dy/latitude",   lat , 28.1077029);
  nh.param("/odom_gps_dy/longitude",  lon , 112.8735103);
  nh.param("/odom_gps_dy/altitude",   alt , 37.6);
  nh.param("/odom_gps_dy/use3d",      enable_z , false);

/*   nh.param("/odom_gps_dy/latitude",   lat , 28.18593249);112.8735103
  nh.param("/odom_gps_dy/longitude",  lon , 112.9446714);
  nh.param("/odom_gps_dy/altitude",   alt , 37.6);
  nh.param("/odom_gps_dy/use3d",      enable_z , false); */

  if(lat == 28.18593249){
    ROS_WARN_STREAM ( "no set gnss origin!");
  }else{
    ROS_INFO("set gnss origin > lat:%lf, lat:%lf, lat:%lf\n", lat, lon, alt);
  }
  
  geo_converter.Reset(lat, lon, alt);

  ros::spin();
  return 0;
}

carto使用多线雷达和imu纯定位如下,获得carto里程计
https://blog.csdn.net/zhaohaowu/article/details/120889458
将carto里程计和gps里程计分别转换为tum数据的轨迹,方便使用evo评估
自定义消息结构为carto_test::odom2tum

float32 x
float32 y
float32 z
float32 q_x
float32 q_y
float32 q_z
float32 q_w

代码如下:

#include <ros/ros.h>
#include <nav_msgs/Odometry.h>
#include "carto_test/odom2tum.h"
ros::Publisher pub_gps;
ros::Publisher pub_carto;

void callback_gps(const nav_msgs::Odometry::ConstPtr& odom)
{
    carto_test::odom2tum msg;
    msg.x = odom->pose.pose.position.x;
    msg.y = odom->pose.pose.position.y;
    msg.z = odom->pose.pose.position.z;
    msg.q_x = odom->pose.pose.orientation.x;
    msg.q_y = odom->pose.pose.orientation.y;
    msg.q_z = odom->pose.pose.orientation.z;
    msg.q_w = odom->pose.pose.orientation.w;
    pub_gps.publish(msg);
    ROS_INFO("gps ok");
}
void callback_carto(const nav_msgs::Odometry::ConstPtr& odom)
{
    carto_test::odom2tum msg;
    msg.x = odom->pose.pose.position.x;
    msg.y = odom->pose.pose.position.y;
    msg.z = odom->pose.pose.position.z;
    msg.q_x = odom->pose.pose.orientation.x;
    msg.q_y = odom->pose.pose.orientation.y;
    msg.q_z = odom->pose.pose.orientation.z;
    msg.q_w = odom->pose.pose.orientation.w;
    pub_carto.publish(msg);
    ROS_INFO("carto ok");
}
int main (int argc, char **argv)
{
    ros::init (argc, argv, "odom2tum");
    ros::NodeHandle n;

    pub_gps = n.advertise<carto_test::odom2tum>("tum_gps", 10, true);
    pub_carto = n.advertise<carto_test::odom2tum>("tum_carto", 10, true);
    ros::Subscriber sub_gps = n.subscribe<nav_msgs::Odometry>("/odom/by_gps", 10, callback_gps);
    ros::Subscriber sub_carto = n.subscribe<nav_msgs::Odometry>("/carto_odom", 10, callback_carto);
    ros::Rate loop_rate(50);
    while(ros::ok())
    {
        ros::spinOnce();
        loop_rate.sleep();
    }
    return 0;
}

然后将转换后的话题tum_gps和tum_gps转换为tum格式的txt

rostopic echo -b tum_gps_carto.bag -p /tum_carto > tum_carto.txt
rostopic echo -b tum_gps_carto.bag -p /tum_gps > tum_gps.txt

在txt中,ctrl+h替换所有的逗号,为空格
使用evo评估,evo使用方法如下
测量指标:
evo_ape:绝对位姿误差
evo_rpe:相对位姿误差
常用命令:
evo_traj:绘制轨迹,一条或多条,支持kitti,eurco,tum三种格式
evo_res:根据指标比较分析不同SLAM方案轨迹输出结果
不常用命令:
evo_fig:重新打开序列化图的工具
evo_config:用于全局设置和配置文件操作的工具
参数:
-p或–plot: 绘图
-v或–verbose: 输出相关信息(均值,方差等)
-f或–full_check: 检查相关信息(时间戳是否对应,四元数是不是单位四元数)
-a或–align: 对轨迹进行对齐,用ICP的方法,并不是仅仅将起点对齐
–correct_scale: 尺度校正

evo_traj tum --ref=tum_gps.txt tum_carto.txt --plot --plot_mode=xy

在这里插入图片描述

使用evo进行校正,原理为icp

evo_traj tum --ref=tum_gps.txt tum_carto.txt --plot --plot_mode=xy --align --correct_scale 

在这里插入图片描述
绝对位姿误差ape

evo_ape tum tum_gps.txt tum_carto.txt --plot --plot_mode=xy

校正后的绝对位姿误差

evo_ape tum tum_gps.txt tum_carto.txt --plot --plot_mode=xy --align --correct_scale

相对位姿误差rpe
在这里插入图片描述
ape和rpe含义
ape绝对位姿误差:比较估计轨迹和参考轨迹并计算整个轨迹的统计数据,适用于测试轨迹的全局一致性
rpe相对位姿误差:相对位姿误差可以给出局部精度,例如slam系统每米的平移或者旋转漂移量

https://zhuanlan.zhihu.com/p/105428199
https://www.codenong.com/cs105316835/

在这里插入图片描述

  • 6
    点赞
  • 56
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 29
    评论
### 回答1: Cartographer是一个开源的、实时的、通用的SLAM(Simultaneous Localization and Mapping)系统,它可以用于机器人、自动驾驶车辆等领域的定位和地图构建。它支持多种传感器,如激光雷达、RGB-D相机等,并且可以在多种操作系统上运行。 ### 回答2: cartographer(制图师)是一种定位职业。制图师主要负责使用各种地理信息和测量数据,绘制出精确的地图。他们利用卫星影像、航空摄影、测量仪器和地面检查等工具和技术,收集和处理大量的地理数据。然后,他们使用专业的计算机软件,将这些数据转化为具有精确尺度和准确位置的图形表示。 制图师的主要任务是根据实地测量和其他可靠数据源,绘制出城市、国家、区域或整个地球的地形图、道路网络图、天文图、海洋图等各种类型的地图。他们还可以根据需要制作各种专题地图,如气候地图、土地利用地图、人口分布地图等。 在绘制地图的过程中,制图师需要准确测量距离、方向和高程,并合理解决地球曲率和投影变形等问题。他们还需要考虑地图的比例和符号规范,确保地图的可读性和易于理解。 制图师的工作有很高的技术要求和责任。他们需要熟练掌握地图制作的各种技术和工具,如测量仪器、遥感技术和地理信息系统(GIS)。同时,他们还需要具备对地理学、地理信息科学和大地测量学的深入理解。 总的来说,制图师是一种定位职业,他们通过使用地理数据和测量技术,绘制出准确、精美的地图,为我们提供了有关地球各个部分的空间信息,为人们的导航、规划及科学研究提供了重要的基础。
评论 29
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

dear小王子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值