从URDF到KDL(C++&Python)

毕竟我也是一个搞机器人的,今天就来写一些和机器人紧密相关的事情。

  • 从URDF到KDLCPython

    • KDL 简介
    • URDF模型
    • KDL C
    • KDL Python

KDL 简介

PyKDL是一个神奇的库。里面包含了KDL库与vector,rotation, frame, kinematics, dynamics的相关函数和接口。计算机器人学中的运动学/动力学和坐标变换都是相当的彪悍。甚至可以加载urdf模型计算运动学,调用DH相关接口或者chain接口直接创建机器人模型。这个库主要是面向C++的,通过sig的形式做了相应的python接口。这里先讨论论c++中KDL的使用。
wiki tutorials
official site and git
python documentation
python kdl git

URDF模型

URDF模型是用于描述机器人运动学参数、动力学参数的配置文件。可以从多种来源获得,比如Solidworks可以直接保存出来。当然也可以自己编写,并不是很繁琐。
这篇教程清晰地写明了如何创建URDF模型。还是把最终的代码贴上来:

<robot name="test_robot"><link name="link1" /><link name="link2" /><link name="link3" /><link name="link4" /><joint name="joint1" type="continuous"><parent link="link1"/><child link="link2"/><origin xyz="5 3 0" rpy="0 0 0" /><axis xyz="-0.9 0.15 0" /></joint><joint name="joint2" type="continuous"><parent link="link1"/><child link="link3"/><origin xyz="-2 5 0" rpy="0 0 1.57" /><axis xyz="-0.707 0.707 0" /></joint><joint name="joint3" type="continuous"><parent link="link3"/><child link="link4"/><origin xyz="5 0 0" rpy="0 0 -1.57" /><axis xyz="0.707 -0.707 0" /></joint>
</robot>

为了check模型的准确性,这篇教程还简单说明了如何使用urdfdom解析我们创建的URDF模型。还有urdfdom python教程
上述URDF模型代码对应的机构学模型如下:(串联、并联和混联机构都可以写出来)

ROS官方给出的下一篇教程是如何在C++中parse urdf模型。我们这里直接使用URDF模型,因此不过多探讨parse这篇博客。

KDL C++

关键点来了,对于机器人常见的运动学和动力学问题,如何使用这个高效的KDL库进行运算和求解呢?首先是正运动学的求解。

#include <kdl/kdl.hpp>
#include <kdl/chain.hpp>
#include <kdl/tree.hpp>
#include <kdl/segment.hpp>
#include <kdl/chainfksolver.hpp>
#include <kdl_parser/kdl_parser.hpp>
#include <kdl/chainfksolverpos_recursive.hpp>
#include <kdl/frames_io.hpp>
#include <stdio.h>
#include <iostream>using namespace KDL;
using namespace std;
int main(int argc,char** argv){Tree my_tree;kdl_parser::treeFromFile("/home/file/catkin_ws/src/KDL_Test/src/ur3_robot.urdf",my_tree);bool exit_value;Chain chain;exit_value = my_tree.getChain("base","tool0",chain);ChainFkSolverPos_recursive fksolver = ChainFkSolverPos_recursive(chain);unsigned int nj = chain.getNrOfJoints();JntArray jointpositions = JntArray(nj);for(unsigned int i=0;i<nj;i++){float myinput;printf("Enter the position of joint %i: ",i);scanf("%e",&myinput);jointpositions(i)=(double)myinput;
}Frame cartpos;bool kinematics_status;kinematics_status = fksolver.JntToCart(jointpositions,cartpos);if(kinematics_status>=0){std::cout << cartpos << std::endl;printf("%s \n","Success, thanks KDL!");}else{printf("%s \n","Error:could not calculate forward kinematics : ");}
}

然后是逆运动学的求解。

#include <kdl/kdl.hpp>
#include <kdl/chain.hpp>
#include <kdl/tree.hpp>
#include <kdl/segment.hpp>
#include <kdl/chainfksolver.hpp>
#include <kdl/chainiksolver.hpp>
#include <kdl/chainiksolverpos_lma.hpp>
#include <kdl/chainiksolverpos_nr.hpp>
#include <kdl/chainiksolverpos_nr_jl.hpp>
#include <kdl_parser/kdl_parser.hpp>
#include <kdl/chainfksolverpos_recursive.hpp>
#include <kdl/frames_io.hpp>
#include <kdl/frames.hpp>
#include <stdio.h>
#include <iostream>using namespace KDL;
using namespace std;
int main(int argc,char** argv){Tree my_tree;kdl_parser::treeFromFile("/home/file/catkin_ws/src/KDL_Test/src/ur3_robot.urdf",my_tree);bool exit_value;Chain chain;exit_value = my_tree.getChain("base","tool0",chain);double eps=1E-5;int maxiter=500;double eps_joints=1E-15;ChainIkSolverPos_LMA iksolver = ChainIkSolverPos_LMA(chain,eps,maxiter,eps_joints);unsigned int nj = chain.getNrOfJoints();JntArray jointGuesspositions = JntArray(nj);for(unsigned int i=0;i<nj;i++){float myinput;printf("Enter the initial guess position of joint %i: ",i);scanf("%e",&myinput);jointGuesspositions(i)=(double)myinput;
}double x,y,z;printf("Enter the x: ");scanf("%lf",&x);printf("Enter the y: ");scanf("%lf",&y);printf("Enter the z: ");scanf("%lf",&z);Vector vector = Vector(x,y,z);float roll,pitch,yaw;printf("Enter the roll: ");scanf("%e",&roll);printf("Enter the pitch: ");scanf("%e",&pitch);printf("Enter the yaw: ");scanf("%e",&yaw);float cy = cos(yaw);float sy = sin(yaw);float cp = cos(pitch);float sp = sin(pitch);float cr = cos(roll);float sr = sin(roll);double rot0 = cy*cp;double rot1 = cy*sp*sr - sy*cr;double rot2 = cy*sp*cr + sy*sr;double rot3 = sy*cp;double rot4 = sy*sp*sr + cy*cr;double rot5 = sy*sp*cr - cy*sr;double rot6 = -sp;double rot7 = cp*sr;double rot8 = cp*cr;Rotation rot = Rotation(rot0,rot1,rot2,rot3,rot4,rot5,rot6,rot7,rot8);Frame cartpos = Frame(rot,vector);JntArray jointpositions = JntArray(nj);bool kinematics_status;kinematics_status = iksolver.CartToJnt(jointGuesspositions,cartpos,jointpositions);if(kinematics_status>=0){for(int i=0;i<nj;i++){std::cout << jointpositions(i) << std::endl;}printf("%s \n","Success, thanks KDL!");}else{printf("%s \n","Error:could not calculate backword kinematics : ");}
}

这里需要注意的有三点:
1. 运动学正解输出的是4×4的坐标变换矩阵,如需变成位姿、四元数或者欧拉角需要进行额外的转换。
2. 运动学逆解的计算需要输入目标位姿和迭代角度初值,初值设置不要太离谱,不然就收敛不过去了,就好比深度学习权重初始值不能随机太夸张,否则就会not a number一样。
3. cmakefile里面各种库的地址要搞正确。

KDL Python

python版本我调研了两天。因为我的机器人主控框架是基于python写的,如果采用上述C++版本就需要把这个求解器搞成ros节点,每次调用的时候需要ros通信。事实上此前我都是这样做的,但是我觉得要是能变成python函数每次使用直接调用肯定方便很多,于是我就这样弄了。
首先是如何在python中解析URDF模型:

from urdf_parser_py.urdf import URDF
from pykdl_utils.kdl_parser import kdl_tree_from_urdf_model
robot = URDF.from_xml_file('/home/file/catkin_ws/src/KDL_Test/src/ur3_robot.urdf') # get a tree

然后在python中求解机构的运动学正逆解非常方便:

# KDL version 1
#!/usr/bin/env python
#-*- coding:utf-8 -*-
############################
#File Name: kdl_module.py
#Author: Wang
#Mail: wang19920419@hotmail.com
#Created Time:2017-09-09 10:51:39
############################import sys
sys.path.insert(0, "/home/file/catkin_ws/src/Basic_math/hrl-kdl-indigo-devel/hrl_geom/src")
sys.path.insert(0, "/home/wangxu/catkin_ws/src/Basic_math/hrl-kdl-indigo-devel/pykdl_utils/src")from urdf_parser_py.urdf import URDF
from pykdl_utils.kdl_kinematics import KDLKinematics
from pykdl_utils.kdl_parser import kdl_tree_from_urdf_modelrobot = URDF.from_xml_file("/home/file/catkin_ws/src/KDL_Test/src/ur3_robot.urdf")
tree = kdl_tree_from_urdf_model(robot)
print tree.getNrOfSegments()
chain = tree.getChain("base", "tool0")
print chain.getNrOfJoints()
kdl_kin = KDLKinematics(robot, "base_link", "ee_link", tree)
q = [0,0,0,0,0,0]
pose = kdl_kin.forward(q) # forward kinematics (returns homogeneous 4x4 numpy.mat)
q_ik = kdl_kin.inverse(pose, [0.1,0.1,-0.1,0.1,0.1,0.1]) # inverse kinematics
if q_ik is not None:pose_sol = kdl_kin.forward(q_ik) # should equal pose
#J = kdl_kin.jacobian(q)
print 'q:', q
print 'q_ik:', q_ik
print 'pose:', pose
if q_ik is not None:print 'pose_sol:', pose_sol
#print 'J:', J

需要说明的:
1. 运动学正解输出的是4×4的坐标变换矩阵,如需变成位姿、四元数或者欧拉角需要进行额外的转换。
2. 运动学逆解的计算需要输入目标位姿和迭代角度初值,初值设置不要太离谱,不然就收敛不过去了,就好比深度学习权重初始值不能随机太夸张,否则就会not a number一样。
3. 如需其他开发,就要在这个基础上增加其他函数,见仁见智。
4. 无论是C++还是python,使用kdl都需要先将urdf parse成kdl能理解的模型。于是就有了两个语言的parser方法:
对应c++:
(http://docs.ros.org/api/kdl_parser/html/namespacekdl__parser.html)
(http://wiki.ros.org/kdl_parser/Tutorials/Start%20using%20the%20KDL%20parser)
对应于python:
(http://wiki.ros.org/pykdl_utils)

KDL是通用的运动学动力学库,对于复杂的运动学问题,比如并联机构的正解问题、串联机构的反解问题、冗余机构的无穷解问题都是利器。

从URDF到KDL(C++Python)相关推荐

  1. orocod_kdl学习(一):坐标系变换

    KDL中提供了点(point).坐标系(frame).刚体速度(twist),以及6维力/力矩(wrench)等基本几何元素,具体可以参考 Geometric primitives 文档. Creat ...

  2. 由浅到深理解ROS URDF教程

    创建自己的URDF文件 1.1创建树形结构文件 在这部分教程中要创建的将是下面的图形所描述的机器人的urdf文件 图片中这个机器人是一个树形结构的.让我们开始非常简单的创建这个树型结构的描述文件,不用 ...

  3. ROS机器人建模与仿真(一)——URDF模型的建立和改进

    申明:本系列参考古月大神教材<ROS机器人开发实践>第六章内容,结合自己学习过程和遇到的问题逐一分解,争取能够吃透!欢迎大家一起讨论! URDF 是 ROS 中机器人模型的描述格式,包含对 ...

  4. 基于 solidworks2021 的三维仿真模型转 ros URDF

    1.SolidWorks转URDF的插件下载和安装 下载sw_urdf_exporter插件 下载后直接运行sw2urdfSetup.exe,将文件安装在SOLIDWORKS安装路径下 2.Solid ...

  5. Solidworks导出URDF总结(Noetic)

    环境 Solidwoks2018 SP0 / Solidwoks2021 SP5: Ubuntu20.04: ROS1 Noetic; Solidwoks2018 SP0对于平移副有问题,显示不出来, ...

  6. urdf 怎么添加头文件_URDF教程

    创建自己的URDF文件 1.1创建树形结构文件 在这部分教程中要创建的将是下面的图形所描述的机器人的urdf文件  图片中这个机器人是一个树形结构的.让我们开始非常简单的创建这个树型结构的描述文件,不 ...

  7. Dofbot机械臂从零部署笔记(1)——ROS之创建URDF模型、配置Moveit和MotionPlanning

    文章目录 从零部署之创建URDF模型 0 创建新工作空间 1 创建URDF模型测试功能包 2 dofbot机械臂的urdf模型 3 meshes 4 launch文件 5 编译并运行 6 运行效果 7 ...

  8. [失败]uuv_simulator在台式机_虚拟环境下会崩溃的问题[失败]

    台式机下的系统环境下可以跑uuv 笔记本下的虚拟环境下可以跑uuv 目前遇到的问题是,台式机下的虚拟环境跑不了uuv 接下来好好debug 终端1运行 source activate py27 cd ...

  9. UR机械臂学习(6):使用robotiq二指夹爪

    在ros中下载的ur机器人包里不包括夹爪.力传感器等Robotiq的产品. Robotiq相关产品的ros功能包可以在 https://github.com/ros-industrial/roboti ...

  10. 使用Baxter仿真器学习一下机械臂的控制

    Baxter simulator由ReThink Robotics公司提供,是一个合理可靠的机器人模型.仿真器和实体机器人模型都有相同的ROS接口,所以在仿真器下开发的程序都可以在相应的实体机器人上快 ...

最新文章

  1. CentOS使用chkconfig增加开机服务提示service xxx does not support chkconfig的问题解决
  2. BZOJ1801: [Ahoi2009]chess 中国象棋
  3. 最短路径算法(一) Dijkstra算法(贪心算法)
  4. 我,大学没毕业,在OpenAI搞AI,想教教你如何提升“研究品味”
  5. Kali 2020版 Linux操作系统解决系统语言问题(英文--中文)
  6. k8s学习: 创建 mysql 任务
  7. UnicodeDecodeError: ‘utf-8‘ codec can‘t decode byte 0xb4 in position 176: in xxxx
  8. Xfce 4.4 beta2
  9. excel 趋势线的定义
  10. 跟着翁凯老师学Cday1#学习记录#
  11. 360腾讯计算机比赛,巅峰对决 腾讯电脑管家VS360详尽评测
  12. OceanBase使用 OBD 自动化部署多节点集群
  13. java 生成二维码图片
  14. 5G注册流程分级详解
  15. excel怎么把两个表格合成一个
  16. css单元格固定宽度大小,超过部分使用省略号表示
  17. 普鸥知产|亚马逊品牌备案被判“滥用行为”无法备案如何解决?
  18. 软路由自建iptv服务器,LEDE软路由 iPTV 实现任意端口看电视的方法
  19. 5GNR漫谈1:NR物理层帧结构
  20. 2020-01-01T00:00:00.000000Z 日期格式转换

热门文章

  1. 计算机时间小于会计期间错误,会计期间手工记账和电脑记账不一样问题
  2. [渝粤教育] 中国地质大学 计算机会计理论与实务 复习题
  3. k8s中对pod设置限制只设置了limits
  4. 【Android安全】手机Root、刷机、救砖常用命令
  5. win 10 PHP开发环境配置
  6. java金蝉素数_回文素数 - 寂寞暴走伤的个人空间 - OSCHINA - 中文开源技术交流社区...
  7. Tire Defect Detection Using Fully Convolutional Network-论文阅读笔记
  8. 《美食街》项目---(登录篇){ ‘blur‘焦点属性,resetFields(),meta对象,$confirm,window.location.href=‘/‘}
  9. 优先队列push pop操作
  10. 飞桨《百度构架师手把手教深度学习》结营体验