坐标转换tf

2023-05-16

tf介绍

  • 坐标转换(TransForm:位置姿态)
  • 坐标变换是空间实体的位置描述,是从一种坐标系统变换到另一种坐标系统的过程。通过建立两个坐标系统之间一一对应关系来实现
  • 下图为机器人几个部件之间的坐标关系在这里插入图片描述

tf概念

  • tf是一个用户随时间跟踪多个坐标系的包,机器人不同部位和世界的坐标系以 tree structure 的形式存储起来,tf管理一系列的树状结构坐标系之间的关系
  • 允许用户在各个坐标系中进行点、向量的变换
  • 通俗的说tf可以帮助我们实时的在各个坐标系中进行坐标转换

在这里插入图片描述

TF树样例

在这里插入图片描述

tf认知

环境搭建,运行已下命令安装相关插件资源
sudo apt-get install ros- kinetic -ros-tutorials ros- kinetic -geometry-tutorials ros- kinetic -rviz ros- kinetic -rosbash ros- kinetic -rqt-tf-tree

运行以下命令打开demo程序
roslaunch turtle_tf turtle_tf_demo.launch
在这里插入图片描述
将当前运行命令的窗口作为激活窗口,用箭头按键控制小乌龟移动,另外一只小乌龟讲会跟着移动
在这里插入图片描述

  • 这个demo用tf库建立了三个坐标系,世界坐标系乌龟1坐标系乌龟2坐标系
  • 在乌龟移动的过程中,tf库创建了一个tf发布器用于发布乌龟1的坐标系在世界坐标系中的实时位置
  • 利用一个tf接收器接收该位置
  • 计算两个乌龟坐标系的差异,让乌龟2跟着乌龟1移动

view_frames:该命令会以一个树状图的形式,给我们展现出当前ros中tf发布的所有坐标系

运行命令生成当前坐标系树状图:rosrun tf view_frames
在这里插入图片描述
查看pdf文件:evince frames.pdf
在这里插入图片描述
从上图中可以看到

  • tf广播了三个坐标系:世界坐标,乌龟1坐标系,乌龟2坐标系
  • world坐标是 turtle1和 turtle2的父级

rqt_tf_tree是一个可以实时可视化显示当前tf发布的坐标系图

输入命令:rosrun rqt_tf_tree rqt_tf_tree
在这里插入图片描述

tf_echo 可以报告任意两个坐标系之间的变换。
用法:
rosrun tf tf_echo [reference_frame] [targe_frame]

输入命令:rosrun tf tf_echo turtle1 turtle2
在这里插入图片描述

rviz和tf:rviz作为一个可视化工具,可以用来观测turtle坐标系

输入命令:rosrun rviz rviz -drospack find turtle_tf/rviz/turtle_rviz.rviz
用键盘控制小乌龟移动,观测rviz中坐标系的变化
在这里插入图片描述

tf消息

  • tf/tfMessage.msg
  • tf2_msgs/TFMessage.msg
  • 查询tf的类型:rostopic info /tf
    在这里插入图片描述

tf相关数据类型

  • 向量:tf::Vector3
  • 点:tf::Point
  • 四元数:tf::Quaternion
  • 3x3矩阵(旋转矩阵):tf::Matrix3x3
  • 位姿:tf::Pose
  • 变换:tf::Transform
  • 带时间戳的以上类型:tf::Stamped<T>
  • 带时间戳的变换:tf::StampedTransform
tf::TransformBroadcaster
TransformBroadcaster()
void sendTransform(const StampedTransform &transform)
void sendTransform(const std::vector<StampedTransform> &transforms)
void sendTransform(const geometry_msgs::TransformStamped &transform)
void sendTransform(const std::vector<geometry_msgs::TransformStamped> &transforms)
tf::TransformListener
void lookupTransform(const std::string &target_frame, 
	const std::string &source_frame, const ros::Time &time,
	StampedTransform &transform) const 

bool canTransform()
bool waitForTransform() const 

操作小记

写一个tf发布器

创建一个tf发布器,发布tf关系,父坐标系为word,子坐标系为turtle_name

创建一个功能包

catkin_create_pkg learning_tf tf roscpp rospy turtlesim

在src文件下新建一个turtle_tf_broadcaster.cpp写入以下代码
#include <ros/ros.h>
#include <tf/transform_broadcaster.h>
#include <turtlesim/Pose.h>

std::string turtle_name;


void poseCallback(const turtlesim::PoseConstPtr& msg){
  static tf::TransformBroadcaster br;
  tf::Transform transform;
  transform.setOrigin( tf::Vector3(msg->x, msg->y, 0.0) );
  tf::Quaternion q;
  q.setRPY(0, 0, msg->theta);
  transform.setRotation(q);
  br.sendTransform(tf::StampedTransform(transform, ros::Time::now(), "world", turtle_name));
}

int main(int argc, char** argv){
  ros::init(argc, argv, "my_tf_broadcaster");
  if (argc != 2){
	  ROS_ERROR("need turtle name as argument"); 
	  return -1;
  };
  turtle_name = argv[1];

  ros::NodeHandle node;
  ros::Subscriber sub = node.subscribe(turtle_name+"/pose", 10, &poseCallback);

  ros::spin();
  return 0;
};
修改CMakeLists.txt文件
add_executable(turtle_tf_broadcaster src/turtle_tf_broadcaster.cpp)
target_link_libraries(turtle_tf_broadcaster ${catkin_LIBRARIES})
编译:catkin_make

正常情况下将在下图所示的目录下生成turtle_tf_broadcaster节点
在这里插入图片描述

在learning_tf下新建一个launch文件夹,并在其中新建一个start_demo.launch文件
<launch>
    <!-- 打开Turtlesim Node,小乌龟-->
    <node pkg="turtlesim" type="turtlesim_node" name="sim"/>

	<!-- 打开键盘控制程序 -->
    <node pkg="turtlesim" type="turtle_teleop_key" name="teleop" output="screen"/>
    <!-- Axes -->
    <param name="scale_linear" value="2" type="double"/>
    <param name="scale_angular" value="2" type="double"/>

	<!-- 以turtle1为命名打开了一个发布器 -->
    <node pkg="learning_tf" type="turtle_tf_broadcaster" args="/turtle1" name="turtle1_tf_broadcaster" />
    
    <!-- 以turtle2为命名打开了一个发布器 -->
    <node pkg="learning_tf" type="turtle_tf_broadcaster" args="/turtle2" name="turtle2_tf_broadcaster" />
   
</launch>
运行命令查看当前tf树

rosrun rqt_tf_tree rqt_tf_tree
在这里插入图片描述
思考:为什么我们运行了两个tf_learning节点分别命名为turtle1和turtle2,而只有turtle1的坐标系发布出来了?

提示:可以运行rqt_graph查看节点,得出答案

写一个tf监听器

创建一个订阅者:订阅乌龟的位置

在src文件下新建一个turtle_tf_listener.cpp写入以下代码
// 头文件包含
#include <ros/ros.h>
#include <tf/transform_listener.h>
#include <geometry_msgs/Twist.h>
#include <turtlesim/Spawn.h>

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

  ros::NodeHandle node;

  // 调用服务生成第二只乌龟
  ros::service::waitForService("spawn");
  ros::ServiceClient add_turtle =
    node.serviceClient<turtlesim::Spawn>("spawn");
  turtlesim::Spawn srv;
  add_turtle.call(srv);

  // 创建一个话题发布器,发布第二只乌龟运行的速度
  ros::Publisher turtle_vel =
    node.advertise<geometry_msgs::Twist>("turtle2/cmd_vel", 10);

  // 创建tf侦听器listener
  tf::TransformListener listener;

  ros::Rate rate(10.0);
  while (node.ok()){
    tf::StampedTransform transform;
    try{
      // 最多等待10秒,如果提前得到了坐标的转换信息,直接结束等待
      listener.waitForTransform("/turtle2", "/turtle1", ros::Time(0), ros::Duration(10.0));
      // 从tf上侦听turtle2在turtle1坐标系中的位置,将该位置存储在transform中
      listener.lookupTransform("/turtle2", "/turtle1", ros::Time(0),  transform);
    }
    catch (tf::TransformException &ex) {
      ROS_ERROR("%s",ex.what());
      ros::Duration(1.0).sleep();
      continue;
    }

    geometry_msgs::Twist vel_msg;
    vel_msg.angular.z = 4.0 * atan2(transform.getOrigin().y(),
                                    transform.getOrigin().x());
    vel_msg.linear.x = 0.5 * sqrt(pow(transform.getOrigin().x(), 2) +
                                  pow(transform.getOrigin().y(), 2));
    // 计算turtle2跑的速度和方向
    turtle_vel.publish(vel_msg);

    rate.sleep();
  }
  return 0;
};
修改CMakeLists.txt文件
add_executable(turtle_tf_listener src/turtle_tf_listener.cpp)
target_link_libraries(turtle_tf_listener ${catkin_LIBRARIES} )
编译:catkin_make
在start_demo.launch中添加以下代码:

<node pkg="learning_tf" type="turtle_tf_listener" name="listener" />

运行

roslaunch learning_tf start_demo.launch

效果

一般一步实现了前面例子的乌龟跟随
在这里插入图片描述

运行 rqt_graph

分析是turtle1跟着turtle2跑还是turtle2跟着turtle1跑?

在这里插入图片描述

添加一个坐标系

为什么要添加坐标系?
  • 对于许多问题,在它自身的坐标系中思考是非常容易的,比如在二维激光雷达自身的坐标系中,推算障碍物的方位是非常容易的
  • tf允许你为系统中所有的传感器,部件定义自身坐标系,前面讲述的urdf建模时,就自动生成了tf树
  • 但如果要处理系统外部的问题,如果能够随时添加一个坐标系的话,将会非常方便
  • tf所建立的坐标系关系为树状结构,他不允许坐标系结构中存在闭环,也就是说一个坐标系只能有一个父级,但是可以有多个子级
  • 目前,我们的tf树包含三个坐标系,world,turtle1,turtle2。turtle1和turtle2为world的子级
    在这里插入图片描述
  • 因此如果我们想添加新的坐标系到tf中的话,我们必须选择一个现存的坐标系作为父级

操作小记

src/learning_tf/src下创建文件frame_tf_broadcaster.cpp,写入以下代码:

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

int main(int argc, char** argv){
  ros::init(argc, argv, "my_tf_broadcaster");
  ros::NodeHandle node;

  tf::TransformBroadcaster br;
  tf::Transform transform;

  ros::Rate rate(10.0);
  while (node.ok()){
    transform.setOrigin( tf::Vector3(0.0, 2.0, 0.0) );
    // 子坐标系在父坐标系中的初始姿态
    transform.setRotation( tf::Quaternion(0, 0, 0, 1) );
    // 发布一个以turtle1为父级命名为carrot1的坐标系
    br.sendTransform(tf::StampedTransform(transform, ros::Time::now(), "turtle1", "carrot1"));
    rate.sleep();
  }
  return 0;
};

在CMakeList.txt中添加如下代码:

add_executable(frame_tf_broadcaster src/frame_tf_broadcaster.cpp)
target_link_libraries(frame_tf_broadcaster ${catkin_LIBRARIES})

编译:catkin_make

在start_demo.launch中添加如下代码:
<node pkg="learning_tf" type="frame_tf_broadcaster" name="broadcaster_frame" />

运行 roslaunch learning_tf start_demo.launch
运行命令查看tf树:rosrun rqt_tf_tree rqt_tf_tree
在这里插入图片描述
此时,操作键盘控制乌龟移动,发现跟之前的行为并没有什么区别
在turtle_tf_listener.cpp文件中做以下修改:

try{
      listener.waitForTransform("/turtle2", "/carrot1", ros::Time(0), ros::Duration(10.0));
      listener.lookupTransform("/turtle2", "/carrot1", ros::Time(0),  transform);
}

重新编译运行,查看效果跟之前的区别


之前,我们创建了一个固定关系的坐标系,它相对于父级是不会变化的。现在创建一个动态的坐标系
修改frame_tf_broadcaster.cpp中对应的代码:

  while (node.ok()){
    transform.setOrigin( tf::Vector3(2.0*sin(ros::Time::now().toSec()), 2.0*cos(ros::Time::now().toSec()), 0.0) );
    transform.setRotation( tf::Quaternion(0, 0, 0, 1) );
    br.sendTransform(tf::StampedTransform(transform, ros::Time::now(), "turtle1", "carrot1"));
    rate.sleep();
  }

编译运行,观察现象

tf和时间

  • 在前面的内容中我们学习了如何跟踪tf树上的坐标系
  • tf树是随时间变化的,tf为tf树上的每个坐标系之间的转换都会缓存一定的时间
  • 我们用lookupTransform()函数可获取到最近的转换关系,但是我们并不知道该转换关系对应的时间
  • 接下来学习如何得到一个转换关系在一个特定的时间
操作小记

打开turtle_tf_listener.cpp,原来代码为:
在这里插入图片描述
ros::Time(0)参数指的就是获取当前最新的转化关系,将代码做如下修改:
在这里插入图片描述
该段代码是指获取当前时间点的转换关系
编译:catkin_make
运行:roslaunch learning_tf start_demo.launch
运行时会出现一个错误:该错误是由于turtle2的生成需要一定的时间,当我们第一次要询问转换关系时,turtle2还没有生成
在这里插入图片描述


如何获取5S前的坐标系转换关系?
修改代码如下:
在这里插入图片描述
编译:catkin_make
运行:roslaunch learning_tf start_demo.launch
在这里插入图片描述
感觉第二只小乌龟完全不受控!
原因在于,我们获取的相对关系是5s前的,5s前的turtle2和turtle1之间的关系


如何让turtle2跟着turtle1 5s前的位置运行呢?
在这里插入图片描述
一共包含了6个参数:

  1. 要转换的目标坐标系;
  2. 在什么时间;
  3. 源坐标系;
  4. 在什么时间;
  5. 不随时间变化的坐标系;
  6. 存储结果的变量

在这里插入图片描述
上图显示了坐标系转换的过程:

  1. tf计算在past的时间点turtle1和世界坐标系之间的关系
  2. 随着时间推移到达现在的时间点,计算turtle2和世界坐标系之间的关系
  3. tf计算当前turtle2和past时间点turtle1之间的关系

在这里插入图片描述
编译:catkin_make
运行:roslaunch learning_tf start_demo.launch

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

坐标转换tf 的相关文章

  • C| |头文件中为什么只声明不定义,而类定义又可以放在头文件中

    头文件中为什么只声明不定义 xff0c 而类定义又可以放在头文件中 首先要了解几个基本概念 xff1a 编译单元 对于c语言 xff0c 每一个 c文件就是一个编译单元 仅仅从编译来说 xff0c 各个编译单元之间没有联系 未解决符号表 提
  • C#软件工程师、 .NET、 上位机软件开发工程师秋招面经八股汇总 及心得

    博主从七月到十月底一共投了142家企业 xff0c 流程走完的有9家 xff0c 收到7个offer xff0c 目前三方已签 xff0c 很满意签约的公司 xff0c 现在把这几个月我遇到常见问题写下来 xff0c 希望能帮助到大家 心得
  • 网络编程--网络字节序和主机字节序详解

    NBO 网络字节序 HBO 主机字节序 LE little endian xff1a 小端 BE big endian xff1a 大端 空中传输的字节的顺序即网络字节序为标准顺序 xff0c 考虑到与协议的一致以及与同类其它平台产品的互通
  • 实现batch内负采样和解决报错:tensorflow.python.framework.errors_impl.InvalidArgumentError

    在我们实现双塔等模型时一些负样本难以获取 xff0c 这时我们可以通过batch内负采样的方式来实现训练 xff0c 此时采集的样本数据仅需要正样本就够了 我们先来看一个案例 xff0c 通过此案例来理解此代码 import tensorf
  • RabbitMQ安装和使用(docker版本)

    1 查找镜像 xff1a xff08 management 版本的镜像才有管理界面 xff09 docker search rabbitmq management 2 拉取镜像 xff1a docker pull docker io mac
  • OpenCV与图像处理学习七——传统图像分割之阈值法(固定阈值、自适应阈值、大津阈值)

    OpenCV与图像处理学习七 传统图像分割之阈值法 xff08 固定阈值 自适应阈值 大津阈值 xff09 一 固定阈值图像分割1 1 直方图双峰法1 2 OpenCV中的固定阈值分割 二 自动阈值图像分割2 1 自适应阈值法2 2 迭代法
  • 驱动编写入门

    按键控制led驱动 一 框架 1 open read write 函数 static int second drv open struct inode inode struct file file 配置GPF0 2为输入 gpfcon am
  • OpenWrt与嵌入式Linux

    OpenWrt与嵌入式Linux 由于要接手学长留下来的一个项目 xff0c 被迫 要学习OpenWrt的配置方法 虽然对于一个five电工来说这事挺莫名其妙的 xff0c 但还是硬着头皮上吧 xff08 我本想拒绝 xff0c 但他给的是
  • ROS学习笔记#3 package.xml解释

    我们都知道在catkin下创建功能包时 会自动生成一些文件 文件夹 其中就有这个package xml 它主要由以下部分组成 描述tag维护tag开源tag依赖tag结尾tag 描述tag span class token operator
  • idea多模块打包

    多模块打包的办法有两个 1 在parent的pom下执行deploy 这样就会自动将父 pom以及子 module都发布到仓库 在模块中添加如下选项 lt distributionManagement gt lt repository gt
  • Linux系统中永久设置GVIM的字体、背景颜色和显示行数等

    在GVIM窗口界面 xff0c 手动改变字体大小 高亮 背景色等之后 xff0c 下次打开依旧是默认配置 因此介绍一种永久设置的方法 xff1a 一 配置命令 set gfn 61 Tlwg Typist 12 colorscheme de
  • ROS安装和MAVROS以及PX4的安装

    只能说怀着沉重的心情 xff0c 本来不想写的 xff0c 但是又还是害怕后续出什么幺蛾子 xff0c 就记录一下 xff0c 希望自己永远没有机会在看这篇文章 文章目录 ROS安装 ubuntu18 04安装melodic 1 Ubunt
  • C#中=>使用

    目录 一 目的 1 1 想知道 xff1a C 中 61 gt 使用 的意思 二 参考 xff1a 1 C 中 61 gt 表示什么意思 xff1a 1 C 中 61 gt 是什么意思 三 注意 四 操作 xff1a 成功 1 总结 2 代
  • UE4如何将虚幻商城资源导入到自己的工程中+保管库的使用

    一 目的 xff1a 1 导入资源到UE4工程里面很多 xff0c 下面介绍一个 一 参考 1 Unreal初级案例 动作游戏入门中 保管库的使用 http www sikiedu com course 514 tasks 总结 xff1a
  • UE4纯C++与Slate开发沙盒游戏:1.项目介绍与资源获取

    目录 一 目的 xff1a 1 以前看教程 xff0c 编写的笔记都是word版本 xff0c 公司现在文档都加密了 xff0c 发现复习的几率很小 xff0c 而且有时候查找起来很是不好找 xff0c 所以将其发布在CSDN上面 xff0
  • 如何写c++简历

    目录 一 目的 xff1a 1 想知道如何写C C 43 43 方面的简历 1 从别人简历哪里了解一下自己的不足 二 参考 1 c 43 43 软件工程师个人简历大全 1 转 xff1a C C 43 43 程序员简历模板 1 C 43 4
  • 解决sentinel key not found (h0007) Unity

    一 目的 1 电脑重做系统后 xff0c 打开Unity项目跳出了sentinel key not found h0007 Unity对话框 二 参考 1 sentinel key not found h0007 Unity https b
  • adb学习:六(成功):adb命令卸载APK文件

    目录 一 目的 1 想知道 xff1a adb命令卸载APK文件 二 参考 1 adb安装和卸载apk的方式 三 注意 1 安装的命令 四 操作 1 完成 xff1a 能实现卸载apk 1 操作 四 操作 2 系统文件不能够卸载 使用adb
  • unity动态修改标准材质自发光(Emission)

    目录 一 目的 1 想知道 xff1a unity动态修改标准材质自发光 xff08 Emission xff09 二 参考 1Unity利用材质自发光实现物体闪烁 三 操作 xff1a 一 xff1a 完成 xff1a 变换材质自发光的数
  • maven导入本地jar包

    最近看 https github com junicorn kira 实现的java的代码 有个库发现没法使用maven安装 https mvnrepository com artifact com bladejava blade kit

随机推荐

  • GitHubDesktop:学习:三:(第一次操作)GitHubDesktop进行创建分支+合并分支:成功

    目录 一 目的 1 想知道 xff1a GitHubDesktop进行创建分支 1 想知道 xff1a GitHubDesktop进行合并分支 二 参考 1 0基础的git教程 xff0c 傻瓜都会用的Github Desktop 三 总结
  • 鱼眼+红外+IMU+VSLAM+SLAM

    一 目的 1 想知道 xff1a 二 参考 1 一分钟详解鱼眼镜头标定基本原理及实现 https mp weixin qq com s VyxoTaYtYPB Bfh3JCXl1A 三 注意 四 操作
  • VSLAM:一:VSLAM小科普

    一 目的 1 想知道 xff1a VSLAM小科普 1 将其转载 xff0c 避免作者删除 xff0c 就没有了 二 参考 1 VSLAM小科普 https zhuanlan zhihu com p 121601875 百度百科 三 注意
  • Unity3D:问题(成功):如何解决:Unity2019新建工程都空白红色感叹号报错

    目录 一 目的 1 如何解决 Unity2019新建工程都空白红色感叹号报错 2 Unity2019好几个版本新建工程都有红色感叹号空白报错 xff0c Unity卸载安装 UnityHUB卸载安装都试过 xff0c 许可证个人的 xff0
  • Unity用UGUI实现省份选择

    参考 Unity3D中使用UGUI实现省市选择器 YOLO TO GAME的博客 CSDN博客
  • Unity3D中Resources动态加载图片

    问题 xff1a unity的Resources动态加载就不必多说了 xff0c 这里出现的问题是当我把图片放入Resources文件夹后 xff0c 使用Resources Load xff08 datapath xff09 却并没有出现
  • Navicat报错:1045-Access denied for user root@localhost(using password:YES)

    解决 xff1a Navicat报错 xff1a 1045 Access denied for user root 64 localhost using password YES SET PASSWORD FOR 39 root 39 64
  • UE4添加音乐、音效

    目录 一 目的 xff1a 1 想 xff1a UE4添加音乐 音效 二 参考 1 三 操作 xff1a 完成 1 前述 xff1a 1 导入音乐 1 创建Cue 1 Cue进行设置 1 创建音乐 1 播放和暂停音乐 一 目的 xff1a
  • 《嵌入式C语言自我修养》书评

    首先 xff0c 介绍本书的内容 笔者从嵌入式工程师的视角出发 xff0c 先为我们初学者补上硬件相关基础 xff0c 如计算机工作原理和系统结构 xff08 理解程序编译 链接 安装和运行机制 xff09 CPU的工作原理 xff08 理
  • SLAM14讲之第五讲--像素坐标系、畸变、双目相机深度求解

    像素坐标系 由相似三角形的定义可得 xff1a 这是相对于成像平面的坐标变化 xff0c 我们实际上所得到的图片还要经历一层成像平面到像素平面的变换 xff0c 实际上就是相差了一个缩放和原点的平移 如此我们定义 xff1a u为横轴向右与
  • python webkit 异步抓取页面数据

    usr bin python from ghost import Ghost class FetcherCartoon def getCartoonUrl self url if url is None return false todo
  • 树莓派 Ubuntu mate 16.04使用VNC开启远程桌面

    1 安装 vncserver sudo apt span class token operator span get span class token operator span y install vnc4server 2 启动 vncs
  • 数学建模(四)-----最优化问题-----Simulate Anneal Arithmetic

    模拟退火算法的应用很广泛 xff0c 可以较高的效率求解最大截问题 Max Cut Problem 0 1背包问题 Zero One Knapsack Problem 图着色问题 Graph Colouring Problem 调度问题 S
  • 路径规划的优化

    因为这个求N个点的最短路径是将把所有可能的走法都可能尝试一遍 这样的话 如果计算十几个点之间的最短路径是没有问题的 但是问题就在如果超过二十个点位 那么最坏的情况就是需要计算20的阶乘个 这个计算是相当高的 可能会把线上的服务器打爆 或者计
  • SPL06电容式压力传感器数据读取与处理(基于STM32)

    该例程使用的开发板为正点原子的精英板F103 xff0c 相关资料请大家自行去正点原子论坛下载 首先来看一下SPL06的简介 xff0c SPL06的压强测量范围30kPa 110kPa xff0c 最大供电电压为3 6V xff0c 相对
  • 企业微信开发实战(六、自建应用-审批流程引擎之配置可信任域名、创建审批模版、发起审批)

    文章目录 4 自建应用审批状态变化通知回调4 1概述4 2代码实战 5 查询自建应用审批单当前状态5 1概述5 2代码实战 源码赞赏 4 自建应用审批状态变化通知回调 4 1概述 1 企业可以在管理后台 自建应用 设置API接收中 xff0
  • FreeRTOS内存管理之heap_4.c

    FreeRTOS内存管理之heap 4 c源码解析 每当创建任务 队列 互斥量 软件定时器 信号量或事件组时 xff0c RTOS内核会为它们分配RAM 标准函数库中的malloc 和free 函数有些时候能够用于完成这个任务 xff0c
  • git图形化管理工具

    一 独立客户端工具 1 GitHub for Desktop 全球开发人员交友俱乐部提供的强大工具 xff0c 功能完善 xff0c 使用方便 对于使用GitHub的开发人员来说是非常便捷的工具 界面干净 xff0c 用起来非常顺手 xff
  • ROS功能包

    ROS package介绍 package是什么呢 xff1f 指的是一种特定的文件结构和文件夹组合 通常将实现同一个具体功能的程序代码放到一个package中 xff0c 比如实现相机数据采集这一功能 文件结构 CMakeLists tx
  • 坐标转换tf

    tf介绍 坐标转换 TransForm 位置和姿态 坐标变换是空间实体的位置描述 xff0c 是从一种坐标系统变换到另一种坐标系统的过程 通过建立两个坐标系统之间一一对应关系来实现下图为机器人几个部件之间的坐标关系 tf概念 tf是一个用户