realsense D435i gazebo slam(px4)仿真

2023-05-16

文章目录

    • realsense D435i gazebo slam仿真
      • 下载realsense 仿真模型
      • 运行D435仿真环境测试
        • D435
        • D435i
    • slam仿真示例
      • UAV模型启动
      • slam启动
      • 其他
        • mavros px4 坐标转换

realsense D435i gazebo slam仿真

包含realsense T265 D435i的urdf和sdf文件、realsense_gazebo_plugin包及realsense 模型文件使用示例。

下载realsense 仿真模型

[catkin_ws]表示自定义的工作目录

mkdir -p [catkin_ws]/src
cd [catkin_ws]/src
git clone https://gitee.com/nie_xun/realsense_ros_gazebo.git
cd [catkin_ws]
catkin_make
source devel/setup.sh

运行D435仿真环境测试

D435

roslaunch realsense_ros_gazebo simulation_sdf.launch
运行结果:
在这里插入图片描述

D435i

相比D435多一个camera/imu topic
roslaunch realsense_ros_gazebo simulation_D435i_sdf.launch
在这里插入图片描述

slam仿真示例

UAV模型启动

本示例使用px4的iris 无人机模型作为示例,本文使用的Firmware为v1.8版本。
在realsense_ros_gazebo的sdf文件夹下已存放携带D435i的iris sdf文件。
以下[px4]为px4 对应的Firmware的根路径
在这里插入图片描述

  1. 在[px4]/launch下生成文件iris_realsense_camera_px4_mavros_vo.launch,内容如下:
<?xml version="1.0"?>
<launch>
    <arg name="x" default="0"/>
    <arg name="y" default="0"/>
    <arg name="z" default="0"/>
    <arg name="R" default="0"/>
    <arg name="P" default="0"/>
    <arg name="Y" default="0"/>
    <!-- vehicle model and world -->
    <arg name="est" default="ekf2"/>
    <arg name="vehicle" default="iris"/>
    <arg name="world" default="$(find px4)/Tools/sitl_gazebo/worlds/empty.world"/>
    <arg name="sdf" default="$(find px4)/Tools/sitl_gazebo/models/iris_realsense_camera/iris_realsense_camera.sdf"/>
    <arg name="rcS" default="$(find px4)/posix-configs/SITL/init/$(arg est)/$(arg vehicle)_vo"/>
    <!-- gazebo configs -->
    <arg name="gui" default="true"/>
    <arg name="debug" default="false"/>
    <arg name="verbose" default="false"/>
    <arg name="paused" default="false"/>
    <arg name="respawn_gazebo" default="false"/>
    <!-- MAVROS configs -->
    <arg name="fcu_url" default="udp://:14540@localhost:14557"/>
    <arg name="respawn_mavros" default="false"/>
    <!-- PX4 configs -->
    <arg name="interactive" default="true"/>
    <!-- PX4 SITL and Gazebo -->
    <include file="$(find px4)/launch/posix_sitl.launch">
        <arg name="x" value="$(arg x)"/>
        <arg name="y" value="$(arg y)"/>
        <arg name="z" value="$(arg z)"/>
        <arg name="R" value="$(arg R)"/>
        <arg name="P" value="$(arg P)"/>
        <arg name="Y" value="$(arg Y)"/>
        <arg name="world" value="$(arg world)"/>
        <arg name="vehicle" value="$(arg vehicle)"/>
        <arg name="sdf" value="$(arg sdf)"/>
        <arg name="rcS" value="$(arg rcS)"/>
        <arg name="gui" value="$(arg gui)"/>
        <arg name="interactive" value="$(arg interactive)"/>
        <arg name="debug" value="$(arg debug)"/>
        <arg name="verbose" value="$(arg verbose)"/>
        <arg name="paused" value="$(arg paused)"/>
        <arg name="respawn_gazebo" value="$(arg respawn_gazebo)"/>
    </include>
    <!-- MAVROS -->
    <include file="$(find mavros)/launch/px4.launch">
        <arg name="gcs_url" value=""/>
        <arg name="fcu_url" value="$(arg fcu_url)"/>
        <arg name="respawn_mavros" value="$(arg respawn_mavros)"/>
    </include>
</launch>

  1. 在[px4]//posix-configs/SITL/init/ekf2下生成iris_vo,操作如下:
cd [px4]//posix-configs/SITL/init/ekf2
cp iris iris_vo

将EKF2_AID_MASK和EKF2_HGT_MODE对应项改成:

param set EKF2_AID_MASK 24
param set EKF2_HGT_MODE 3

在这里插入图片描述

  1. 拷贝模型文件到px4
cp realsense_ros_gazebo/sdf/* [px4]/Tools/sitl_gazebo/models/ -r
  1. 启动
roscd px4/launch
roslaunch iris_realsense_camera_px4_mavros_vo.launch

在这里插入图片描述

slam启动

  1. 需要将slam的odom输出remap到/mavros/vision_pose/pose
    1)如果slam输出使用的odom消息类型为geometry_msgs::PoseStamped,且坐标系为(NWU: x:前;y:左;z:上)则直接在slam的launch文件中发布odom消息的node下加入以下内容:
<remap from="/camera/odom" to="/mavros/vision_pose/pose" />

2)本文使用的slam坐标系为WUN,发布的odom消息类型为/camera/odometry
使用的转换代码文件如下:
nav_msg_to_mavros.cpp

#include <iostream>
#include <ros/ros.h>
#include <geometry_msgs/Pose.h>
#include <geometry_msgs/PoseStamped.h>
#include <nav_msgs/Odometry.h>

ros::Publisher camera_pose_publisher;

int data_source;
enum {
  GAZEBO_GT = 0,
  CAMERA_VO = 1 
};

void vision_cb(const nav_msgs::Odometry::ConstPtr &msg)
{
    geometry_msgs::PoseStamped msg_body_pose;

    if (data_source == GAZEBO_GT) {
        // 0 means use gazebo grougtruth
        msg_body_pose.header.stamp = msg->header.stamp;
        msg_body_pose.header.frame_id = "world";
        msg_body_pose.pose.position.x = msg->pose.pose.position.x;
        msg_body_pose.pose.position.y = msg->pose.pose.position.y;
        msg_body_pose.pose.position.z = msg->pose.pose.position.z;
        msg_body_pose.pose.orientation.x = msg->pose.pose.orientation.x;
        msg_body_pose.pose.orientation.y = msg->pose.pose.orientation.y;
        msg_body_pose.pose.orientation.z = msg->pose.pose.orientation.z;
        msg_body_pose.pose.orientation.w = msg->pose.pose.orientation.w;
    } else if (data_source == CAMERA_VO) {
        // 1 means use camera vo
        // Create PoseStamped message to be sent
        msg_body_pose.header.stamp = msg->header.stamp;
        msg_body_pose.header.frame_id = "world";
        msg_body_pose.pose.position.x = msg->pose.pose.position.z;
        msg_body_pose.pose.position.y = msg->pose.pose.position.x;
        msg_body_pose.pose.position.z = msg->pose.pose.position.y;
        msg_body_pose.pose.orientation.x = msg->pose.pose.orientation.z;
        msg_body_pose.pose.orientation.y = msg->pose.pose.orientation.x;
        msg_body_pose.pose.orientation.z = msg->pose.pose.orientation.y;
        msg_body_pose.pose.orientation.w = msg->pose.pose.orientation.w;
    }   

    // Publish pose of body frame in world frame
    camera_pose_publisher.publish(msg_body_pose);
}

int main(int argc, char **argv)
{
    ros::init(argc, argv, "vision_to_mavros");
    ros::NodeHandle nh("~");
    nh.param<int>("data_source", data_source, 0);

    ros::Subscriber gazebo_sub = nh.subscribe<nav_msgs::Odometry>("/camera/odometry", 50, vision_cb);
    camera_pose_publisher = nh.advertise<geometry_msgs::PoseStamped>("/mavros/vision_pose/pose", 50);

    ros::spin();

}

2.启动想使用的slam

结果示例:
在这里插入图片描述

其他

mavros px4 坐标转换

mavros:enu
px4:ned

在外部传感器定位,非GPS自身定位,世界坐标系由外部传感器定义。
如optirack,使用自身的定义的原点坐标系,由定义原点时,使用的定位杆长短轴及motive软件的Y/Z up综合定义。

Y up: 前(Z+), 左(X+), 上(Y+) 。
Z up: 在Y up的坐标系基础上绕x轴旋转-90度。Z up即使用的enu的坐标系。

坐标系的定位也有相对之分,比如optirack相对于GPS坐标系就是相对坐标系,GPS作为地球坐标系(更大的坐标系)则作为绝对坐标系,当使用相机定位做对比实验,则又能将optirack看做绝对坐标系,相机坐标系作为相对坐标系。

f:first l:left b:back u:up

因此像enu end这种坐标系更多的是说明xyz三轴的相对关系,比如(flu, lbu)都是一种enu坐标系,更多的是说明机体坐标系来用的。如下图所示:通过旋转后的坐标系,满足三轴规则,还是enu坐标系。
在这里插入图片描述

当optirack vo等相对局部的坐标系只要满足xyz的右手关系,即,食指指向x,对应中指就指向y, 大拇指就是z方向。则就满足enu坐标系。

无人机以固件启动时作为原点,偏航初始化为0,当无人机以外部传感器作为定位及yaw的输入时(roll pitch由无人机自身imu获得),需要对准机头方向,使外部传感器得到的偏航和机体得到的偏航一致。

例子1:外部定位使用optirack,Zup(enu), 将初始化时将机头于optirack的x轴对齐,则直接将/vrpn_client_node/<rigid_body_name>/poseremap到mavros/vision_pose/pose即可。
使用mavros/vision_pose发送,mavros采用的enu坐标系,mavros会自动两enu转换到ned坐标系,则初始化时将机头于optirack的x轴对齐,从而能够使px4初始化时,px4解算偏航与optirack解算的机体偏航一致,约为0。或者不对齐时,需减去optirack的偏航测量值再赋值给mavros/vision_pose

例子2:外部定位使用vo,相机前向与无人机绑定,坐标系为(LUF),将vo输出转换到ENU坐标系赋值给mavros/vision_pose/pose,则对应的转换:类似将(LUF->FLU)

poseX = voZ
poseY = voX
poseZ = voY

此时,直接将机头与mavros的enu的初始化x轴对齐了,即将相机的前向(机头方向)作为mavros的x轴。

总结:无论是vo还是optitrack,要保证的是初始化时,机头要对准赋值给mavros/vision_pose的x。mavros/vision_pose在ENU坐标系下。

附vins 的配置文件
vins-fusion,仅作参考,实际应根据realsense_ros_gazebo/sdf/D435i/model.sdf计算得。
本人只用了单目、imu及深度图,因此没有去解算双目的变换矩阵。以下仅供参考:建议将estimate_extrinsic设为1。

realsense_stereo_imu_config.yaml

imu_topic: "/camera/imu"
image0_topic: "/camera/infra1/image_raw"
image1_topic: "/camera/infra2/image_raw"
output_path: "/home/xxx/output"

cam0_calib: "left.yaml"
cam1_calib: "right.yaml"
image_width: 640 
image_height: 480 
   
# Extrinsic parameter between IMU and Camera.
estimate_extrinsic: 1   # 0  Have an accurate extrinsic parameters. We will trust the following imu^R_cam, imu^T_cam, don't change it.
                        # 1  Have an initial guess about extrinsic parameters. We will optimize around your initial guess.

body_T_cam0: !!opencv-matrix
   rows: 4
   cols: 4
   dt: d
   data: [ -5.7586305857286746e-03, -4.0463318787729019e-03,
       9.9997523237933461e-01, 2.0329267950355900e-02,
       -9.9998287214160420e-01, -1.0224590553211677e-03,
       -5.7628118925283633e-03, 7.9325209639615653e-03,
       1.0457519809151661e-03, -9.9999129084997906e-01,
       -4.0403746097850135e-03, 2.8559824645148020e-03, 0., 0., 0., 1. ]

body_T_cam1: !!opencv-matrix
   rows: 4
   cols: 4
   dt: d
   data: [ -1.0021770212322867e-03, 3.6313480322730518e-04,
       9.9999943188700535e-01, 1.5285779565991807e-02,
       -9.9999216342926500e-01, -3.8303422615924010e-03,
       -1.0007788055728661e-03, -5.2435791444330505e-02,
       3.8299766679101843e-03, -9.9999259827824449e-01,
       3.6697063849344680e-04, 8.6931302450199057e-03, 0., 0., 0., 1. ]

left.yaml/right.yaml

model_type: PINHOLE
camera_name: camera
image_width: 640 
image_height: 480 
distortion_parameters:
   k1: 0.0 
   k2: 0.0 
   p1: 0.0 
   p2: 0.0 
projection_parameters:
   fx: 383.6
   fy: 383.3
   cx: 317.0
   cy: 240.0        
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

realsense D435i gazebo slam(px4)仿真 的相关文章

  • slam数学基础——最小二乘

    一 前言 1 最小二乘是一类特殊形式的最优化求解问题 相比于其他优化问题 求解方式比较简洁 2 最小二乘被广泛应用于各种实际问题的建模 在求解实际工程问题中有着广泛的应用 例如 slam 中随处可见最小二乘的声影 二 线性最小二乘法 1 预
  • 三维刚体变换

    欢迎访问我的博客首页 三维刚体变换 1 坐标系 1 1 空间坐标系 1 2 右手坐标系与像素坐标系 2 旋转与平移 2 1 推导旋转 2 2 推导平移 2 3 推导变换 2 4 刚体变换 2 5 坐标系旋转与向量旋转 3 链式变换 4 Ei
  • ROS STAGE教程2(地图定义和GMAPPING建图)

    目前用在ROS Kinetic上的stage版本为4 1 官方教程http rtv github io Stage modules html 用户可以用stage或者gazebo来创建地图和机器人 传感器模型来进行仿真 并与自己的SLAM模
  • LIO-SAM:在高斯牛顿法求解过程中用SO3代替欧拉角

    LIO SAM发表于IROS2020 是一个效果非常好的惯性 激光紧耦合里程计 我打算给我们的机器人搞一个激光里程计 于是打算把LIO SAM改一改搞过来 修改过程中发现一个问题 在里程计求解 mapOptimization的LMOptim
  • 使用EKF融合odometry及imu数据

    整理资料发现早前学习robot pose ekf的笔记 大抵是一些原理基础的东西加一些自己的理解 可能有不太正确的地方 当时做工程遇到的情况为机器人在一些如光滑的地面上打滑的情形 期望使用EKF利用imu对odom数据进行校正 就结果来看
  • URDF、Gazebo与Rviz机器人仿真综合应用-autolabor笔记

    URDF Gazebo与Rviz综合应用 6 7 1 1 机器人运动控制 编写机器人my base xacro 编写传动装置以及控制器move xacro文件 搭建环境world文件 将上述整合进一个car xacro文件 加载惯性矩阵xa
  • 飞行姿态解算(三)

    继之前研究了一些飞行姿态理论方面的问题后 又找到了之前很流行的一段外国大神写的代码 来分析分析 第二篇文章的最后 讲到了文章中的算法在实际使用中有重大缺陷 大家都知道 分析算法理论的时候很多情况下我们没有考虑太多外界干扰的情况 原因是很多情
  • vscode配置eigen3

    目录 1 头文件包含 2 c cpp properties json 3 CMakeList txt 4 完整代码 1 头文件包含 Eigen 核心部分 include
  • 激光SLAM7-基于已知位姿的构图算法

    1 通过覆盖栅格建图算法进行栅格地图的构建 1 1 Theory 1 2 code 这里没有判断idx和hitPtIndex是否有效 start of TODO 对对应的map的cell信息进行更新 1 2 3题内容 GridIndex h
  • gazebo通过sdf搭建仿真环境和机器人Husky

    具体格式要求可参考 http sdformat org spec ver 1 6 elem sdf
  • 互转(经纬度、地心坐标、东北天坐标)

    Part1三种坐标系介绍 经纬度坐标 假设空间某点P 用经纬度表示的话 你们B代表纬度 L代表经度 H代表大地高 纬度B P点沿着地球法线方向与赤道面的夹角 向北为正称为北纬 0 90 向南为负称为南纬 0 90 实际表示可以用 90 90
  • 视觉SLAM技术及其应用(章国锋--复杂环境下的鲁棒SfM与SLAM)

    SLAM 同时定位与地图构建 机器人和计算机视觉领域的基本问题 在未知环境中定位自身方位并同时构建环境三维地图 应用广泛 增强现实 虚拟现实 机器人 无人驾驶 SLAM常用的传感器 红外传感器 较近距离感应 常用与扫地机器人 激光雷达 单线
  • IMU预积分的一些理解

    IMU预积分 算是比较简单的一个算法 无奈网上找到的资料都讲的晦涩难懂 看明白了也觉得不过如此 讲一下我的理解 整体流程 1 推导IMU离散运动方程 2 根据离散运动方程 进行预积分 并将预积分的误差项拆分出来 因为我们在定义误差的时候 有
  • 动态场景下基于实例分割的SLAM(毕业设计开题及语义分割部分)

    动态场景下基于实例分割的SLAM 毕业论文设计思路及流水 前言 今年选了个比较难的毕设题目 这里记录一下自己思路和流程 为之后的学弟学妹 划掉 铺个方向 会按日期不定期的更新 一 开题 2019 12 24 考研前选择课题是 利用深度学习对
  • SLAM-hector_slam 简介与使用

    hector slam功能包使用高斯牛顿方法 不需要里程计数据 只根据激光信息便可构建地图 所以他的总体框架如下 hector slam功能包 hector slam的核心节点是hector mapping 它订阅 scan 话题以获取SL
  • 用Eigen库练习代数运算方式以便后续对刚体旋转和移动做基础

    include
  • 【Pytorch论文相关代码】使用SOLD2预训练好的模型检测与匹配线段(自己的数据集)

    文章目录 前言 使用流程 检测与匹配结果 前言 论文链接 SOLD2 Self supervised Occlusion aware Line Description and Detection 论文源码 https github com
  • 高翔博士Faster-LIO论文和算法解析

    说明 题目 Faster LIO 快速激光IMU里程计 参考链接 Faster LIO 快速激光IMU里程计 iVox Faster Lio 智行者高博团队开源的增量式稀疏体素结构 Faster Lio是高翔博士在Fast系列的新作 对标基
  • KITTI校准文件中参数的格式

    我从以下位置访问了校准文件KITTI 的部分里程计 http www cvlibs net datasets kitti eval odometry php 其中一个校准文件的内容如下 P0 7 188560000000e 02 0 000
  • gazebo(fortress) set the path of sdf file

    This method only satisfied with gazebo fortress not harmenic

随机推荐