【chatgpt代码系列】激光+二维码融合定位AGV用的tf计算

16 篇文章 6 订阅
3 篇文章 7 订阅

Q1:已知机器人有tf关系map->robot->qr_code->qr_label,现在知道map->qr和qr_code->qr_label,robot->qr_code,->表示两个坐标系的连接关系,现在想求map->robot,如何用ros的tf库、矩阵计算,用c++实现该功能

我们可以通过tf库和矩阵计算来实现map到robot的转换。

首先,我们可以使用lookupTransform函数来获取qr_code相对于map和robot之间的变换。具体代码如下:

#include <ros/ros.h>
#include <tf/transform_listener.h>

int main(int argc, char** argv)
{
    ros::init(argc, argv, "tf_demo");

    ros::NodeHandle node;
    tf::TransformListener listener;

    tf::StampedTransform qr_code_to_qr_label;
    listener.lookupTransform("qr_code", "qr_label", ros::Time(0), qr_code_to_qr_label);

    tf::StampedTransform robot_to_qr_code;
    listener.lookupTransform("robot", "qr_code", ros::Time(0), robot_to_qr_code);

    tf::StampedTransform map_to_qr_code;
    listener.lookupTransform("map", "qr_code", ros::Time(0), map_to_qr_code);

    // 计算qr_code到robot的变换
    tf::Transform qr_code_to_robot = qr_code_to_qr_label.inverse() * robot_to_qr_code;

    // 计算map到robot的变换
    tf::Transform map_to_robot = map_to_qr_code * qr_code_to_robot;

    ROS_INFO_STREAM("map -> robot:");
    ROS_INFO_STREAM("translation: " << map_to_robot.getOrigin().getX() << ", " << map_to_robot.getOrigin().getY() << ", " << map_to_robot.getOrigin().getZ());
    ROS_INFO_STREAM("rotation: " << map_to_robot.getRotation().getX() << ", " << map_to_robot.getRotation().getY() << ", " << map_to_robot.getRotation().getZ() << ", " << map_to_robot.getRotation().getW());

    return 0;
}

其中,我们首先通过lookupTransform函数获取qr_code相对于qr_label和robot的变换,然后通过矩阵乘法计算出qr_code到robot的变换,最后再将map到qr_code的变换与qr_code到robot的变换进行矩阵乘法,就可以得到map到robot的变换了。

注意,在使用lookupTransform函数时,需要保证map、robot、qr_code、qr_label四个坐标系之间都存在tf树的父子关系。

Q2:变换数据不能从tf中取,而是直接赋值的方式

如果我们不能通过tf库获取变换数据,而是通过其他方式得到了相应的变换矩阵,那么也可以使用tf库来进行变换计算。这时我们可以使用tf中的Transform类来表示变换,并使用该类提供的函数来进行变换计算。

假设我们已经得到了map到qr_code和qr_code到qr_label、qr_code到robot之间的变换矩阵,我们可以按以下步骤来计算map到robot之间的变换:

#include <ros/ros.h>
#include <tf/transform_datatypes.h>
#include <tf/transform_broadcaster.h>

int main(int argc, char** argv)
{
    ros::init(argc, argv, "tf_demo");

    // 假设map到qr_code的变换为T_map_qr,qr_code到qr_label的变换为T_qr_qr_label,qr_code到robot的变换为T_qr_robot
    tf::Transform T_map_qr;
    tf::Vector3 translation(1.0, 2.0, 3.0);
    tf::Quaternion rotation(0.0, 0.0, 0.0, 1.0);
    T_map_qr.setOrigin(translation);
    T_map_qr.setRotation(rotation);

    tf::Transform T_qr_qr_label;
    translation.setValue(0.1, 0.2, 0.3);
    rotation.setRPY(1.0, 2.0, 3.0);
    T_qr_qr_label.setOrigin(translation);
    T_qr_qr_label.setRotation(rotation);

    tf::Transform T_qr_robot;
    translation.setValue(0.4, 0.5, 0.6);
    rotation.setRPY(4.0, 5.0, 6.0);
    T_qr_robot.setOrigin(translation);
    T_qr_robot.setRotation(rotation);

    // 计算qr_code到robot、map到qr_code的变换
    tf::Transform T_qr_robot_inv = T_qr_robot.inverse();  // qr_code到robot的逆变换
    tf::Transform T_qr_map = T_map_qr.inverse();  // qr_code到map的逆变换

    // 计算map到robot的变换
    tf::Transform T_map_robot = T_qr_map * (T_qr_qr_label * T_qr_robot_inv);

    ROS_INFO_STREAM("map -> robot:");
    ROS_INFO_STREAM("translation: " << T_map_robot.getOrigin().getX() << ", " << T_map_robot.getOrigin().getY() << ", " << T_map_robot.getOrigin().getZ());
    ROS_INFO_STREAM("rotation: " << T_map_robot.getRotation().getX() << ", " << T_map_robot.getRotation().getY() << ", " << T_map_robot.getRotation().getZ() << ", " << T_map_robot.getRotation().getW());

    return 0;
}

在这个例子中,我们首先手动创建了三个Transform对象,分别表示map到qr_code、qr_code到qr_label、qr_code到robot之间的变换。

接着,我们使用inverse函数求出qr_code到robot矩阵的逆变换,并使用乘法运算得到qr_code到map的变换,最后再次使用乘法运算计算出map到robot的变换。

需要注意的是,在使用setOrigin和setRotation函数给Transform对象设置变换时,需要传入tf::Vector3和tf::Quaternion类型的参数。而在获取变换数据时,也可以通过getOrigin和getRotation函数得到相应的tf::Vector3和tf::Quaternion类型的数据。

Q3:如何用eigen库实现该需求

如果我们想在代码中使用Eigen库来进行变换计算,可以按照以下步骤:

首先,在CMakeLists.txt文件中添加如下代码,以便程序可以链接Eigen库:

find_package(Eigen3 REQUIRED)
include_directories(${EIGEN3_INCLUDE_DIRS})

接着,在代码中引入Eigen头文件:

#include <Eigen/Core>
#include <Eigen/Geometry>

假设我们已经得到了map到qr_code、qr_code到qr_label和qr_code到robot之间的变换矩阵,我们可以按以下步骤来计算map到robot之间的变换:

#include <ros/ros.h>
#include <Eigen/Core>
#include <Eigen/Geometry>

int main(int argc, char** argv)
{
    ros::init(argc, argv, "eigen_demo");

    // 假设map到qr_code的变换为T_map_qr,qr_code到qr_label的变换为T_qr_qr_label,qr_code到robot的变换为T_qr_robot

    Eigen::Matrix3d R_map_qr = Eigen::Quaterniond(1.0, 0.0, 0.0, 0.0).toRotationMatrix();  // map到qr_code的旋转矩阵,这里假设旋转部分为单位四元数
    Eigen::Vector3d p_map_qr(1.0, 2.0, 3.0);  // map到qr_code的平移矩阵
    Eigen::Isometry3d T_map_qr = Eigen::Translation3d(p_map_qr) * Eigen::Quaterniond(R_map_qr);  // map到qr_code的变换矩阵

    Eigen::Matrix3d R_qr_qr_label = Eigen::AngleAxisd(1.0, Eigen::Vector3d::UnitX()).toRotationMatrix();  // qr_code到qr_label的旋转矩阵,这里假设旋转部分为绕X轴的旋转
    Eigen::Vector3d p_qr_qr_label(0.1, 0.2, 0.3);  // qr_code到qr_label的平移矩阵
    Eigen::Isometry3d T_qr_qr_label = Eigen::Translation3d(p_qr_qr_label) * Eigen::Quaterniond(R_qr_qr_label);  // qr_code到qr_label的变换矩阵

    Eigen::Matrix3d R_qr_robot = Eigen::AngleAxisd(4.0, Eigen::Vector3d::UnitX()) * Eigen::AngleAxisd(5.0, Eigen::Vector3d::UnitY()) * Eigen::AngleAxisd(6.0, Eigen::Vector3d::UnitZ());  // qr_code到robot的旋转矩阵,这里假设旋转部分为绕X/Y/Z轴的旋转
    Eigen::Vector3d p_qr_robot(0.4, 0.5, 0.6);  // qr_code到robot的平移矩阵
    Eigen::Isometry3d T_qr_robot = Eigen::Translation3d(p_qr_robot) * Eigen::Quaterniond(R_qr_robot);  // qr_code到robot的变换矩阵

    // 计算qr_code到robot、map到qr_code的变换
    Eigen::Isometry3d T_qr_robot_inv(T_qr_robot.matrix().inverse());  // qr_code到robot的逆变换
    Eigen::Isometry3d T_qr_map(T_map_qr.matrix().inverse());  // qr_code到map的逆变换

    // 计算map到robot的变换
    Eigen::Isometry3d T_map_robot(T_qr_map.matrix() * T_qr_qr_label.matrix() * T_qr_robot_inv.matrix());

    ROS_INFO_STREAM("map -> robot:");
    ROS_INFO_STREAM("translation: " << T_map_robot.translation().transpose());
    ROS_INFO_STREAM("rotation:\n" << T_map_robot.rotation());

    return 0;
}

在这个例子中,我们首先手动创建了三个Eigen::Isometry3d对象,分别表示map到qr_code、qr_code到qr_label、qr_code到robot之间的变换。对于旋转部分,我们可以使用Eigen库中提供的AngleAxisd类或Quaterniond类来构造旋转矩阵或四元数。

接着,我们使用matrix函数将Eigen::Isometry3d对象转成4x4的变换矩阵,并使用inverse函数求出qr_code到robot矩阵的逆变换。最后,我们使用乘法运算得到qr_code到map的变换,再使用matrix函数将Eigen::Isometry3d对象转成4x4的变换矩阵。最后通过乘法运算计算出map到robot的变换。

注意,在Eigen库中,我们可以使用Translation3d和Quaterniond类分别表示平移向量和旋转四元数。在计算map到robot变换时,我们使用逆变换求解qr_code到map的变换,这里需要对变换矩阵做一个inverse函数,将其转换成逆矩阵。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值