使用2D雷达laser+imu实现cartographer实时建图

参考链接:cartographer接入2D雷达laser+imu实时建图_cartographer imu_Astrophily的博客-CSDN博客

激光雷达型号:Slamtec A1 【安装与使用见前文】

IMU型号:WHT901B-485

imu使用说明:深圳维特智能科技有限公司

1.安装使用IMU

1.1 安装ROS IMU依赖项

sudo apt-get install ros-melodic-imu-tools ros-melodic-rviz-imu-plugin

1.2 使用维特智能官网 下载对应的示例程序【ubuntu18.04火狐浏览器看不到下载地址】

ubuntu中要解压rar文件 要下载对应功能包

链接:Ubuntu下解压rar压缩文件_ubuntu解压rar文件_沉醉,于风中的博客-CSDN博客

1.3 编译与安装IMU功能包

cd wit_ros_ws //加入工作空间
catkin_make   //编译
cd /src/scripts
sudo chmod 777 *.py

修改参数:wit_imu.launch文件中default类型normal改为modbus

 重新编译会报错:

 解决:

pip3 install modbus_tk

测试:查看imu数据

端口1:

sudo chmod 777 /dev/ttyUsb0  //给imu端口权限
roslaunch wit_os_imu wit_imu.launch

端口2:

cd wit_ros_ws/src/scripts
python get_imu_rpy.py

测试结果--imu话题:/wit/imu

2.修改cartographer参数

补充:查看话题的 frame_id

rostopic echo /topic | grep frame_id

2.1修改revo_lds.lua [~/car2_ws/src/cartographer_ros/cartographer_ros/configuration_files下]

修改内容:

   tracking_frame =“ base_link”  
    published_frame= “base_link”  
   provide_odom_frame = true
   TRAJECTORY_BUILDER_2D.use_imu_data =true

2.2 修改backpack_2d.urdf【~/car2_ws/src/cartographer_ros/cartographer_ros/urdf下】

更改后文件内容:

<robot name="cartographer_backpack_2d">
  <material name="orange">
    <color rgba="1.0 0.5 0.2 1" />
  </material>
  <material name="gray">
    <color rgba="0.2 0.2 0.2 1" />
  </material>

  <link name="imu_link">
    <visual>
      <origin xyz="0 0 0" />
      <geometry>
        <box size="0.06 0.04 0.02" />
      </geometry>
      <material name="orange" />
    </visual>
  </link>

  <link name="laser">
    <visual>
      <origin xyz="0 0 0" />
      <geometry>
        <cylinder length="0.05" radius="0.03" />
      </geometry>
      <material name="gray" />
    </visual>
  </link>

  <link name="base_link" />

  <joint name="imu_link_joint" type="fixed">
    <parent link="base_link" />
    <child link="imu_link" />
    <origin xyz="0 0 0" />
  </joint>

  <joint name="laser_joint" type="fixed">
    <parent link="base_link" />
    <child link="laser" />
    <origin xyz="0.1007 0 0.0558" />
  </joint>

</robot>

2.3 修改demo_revo_lds.launch【~/car2_ws/src/cartographer_ros/cartographer_ros/launch下】

更改后内容如下:

<launch>
  <param name="/use_sim_time" value="false" />

  <param name="robot_description"
    textfile="$(find cartographer_ros)/urdf/backpack_2d.urdf" />
    
 <node name="robot_state_publisher" pkg="robot_state_publisher"
    type="robot_state_publisher" />

  <node name="cartographer_node" pkg="cartographer_ros"
      type="cartographer_node" args="
          -configuration_directory $(find cartographer_ros)/configuration_files
          -configuration_basename revo_lds.lua"
      output="screen">
    <remap from="scan" to="scan" />
    <remap from="imu" to="/wit/imu" />
  </node>

  <node name="cartographer_occupancy_grid_node" pkg="cartographer_ros"
      type="cartographer_occupancy_grid_node" args="-resolution 0.05" />

  <node name="rviz" pkg="rviz" type="rviz" required="true"
      args="-d $(find cartographer_ros)/configuration_files/demo_2d.rviz" />
</launch>

3.测试

3.1 给端口权限【多个接口时,要在节点中更改默认节点名】

sudo chmod 777 /dev/ttyUSB0  //激光
sudo chmod 777 /dev/ttyUSB1  //IMU

3.2 启动激光雷达节点

cd  Slamtec
source ./devel/setup.bash    
roslaunch  rplidar_ros rplidar.launch

3.3 启动IMU节点

cd wit_ros_ws
source ./devel/setup/bash
roslaunch wit_ros_imu  wit_imu.launch

3.4 启动cartographer demo

cd car2_ws
source ./devel/setup.bash
roslaunch cartographer_ros demo_revo_lds.launch

4.测试结果:

1.rqt_grapher

 2.tf-tree

  • 0
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个基于ROS的激光雷达+IMU畸变补偿的示例代码: ``` #include <ros/ros.h> #include <sensor_msgs/Imu.h> #include <sensor_msgs/LaserScan.h> #include <tf/transform_listener.h> #include <tf/transform_broadcaster.h> class LaserImuCalibration { public: LaserImuCalibration(); void imuCallback(const sensor_msgs::Imu::ConstPtr& imu_msg); void scanCallback(const sensor_msgs::LaserScan::ConstPtr& scan_msg); private: ros::NodeHandle nh_; ros::Subscriber imu_sub_; ros::Subscriber scan_sub_; tf::TransformListener tf_listener_; tf::TransformBroadcaster tf_broadcaster_; ros::Publisher scan_pub_; sensor_msgs::LaserScan scan_msg_; bool imu_received_; bool scan_received_; double imu_roll_, imu_pitch_, imu_yaw_; double imu_gx_, imu_gy_, imu_gz_; double imu_ax_, imu_ay_, imu_az_; double imu_time_; double scan_time_; }; LaserImuCalibration::LaserImuCalibration() : imu_received_(false), scan_received_(false) { imu_sub_ = nh_.subscribe("/imu/data", 1, &LaserImuCalibration::imuCallback, this); scan_sub_ = nh_.subscribe("/scan", 1, &LaserImuCalibration::scanCallback, this); scan_pub_ = nh_.advertise<sensor_msgs::LaserScan>("/scan_calibrated", 1); } void LaserImuCalibration::imuCallback(const sensor_msgs::Imu::ConstPtr& imu_msg) { imu_received_ = true; imu_roll_ = imu_msg->orientation.x; imu_pitch_ = imu_msg->orientation.y; imu_yaw_ = imu_msg->orientation.z; imu_gx_ = imu_msg->angular_velocity.x; imu_gy_ = imu_msg->angular_velocity.y; imu_gz_ = imu_msg->angular_velocity.z; imu_ax_ = imu_msg->linear_acceleration.x; imu_ay_ = imu_msg->linear_acceleration.y; imu_az_ = imu_msg->linear_acceleration.z; imu_time_ = imu_msg->header.stamp.toSec(); } void LaserImuCalibration::scanCallback(const sensor_msgs::LaserScan::ConstPtr& scan_msg) { scan_received_ = true; scan_time_ = scan_msg->header.stamp.toSec(); scan_msg_ = *scan_msg; } int main(int argc, char** argv) { ros::init(argc, argv, "laser_imu_calibration"); LaserImuCalibration node; while (ros::ok()) { ros::spinOnce(); if (node.imu_received_ && node.scan_received_) { // Get the laser scanner transformation tf::StampedTransform laser_transform; try { node.tf_listener_.lookupTransform("laser", "imu", ros::Time(0), laser_transform); } catch (tf::TransformException ex) { ROS_ERROR("%s", ex.what()); continue; } // Compute the rotation matrix from the IMU data tf::Quaternion q(imu_roll_, imu_pitch_, imu_yaw_); tf::Matrix3x3 m(q); double imu_roll, imu_pitch, imu_yaw; m.getRPY(imu_roll, imu_pitch, imu_yaw); // Compute the IMU acceleration in the laser scanner frame tf::Vector3 imu_acceleration(imu_ax_, imu_ay_, imu_az_); imu_acceleration = laser_transform.getBasis() * imu_acceleration; // Compute the IMU angular velocity in the laser scanner frame tf::Vector3 imu_angular_velocity(imu_gx_, imu_gy_, imu_gz_); imu_angular_velocity = laser_transform.getBasis() * imu_angular_velocity; // Compute the time offset between the IMU and the laser scanner double time_offset = scan_time_ - imu_time_; // Update the laser scanner pose using the IMU data tf::Quaternion q_laser = laser_transform.getRotation(); tf::Quaternion q_imu(imu_roll, imu_pitch, imu_yaw); tf::Quaternion q_new = q_imu * q_laser; tf::Transform laser_transform_new(q_new, laser_transform.getOrigin()); laser_transform_new.setOrigin(laser_transform_new.getOrigin() + laser_transform_new.getBasis() * imu_acceleration * time_offset); laser_transform_new.setRotation(laser_transform_new.getRotation() + tf::Quaternion(0, 0, imu_angular_velocity.getZ() * time_offset, 1) * laser_transform_new.getRotation() * 0.5); // Publish the calibrated laser scanner data scan_msg_.header.stamp = ros::Time::now(); tf::transformStampedTFToMsg(tf::StampedTransform(laser_transform_new, scan_msg_.header.stamp, "imu", "laser"), scan_msg_.header.frame_id); scan_pub_.publish(scan_msg_); // Broadcast the laser scanner pose tf_broadcaster_.sendTransform(tf::StampedTransform(laser_transform_new, ros::Time::now(), "imu", "laser")); // Reset the received flags node.imu_received_ = false; node.scan_received_ = false; } } return 0; } ``` 该代码中,首先定义了LaserImuCalibration类,该类订阅IMU数据和激光雷达数据,然后计算IMU数据和激光雷达数据之间的转换关系,最后发布校准后的激光雷达数据。 在imuCallback回调函数中,获取IMU的姿态角、角速度和加速度等数据。在scanCallback回调函数中,获取激光雷达数据。 在计算激光雷达IMU之间的转换关系时,需要获取激光雷达IMU之间的变换关系,可以使用tf库中的tf_listener查找二者之间的变换关系。然后,根据IMU的姿态角、角速度和加速度等数据,计算出激光雷达IMU坐标系下的位姿,并通过发布校准后的激光雷达数据和广播激光雷达位姿,完成畸变补偿。 需要注意的是,该代码仅供参考,具体实现需要根据实际情况进行修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值