orocos KDL 由位置计算力矩

本文深入探讨了使用KDL库进行机器人动力学模型的构建与解析,通过URDF文件加载机械臂模型,实现关节状态与扭矩计算的动态模拟,为机器人控制与优化提供理论依据。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

// Software License Agreement (BSD License)
//
// Copyright (c) 2017 Svenzva Robotics
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
//  * Redistributions of source code must retain the above copyright
//    notice, this list of conditions and the following disclaimer.
//  * Redistributions in binary form must reproduce the above
//    copyright notice, this list of conditions and the following
//    disclaimer in the documentation and/or other materials provided
//    with the distribution.
//  * Neither the name of University of Arizona nor the names of its
//   contributors may be used to endorse or promote products derived
//    from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

#include <kdl_parser/kdl_parser.hpp>
#include <ros/ros.h>
#include <ros/package.h>
#include <stdlib.h> 
#include <cmath>

#include <kdl/frames.hpp>
#include <kdl/chainfksolverpos_recursive.hpp>
#include <kdl/chainidsolver_recursive_newton_euler.hpp>
#include <kdl/chainiksolvervel_pinv.hpp>

#include <sensor_msgs/JointState.h>


sensor_msgs::JointState joint_states;
KDL::Tree my_tree;
KDL::Chain chain;
int mNumJnts = 6;
// Get some joint pos, vel, acc values
KDL::JntArray jnt_q(mNumJnts);
KDL::JntArray jnt_qd(mNumJnts);
KDL::JntArray jnt_qdd(mNumJnts);
KDL::JntArray jnt_taugc(mNumJnts);
sensor_msgs::JointState model_states;
bool first_run = true;
KDL::ChainIdSolver_RNE *gcSolver;

double alpha = 0.5;

void js_cb(const sensor_msgs::JointState::ConstPtr& msg){
    for(int i = 0; i < msg->effort.size(); i++){
        joint_states.effort[i] = msg->effort[i] * alpha + (1.0 - alpha) * joint_states.effort[i];
    }
    joint_states.position = msg->position;
    //joint_states = *msg;
}

/*
 * tau given q and the system dynamics
 */
void feel_efforts(ros::Publisher tau_pub){
    KDL::Wrenches jnt_wrenches;
    for (unsigned int i = 0; i < mNumJnts; i++) {
      jnt_q(i) = joint_states.position[i];
      jnt_qd(i) = 0.0;
      jnt_qdd(i) = 0.0;
      KDL::Wrench wr = KDL::Wrench();
      if( !first_run) {
        int gr = 1;
        /*if(i == 0)
            gr = 4;
        else if(i == 3)
            gr = 3;
        else if( i == 4)
            gr = 4;
        else if(i == 1 || i == 2)
            gr = 7;
        */
        double diff = model_states.effort[i] - joint_states.effort[i];
        double frc = 0.0;

        frc = -1 * (diff) * gr;
        
        KDL::Vector force(0, frc, 0);
        wr.torque = force;
        jnt_wrenches.push_back(wr);
      }
      else{
        jnt_wrenches.push_back(KDL::Wrench());
      }
    }

    first_run = false;
    // Compute Dynamics 
    int ret = gcSolver->CartToJnt(jnt_q, jnt_qd, jnt_qdd, jnt_wrenches,jnt_taugc);
    model_states = joint_states;
    if (ret < 0){ 
        ROS_ERROR("KDL: inverse dynamics ERROR");
        ROS_ERROR("%d", ret);
    }
    else{
        int divisor = 1;
        for( int i = 0; i < mNumJnts; i++){
            //Compute the error in the model vs present output torques
            if( i == 1){
                //spring function: y= -0.000012159725010x^3 + 0.001933370127203x^2 + 0.002502918014389x + 0.075320089110718
                double spring_offset = (-0.0001215972501*std::pow(joint_states.position[i], 3)) + (0.0019337012*std::pow(joint_states.position[i], 2)) + (0.0025029181439*joint_states.position[i]) + 0.0753200891107  ;
                jnt_taugc(i) = jnt_taugc(i) - spring_offset; 
            }
            
            if (i == 0)
                divisor = 10000;
            if (i == 1 || i == 2)
                divisor = 7;
            else if (i == 3)
                divisor = 3;
            else if (i == 4)
                divisor = 4;
            model_states.effort[i] = jnt_taugc(i) / divisor;
        }
    }
    tau_pub.publish(model_states);
}

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

    ros::NodeHandle n;
    
    for(int i = 0; i < 7; i++)
        joint_states.effort.push_back(0.0);

    ros::Subscriber js_sub = n.subscribe("joint_states", 1, js_cb);
    ros::Publisher tau_pub = n.advertise<sensor_msgs::JointState>("/revel/model_efforts/", 1);
    ros::Rate update_rate = ros::Rate(10);
    std::string path = ros::package::getPath("svenzva_description");
    std::string full_path = path + "/robots/svenzva_arm.urdf";
    ROS_INFO("Loading model from %s", full_path.c_str());
    
    kdl_parser::treeFromFile(full_path, my_tree);
    
    if (!kdl_parser::treeFromFile(full_path, my_tree)){
       ROS_ERROR("Failed to construct kdl tree");
       return false;
    }
    my_tree.getChain("base_link", "link_6", chain);
    ROS_INFO("Kinematic chain expects %d joints", chain.getNrOfJoints());

    KDL::Vector gravity(0.0, 0.0, -9.81);
    gcSolver = new KDL::ChainIdSolver_RNE(chain, gravity);


    /*
     * Publish the expected torque according to the dynamic model
     */
    ros::spinOnce();
    ros::Duration(5).sleep();
    update_rate.sleep();
    while(ros::ok()){
        ros::spinOnce();
        feel_efforts(tau_pub);
        update_rate.sleep();
    }
    
    return 0;

}
参考:
https://github.com/SvenzvaRobotics/svenzva_ros/

转载于:https://my.oschina.net/itfanr/blog/1982293

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值