ros bag包坐标系偏移,对bag包坐标系进行修正并重新录包(一)

本文介绍了如何处理因激光雷达晃动导致的坐标系倾斜问题,通过使用tunable_static_tf_broadcaster项目,调整bag包中的点云坐标系,使其与base_link平行。详细步骤包括启动项目,调节x、y、z、r、p、y参数,观察并记录结果,为后续点云标注和模型训练提供准确数据。
摘要由CSDN通过智能技术生成

背景描述

  • 使用激光雷达在录制点云bag包的过程中,因为激光雷达晃动,坐标系倾斜。导致影响后续的点云标注和模型训练。
    雷达扫描的点云地面与base_link倾斜,有夹角
  • 现在需要将录制的bag包进行处理,调整点云坐标系,使之与base_link坐标平行(点云地面与base_link坐标平面平行)。
  • 参考如下项目代码:tunable_static_tf_broadcaster

使用步骤

  • 项目代码结构很简单。源代码.cpp主要看tunable_static_tf_broadcaster.cpp。
  • 使用方法:
cd ~
mkdir tunable_static_tf_broadcaster
cd tunable_static_tf_broadcaster
mkdir src
cd src
git clone https://github.com/jianbuzhang/tunable_static_tf_broadcaster.git
cd ..
catkin_make
source devel/setup.bash
roslaunch tunable_static_tf_broadcaster sample.launch
  • 启动项目后,弹出下面的界面,选中arm,会有x,y,z,r,p,y六个调节值。
    在这里插入图片描述
  • 同时播放坐标系有倾斜的bag包,打开arm和base_link坐标系。并将Fixed Frame设置为arm。如下图:
    在这里插入图片描述
    此时调整项目gui的x,y,z,r,p,y。使点云地面相对于arm坐标水平。
    记录gui界面的值。
    在这里插入图片描述
    至此,该项目所有步骤完成。
#include <string>
#include <tf2/LinearMath/Quaternion.h>
#include "tunable_static_tf_broadcaster/tunable_static_tf_broadcaster.h"
#include "tunable_static_tf_broadcaster/TfConfig.h"

namespace tunable_static_tf_broadcaster
{
TunableStaticTfBroadcaster::TunableStaticTfBroadcaster() : private_nh_("~")
{
  // Initialize transform
  transform_.transform.translation.x = 0.0;
  transform_.transform.translation.y = 0.0;
  transform_.transform.translation.z = 0.0;
  tf2::Quaternion quaternion;
  quaternion.setRPY(0.0, 0.0, 0.0);
  transform_.transform.rotation.x = quaternion.x();
  transform_.transform.rotation.y = quaternion.y();
  transform_.transform.rotation.z = quaternion.z();
  transform_.transform.rotation.w = quaternion.w();

  // Get configuration from param
  publish_rate_ = private_nh_.param<int>("rate", 10);
  transform_.header.frame_id = private_nh_.param<std::string>("header_frame", "world");
  transform_.child_frame_id = private_nh_.param<std::string>("child_frame", "base_link");

  ROS_DEBUG("[tunable_static_tf_broadcaster] Setting parameters... {rate: %d, header_frame: %s, child_frame: %s}",
            publish_rate_, transform_.header.frame_id.c_str(), transform_.child_frame_id.c_str());

  // Get if static param is set
  if (private_nh_.hasParam("tf_x") || private_nh_.hasParam("tf_y") || private_nh_.hasParam("tf_z") ||
      private_nh_.hasParam("tf_roll") || private_nh_.hasParam("tf_pitch") || private_nh_.hasParam("tf_yaw"))
  {
    has_initial_static_params_ = true;
  }
  else
  {
    has_initial_static_params_ = false;
  }

  // Setup dynamic reconfigure
  dynamic_reconfigure_server_ = std::make_shared<dynamic_reconfigure::Server<TfConfig> >();
  dynamic_reconfigure::Server<TfConfig>::CallbackType f;
  f = boost::bind(&TunableStaticTfBroadcaster::dynamicReconfigureCallback, this, _1, _2);
  dynamic_reconfigure_server_->setCallback(f);
}

TunableStaticTfBroadcaster::~TunableStaticTfBroadcaster()
{
  // Delete params for another run
  if (!is_valid_config_received_)
  {
    private_nh_.deleteParam("tf_x");
    private_nh_.deleteParam("tf_y");
    private_nh_.deleteParam("tf_z");
    private_nh_.deleteParam("tf_roll");
    private_nh_.deleteParam("tf_pitch");
    private_nh_.deleteParam("tf_yaw");
  }
}

void TunableStaticTfBroadcaster::run()
{
  ros::Rate rate(publish_rate_);
  ros::Duration duration(1.0 / publish_rate_);

  while (private_nh_.ok())
  {
    // Send transform
    if (is_valid_config_received_)
    {
      transform_.header.stamp = ros::Time::now() + duration;  // Set future time to allow
                                                              // slower sending w/o other node's timeout.
      broadcaster_.sendTransform(transform_);
    }
    else
    {
      ROS_WARN_THROTTLE(3.0, "[tunable_static_tf_broadcaster] Configuration not received. waiting...");
    }

    ros::spinOnce();
    rate.sleep();
  }
}

void TunableStaticTfBroadcaster::dynamicReconfigureCallback(TfConfig& config, uint32_t level)
{
  if (is_first_config_callback_)
  {
    // If it was first calling, there are cases that it has static param value or not.
    if (has_initial_static_params_)
    {
      // Get static param value
      transform_.transform.translation.x = config.tf_x;
      transform_.transform.translation.y = config.tf_y;
      transform_.transform.translation.z = config.tf_z;
      tf2::Quaternion quaternion;
      quaternion.setRPY(config.tf_roll, config.tf_pitch, config.tf_yaw);
      transform_.transform.rotation.x = quaternion.x();
      transform_.transform.rotation.y = quaternion.y();
      transform_.transform.rotation.z = quaternion.z();
      transform_.transform.rotation.w = quaternion.w();
      is_valid_config_received_ = true;

      ROS_DEBUG("[tunable_static_tf_broadcaster] Setting parameters by static params... {x: %lf y: %lf z: %lf roll: "
                "%lf pitch: %lf yaw: %lf}",
                config.tf_x, config.tf_y, config.tf_z, config.tf_roll, config.tf_pitch, config.tf_yaw);
    }
    else
    {
      // Static param is not set. Wait for dynamic configuration.
      is_valid_config_received_ = false;
    }
    is_first_config_callback_ = false;
  }
  else
  {
    // Not first calling
    transform_.transform.translation.x = config.tf_x;
    transform_.transform.translation.y = config.tf_y;
    transform_.transform.translation.z = config.tf_z;
    tf2::Quaternion quaternion;
    quaternion.setRPY(config.tf_roll, config.tf_pitch, config.tf_yaw);
    transform_.transform.rotation.x = quaternion.x();
    transform_.transform.rotation.y = quaternion.y();
    transform_.transform.rotation.z = quaternion.z();
    transform_.transform.rotation.w = quaternion.w();
    is_valid_config_received_ = true;

    ROS_DEBUG("[tunable_static_tf_broadcaster] Setting dynamic parameters... {x: %lf y: %lf z: %lf roll: %lf pitch: "
              "%lf yaw: %lf}",
              config.tf_x, config.tf_y, config.tf_z, config.tf_roll, config.tf_pitch, config.tf_yaw);
  }
}

}  // namespace tunable_static_tf_broadcaster

后续

  • 该文章为第一章节。bag包处理第二节请看下一篇。
  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

shuimanting520

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

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

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

打赏作者

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

抵扣说明:

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

余额充值