ROS机械臂正逆运动学

2023-11-15

这里做一个六轴机械臂用于正逆运动学实验。

这里其实一共只有3轴,只有3轴位置没有姿态。所以urdf文件里我在末端做了3个虚拟关节,以便将kdl的frame能够填满,使得齐次坐标变换是规则的。

1.urdf建模

<?xml version="1.0" ?>

<!--           -->
<robot name="mbot">

    <!--   -->
    <link name="base_link" >
        <visual>
            <origin xyz="0 0 0" rpy="0 0 0" />
            <geometry>
                    <cylinder length="0.2" radius="0.1" />
            </geometry>
            <material name="yellow">
                <color rgba="1 0.4 0 1" />
            </material>
        </visual>
    </link>

        <!-- -->
    <joint name="joint1" type="continuous" >
        <origin xyz="0 0 0.15" rpy="0 0 0" />
        <parent link="base_link" />
        <child link="link1" />
        <axis xyz="0 0 1" />
    </joint>

    <!--  -->
    <link name="link1">
    <visual>
        <origin xyz="0 0 0" rpy="-1.57 0 0" />
        <geometry>
            <cylinder radius="0.05" length="0.05" />
        </geometry>
        <material name="white">
            <color rgba="1 1 1 0.9" />
        </material>
    </visual>
    </link>

    <joint name="joint2" type="continuous" >
        <origin xyz="0 0.075 0" rpy="-1.57 0 0" />
        <parent link="link1" />
        <child link="link2" />
        <axis xyz="0 0 1" />
    </joint>

    <link name="link2">
    <visual>
        <origin xyz="0 -0.15 0" rpy="1.57 0 0" />
        <geometry>
            <cylinder radius="0.05" length="0.3" />
        </geometry>
        <material name="white">
            <color rgba="1 1 1 0.9" />
        </material>
    </visual>
    </link>

     <joint name="joint3" type="continuous" >
        <origin xyz="0 -0.3  0" rpy="0 0 0" />
        <parent link="link2" />
        <child link="link3" />
        <axis xyz="0 0 1" />
    </joint>

    <link name="link3">
    <visual>
        <origin xyz="0 -0.15 0" rpy="-1.57 0 0" />
        <geometry>
            <cylinder radius="0.05" length="0.3" />
        </geometry>
        <material name="white">
            <color rgba="1 1 1 0.9" />
        </material>
    </visual>
    </link>

    <joint name="joint4" type="continuous" >
        <origin xyz="0 -0.3  0" rpy="1.57 0 0" />
        <parent link="link3" />
        <child link="link4" />
        <axis xyz="0 0 1" />
    </joint>

    <link name="link4">
    <visual>
        <origin xyz="0 0 0" rpy="0 0 0" />
        <geometry>
            <cylinder radius="0" length="0" />
        </geometry>
        <material name="white">
            <color rgba="1 1 1 0.9" />
        </material>
    </visual>
    </link>

     <joint name="joint5" type="continuous" >
        <origin xyz="0 0 0" rpy="-1.57 0 0" />
        <parent link="link4" />
        <child link="link5" />
        <axis xyz="0 0 1" />
    </joint>

    <link name="link5">
    <visual>
        <origin xyz="0 0 0" rpy="0 0 0" />
        <geometry>
            <cylinder radius="0" length="0" />
        </geometry>
        <material name="white">
            <color rgba="1 1 1 0.9" />
        </material>
    </visual>
    </link>

    <joint name="joint6" type="continuous" >
        <origin xyz="0 0 0" rpy="0 1.57 0" />
        <parent link="link5" />
        <child link="link6" />
        <axis xyz="0 0 1" />
    </joint>

    <link name="link6">
    <visual>
        <origin xyz="0 0 0" rpy="0 0 0" />
        <geometry>
            <cylinder radius="0" length="0" />
        </geometry>
        <material name="white">
            <color rgba="1 1 1 0.9" />
        </material>
    </visual>
    </link>








</robot>

如下图:

 

2. 编写正逆运动学程序

我这里只定义了两个机械臂状态,让机械臂在两个状态之间来回切换,以达到运动的效果,由于是实验,就没有规划末端轨迹

程序如下:

#include <iostream>
#include <string>
#include <vector>

#include "ros/ros.h"
#include "sensor_msgs/JointState.h"
#include "turtlesim/Pose.h"
#include "tf2_ros/static_transform_broadcaster.h"
#include "tf2_ros/transform_broadcaster.h"
#include "geometry_msgs/TransformStamped.h"
#include "tf2/LinearMath/Quaternion.h"
#include "kdl_parser/kdl_parser.hpp"
#include "kdl/chainiksolverpos_nr_jl.hpp"
#include "trac_ik/trac_ik.hpp"
#include "urdf/model.h"
#define pi 3.141592653

int main(int argc, char* argv[])
{
    setlocale(LC_ALL,"");
    ros::init(argc,argv,"dynamic_tf_pub");
    ros::NodeHandle nh;
    ros::Publisher joint_pub = nh.advertise<sensor_msgs::JointState>("joint_states", 1);
    //定义tf坐标广播器
    tf2_ros::StaticTransformBroadcaster broadcaster;
    geometry_msgs::TransformStamped ts;
    KDL::Vector v1(1,1,1);
    KDL::Tree my_tree;
    sensor_msgs::JointState joint_state;
    
    std::string robot_desc_string;
    nh.param("robot_description", robot_desc_string, std::string());
    
    if(!kdl_parser::treeFromString(robot_desc_string, my_tree))
    //if(!kdl_parser::treeFromFile("/home/zhitong/catkin_ws_serial/src/quadruped_9g-master/urdf/mbot_base.urdf", my_tree))
    {
        ROS_ERROR("Failed to construct kdl tree");
    }
    else
    {
        ROS_INFO("成功生成kdl树!");
    }
    std::vector<std::string> joint_name = {"joint1", "joint2", "joint3", "joint4","joint5","joint6"};
    std::vector<double> joint_pos = {0,0,0,0,0,0};
    
    std::string urdf_param = "/robot_description";
    double timeout = 0.005;
    double eps = 1e-5;
    std::string chain_start = "base_link"; 
    std::string chain_end = "link6"; 
    TRAC_IK::TRAC_IK tracik_solver(chain_start, chain_end, urdf_param, timeout, eps);
    KDL::Chain chain;
    KDL::JntArray ll, ul; //关节下限, 关节上限
    bool valid = tracik_solver.getKDLChain(chain);
    if(!valid)
    {
        ROS_ERROR("There was no valid KDL chain found");
    }
    valid = tracik_solver.getKDLLimits(ll, ul);
    if(!valid)
    {
        ROS_ERROR("There was no valid KDL joint limits found");
    }
    KDL::ChainFkSolverPos_recursive fk_solver(chain);
    ROS_INFO("关节数量: %d", chain.getNrOfJoints());
    KDL::JntArray nominal(6);
    ROS_INFO("the nominal size is:%d",nominal.data.size());
    for(size_t j = 0; j < 6; j ++)
    {
        nominal(j)=0.0;
        //nominal(j) = (ll(j) + ul(j))/2.0;
    }
    KDL::JntArray q(6); // 目标关节位置
    q(0)=0;
    q(1)=pi/3;
    q(2)=pi/3;
    q(3)=0;
    q(4)=0;
    q(5)=0;
    q(6)=0;
    //定义末端4x4齐次变换矩阵
    KDL::Frame end_effector_pose;
    //定义逆运动学解算结果存储数组
    KDL::JntArray result;
    ros::Rate r(1);

    bool flag=true;
    auto print_frame_lambda = [](KDL::Frame f)
    {
        double x, y, z, roll, pitch, yaw;
        x = f.p.x();
        y = f.p.y();
        z = f.p.z();
        f.M.GetRPY(roll, pitch, yaw);
        std::cout << "x:" << x << " y:" << y << " z:" << z << " roll:" << roll << " pitch:" << pitch << " yaw:" << yaw << std::endl;
    };

    //正运动学
    fk_solver.JntToCart(q,end_effector_pose);
    //逆运动学
    int rc = tracik_solver.CartToJnt(nominal, end_effector_pose, result);
    
    ROS_INFO("1:%f,2:%f,3:%f,4:%f,5:%f,6:%f",result(0),result(1),result(2),result(3),result(4),result(5));
    print_frame_lambda(end_effector_pose);
    
    
    while(ros::ok())
    {
    if(flag)
        {
            fk_solver.JntToCart(q, end_effector_pose);
            int rc = tracik_solver.CartToJnt(nominal, end_effector_pose, result);
            
            print_frame_lambda(end_effector_pose);
        }
        else
        {
            fk_solver.JntToCart(nominal, end_effector_pose); 
            int rc = tracik_solver.CartToJnt(q, end_effector_pose, result);
            print_frame_lambda(end_effector_pose);
        }
        flag = !flag;
        // 更新关节状态
        ROS_INFO("更新关节状态");
        joint_state.header.stamp = ros::Time::now();
	//ROS_INFO("%d",joint_state.header.stamp);
        joint_state.name.resize(6);
        joint_state.position.resize(6);

        for(size_t i = 0; i < 6; i ++)
        {
            joint_state.name[i] = joint_name[i];
            //joint_state.position[i] = result(i);
        }
    joint_state.position[0] = result(0);
    joint_state.position[1] = result(1);
    joint_state.position[2] = result(2);
    joint_state.position[3] = result(3);
    joint_state.position[4] = result(4);
    joint_state.position[5] = result(5);
    joint_pub.publish(joint_state);
    
    
    
    
    
    
    
    r.sleep();
    }
    return 0;

}

3.编写launch文件

<launch>

  <arg name="model" default="$(find quadruped_9g)/urdf/mbot_base.urdf"/>
  <arg name="gui" default="true" />
  <arg name="rvizconfig" default="$(find quadruped_9g)/rviz/urdf.rviz" />

  <param name="robot_description" command="$(find xacro)/xacro --inorder $(arg model)" />
  <param name="use_gui" value="$(arg gui)"/>

  <node name="test" pkg="quadruped_9g" type="test" output="screen"/>
  <node name="robot_state_publisher" pkg="robot_state_publisher" type="state_publisher" />

  <node name="rviz" pkg="rviz" type="rviz" args="-d $(arg rvizconfig)" required="true" />

</launch>

4.启动节点运行程序

 可以看到已经成功了!

ROS机械臂运动学(正逆运动学)

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

ROS机械臂正逆运动学 的相关文章

  • 排序算法(2)

    本文介绍插入排序和希尔排序 插入排序是较为常见的排序算法 希尔排序也是基础的排序算法 废话不多说 具体来看一下两种算法 插入排序 插入排序的基本思想是拿到下一个插入元素 在已经有序的待排数组部分找到自己的位置 然后进行数据的移动 完成该元素
  • Python每日一练第4天——合并两个有序数组

    合并两个有序数组 给你两个有序整数数组 nums1 和 nums2 请你将 nums2 合并到 nums1 中 使 nums1 成为一个有序数组 初始化 nums1 和 nums2 的元素数量分别为 m 和 n 你可以假设 nums1 的空
  • 浅谈深度学习的基础——神经网络算法(科普)

    浅谈深度学习的基础 神经网络算法 科普 神经网络算法是一门重要的机器学习技术 它是目前最为火热的研究方向 深度学习的基础 学习神经网络不仅可以让你掌握一门强大的机器学习方法 同时也可以更好地帮助你理解深度学习技术 人工神经网络早期的研究工作
  • 事务方法中保证数据只插入一次方案探究

    需求场景 在项目的接口请求中 我们有一个接口A需要事务支持 在接口A中调用了方法B 方法B也需要事务支持 两者都带有 Transactional注解 在B方法中是这个一个逻辑 查询本地数据库是否包含属性值为一个特定值的字段 如果没有的话就插
  • CodeBlocks中安装使用OpenCV3.4.14

    最近想在Windows下搭建OpenCV环境 看大部分都是采用VC进行搭建 考虑到VC环境太大 N多GB 所以选择小巧开源的CodeBlocks 参考网上的一些资料 在CodeBlocks 20 03中安装好了OpenCV3 4 14版本
  • 程序退出状态码

    状态码简介 上图是一个zsh的截图 当我们执行命令asdsad之后 因为没有这个命令 所以zsh 类似于bash的一种shell 输出没有找到这个命令 但是我们发现图中箭头 由绿色变成红色 表示程序不是正常退出 现在有一个问题是 zsh是怎
  • VS2008, MFC 文件的操作5 - 注册表 操作

    接上一节笔记 VS2008 MFC 文件的操作4 CFile类 CFileDialog类 方式 文本方式打开 1 在工程APP类 先在InitInstance中进行示范 不需要的特定初始化例程 更改用于存储设置的注册表项 TODO 应适当修
  • PostgreSQL 设置允许访问IP

    PostgreSQL安装后默认只能localhost 5432访问 检验方法 curl localhost 5432 访问成功提示 curl 52 Empty reply from server curl 127 0 0 1 5432 访问
  • Flutter

    前言 Image 是 Flutter 用于显示图像的小组件 它可以加载网络 本地 文件或者内存中的图像 支持 JPEG PNG GIF 动画 GIF WebP 动画 WebP BMP 和 WBMP 格式 Flutter Image 本身也实
  • springboot如何集成redis哨兵集群?

    前言 redis主从集群和redis sentinel集群都配置完毕了 现在我们需要了解spring boot 如何连接上该集群 才能用上这两个集群带来的便利 本章内容 为什么需要关注这个问题 怎么配置 记住 本章是针对redis已经配置了
  • Spark的新方案UnifiedMemoryManager内存管理模型分析

    StaticMemoryManager继承与MemoryManager 它是静态的内存分配 是1 6版本以前的实现 就像是建筑商建造好了房子 用户来到直接住进去就好了 弊端 有的人多住了小房子 有的人少住了大房子 而UnifiedMemor
  • neo4j下载安装配置步骤

    目录 一 介绍 简介 Neo4j和JDK版本对应 二 下载 官网下载 直接获取 三 解压缩安装 四 配置环境变量 五 启动测试 一 介绍 简介 Neo4j是一款高性能的图数据库 专门用于存储和处理图形数据 它采用节点 关系和属性的图形结构
  • linux安装服务器步骤,Linux服务器的安装配置流程

    不积跬步无以至千里 贴士 因为是装在Ubuntu系统上 其中有几个常用的命令告诉大家 下面在操作中你也会见到如下等命令 sudo gedit 文件目录对某个文件进行编辑和vi命令差不多 因为好多系统文件是只读的 可通过此方式来进行编辑修改
  • k8s六

    参考资料 从Docker到Kubernetes进阶 阳明 这里写目录标题 一 StatefulSet的设计原理 二 有状态服务的拓扑状态 三 有状态服务的存储状态 四 使用StatefulSet控制器部署ES集群 1 创建无头服务 2 部署
  • 华为云云耀云服务器L实例评测|在Docker环境下部署Mysql数据库

    华为云云耀云服务器L实例评测 在Docker环境下部署Mysql数据库 一 前言 1 1 云耀云服务器L实例简介 1 2 Mysql数据库简介 二 本次实践介绍 2 1 本次实践简介 2 2 本次环境规划 三 购买云耀云服务器L实例 3 1

随机推荐

  • vagrant加virtualbox轻松搭建k8s集群脚本

    文章目录 环境准备 配置k8s节点 环境准备 windows 电脑上使用vagrant 加 virtualbox 搭建k8s 集群 不熟悉vagrant 与 virtualbox 的可以查看这篇文章 使用VirtualBox和Vagrant
  • 由ValueError: not enough values to unpack (expected 2, got 1)报错说开去

    一 背景 今日做了一个文本分类任务 在更换对应的语料库的时候 处理完的语料报了个如题的错误 究其原因 这里用到了一个split t 作为content和label的分割 也就是在语料库中使用 t作为语料库中句子和标签的分隔符 但是在我写下
  • 基于Pytorch框架的ResNet:MNIST数据集手写数字识别

    Debug经验总结 一 常规ResBlock的输出尺寸与输入尺寸相同 否则需要进行尺寸变换 二 在数据集较大时设置num work进行多线程处理 可以很大提高训练效率 三 较复杂的网络在搭建前可以先用草图计算每个输出位置的矩阵尺寸 减少De
  • C++ opencv 识别火焰 (代码)

    brief 火焰识别
  • Java中anyMatch()、allMatch()、noneMatch()用法详解

    说明 anyMatch 匹配到任何一个元素和指定的元素相等 返回 true allMatch 匹配到全部元素和指定的元素相等 返回 true noneMatch 与 allMatch 效果相反 验证 一 anyMatch 1 正常匹配 多元
  • 解决mac下每次git pull/push都需要输入密码的问题

    首先本身项目是走ssh克隆下来的 之前也配置过密钥 按理来说不应该出现这样的问题 在日常开发过程中突然需要我输入密码 小朋友你是否有很多问号 在经过多方面资料查找与解决方案尝试后终于找到了原因 背后的黑手是系统升级了 在升级为macOS c
  • Mysql-提示java.sql.SQLException: Cannot convert value '0000-00-00 00:00:00' from column 7 to TIMESTAMP...

    在Mysql数据库中使用DATETIME类型来存储时间 使用JDBC中读取这个字段的时候 应该使用 ResultSet getTimestamp 这样会得到一个java sql Timestamp类型的数据 在这里既不能使用 ResultS
  • Shader学习笔记:BRDF简单概述

    这篇文章写于一年多以前的一次课程作业 这次作为一个 存货 给放出来 仅仅只是针对代码和一些要点进行简单叙述 如果想听完整的版本 请搜索毛星云大神的博客或者书籍 关于基本的物理渲染公式 网络上的博客和典籍已经多如牛毛了 这里只是自己在之前整理
  • 统计学习之方差分析

    零 案例说明 为了检验某小学六年级教学质量的差异 从该小学六年级的三个班级中分别选取一定数量的学生 分成三个组 三个样本 对他们期末考试的平均分进行统计分析 如果实验显示每个每组的均值相同 即三个班期末考试的成绩差异不大 则表明该小学六年级
  • chatgpt赋能python:Python题目搜索软件:提升你的编程水平

    Python题目搜索软件 提升你的编程水平 对于那些喜欢编程的人来说 学习Python是一个非常不错的选择 但是 学习Python的难度并不小 需要大量的时间和精力 一个好的学习方式是通过完成Python编程题目来加深对该编程语言的理解 但
  • firebug 调试ajax,Jquery使用Firefox FireBug插件调试Ajax步骤讲解

    首先 我们用一个示例来说明JQuery的Ajax调用过程 实现的一个功能是 点击确认支付按钮之后 实现余额支付的功能 1 首先在php页面将相关需要调用的函数绑定到按钮上 function pay btn bind click ABC ba
  • qq引流有哪些模式? QQ引流的几种方法

    现在做QQ营销的方法真的是太多了 花样百出 什么招式都有的 QQ作为我们常用的交流工具 用于营销也是无可厚非的事情 现在做互联网的 永远离不开两个话题 就是 流量 和 变现 缺少其中一个 你所做的所有事情就完全没有任何意义 1 QQ空间引流
  • Mysql 多表关联查询

    文章目录 1 Mysql中表之间的关系 1 1 多表关系 1 2 外键约束 2 多表联合查询 2 1 交叉连接查询 笛卡尔积 2 2 内连接查询 inner join 2 3 外连接查询 2 3 1 左连接 2 3 2 右连接 2 3 4
  • 【接口测试 】Day3-Postman高级用法1(附项目实战)

    目录 课程大纲 昨日回顾 今日目标 Postman高级用法1 一 用例管理 二 Postman断言 三 环境变量与全局变量 四 请求前置脚本 了解 五 Postman关联 重点 课程大纲 接口测试 Day1 接口测试基础 附项目实战 小慌慌
  • 父页面调用easyui datagrid

    opener tt datagrid insertRow index 0 row name name
  • 关于kerberos使用keytab安全认证连接hive票据过期的问题及解决方法。

    关于kerberos使用keytab安全认证连接hive票据过期的问题及解决方法 问题描述 解决方法 问题描述 本人在使用HiveStreaming的过程中 使用kerberos keytab进行安全验证 程序会保持长期连接 hive jd
  • 动手强化学习(六):DQN 算法

    动手强化学习 六 DQN 算法 1 简介 2 CartPole 环境 3 DQN 3 1 经验回放 3 2 目标网络 4 DQN 代码实践 5 以图像为输入的 DQN 算法 6 小结 文章转于 伯禹学习平台 动手学强化学习 强推 本文所有代
  • 5.1-集成学习

    文章目录 集成框架 Framework of Ensemble 一 Ensemble Bagging 1 1 决策树 Decision Tree 1 2 随机森林 Random Forest 二 Ensemble Boosting 2 1
  • 大模型的普及与应用,数据保护非常重要

    随着AI技术的不断发展和应用 大模型已经成为了AI领域中的一个热门话题 随着大模型的应用越来越广泛 保护隐私和数据安全的重要性也越来越突出 隐私和数据安全不仅仅是技术要求 更是对个人权利和社会发展的必然需求 在AI大模型的应用中 数据是非常
  • ROS机械臂正逆运动学

    这里做一个六轴机械臂用于正逆运动学实验 这里其实一共只有3轴 只有3轴位置没有姿态 所以urdf文件里我在末端做了3个虚拟关节 以便将kdl的frame能够填满 使得齐次坐标变换是规则的 1 urdf建模