宇数机器狗开源代码详解:代码框架梳理1

#这一篇文章会讲讲[unitree_ros](https://github.com/unitreerobotics/unitree_ros)的代码框架,仅代表个人看法,写出来加深自己的印象,欢迎交流。

#附上宇树家的学习资料[《四足机器人控制算法--建模、控制与实践》](https://detail.tmall.com/item.htm?spm=a212k0.12153887.0.0.5487687dBgiovR&id=704510718152)#

下载了GitHub上的压缩包之后,有五个文件(第五个unitree_ros_to_real是空的),

robots装的是宇树家不同机器狗的描述文件

unittree_controller是一个控制器功能包

unitree_legged_control是底层电机控制功能包

1、unittree_controller功能包(文件夹)

这个文件夹下面含有三个文件夹,需要对ros的框架有一定了解,include是头文件,launch文件夹装着一次性打开多个节点的launch文件,src则装着实现功能的c++文件。(如果没学过ros,可以去b站看赵虚左老师的ros教程,非常详细)。除此之外CMakelist.txt文件和package.xml文件是配置文件,当你创建了新的文件需要编译时,就需要在配置文件中加入新创建的文件才能编译成功。

1.先看include文件夹里的头文件body.h
/************************************************************************
Copyright (c) 2018-2019, Unitree Robotics.Co.Ltd. All rights reserved.
Use of this source code is governed by the MPL-2.0 license, see LICENSE.
************************************************************************/

#ifndef __BODY_H__ //预处理指令,用于防止头文件被多次包含。
#define __BODY_H__

#include "ros/ros.h"//ros自带的头文件类型,提供ros节点的基本功能
#include "unitree_legged_msgs/LowCmd.h"//这个Github里没有,这是宇树家自带的消息类文件msg,需要下载另外一个包
#include "unitree_legged_msgs/LowState.h"//消息里面的低级状态,指电机状态之类的消息
#include "unitree_legged_msgs/HighState.h"//消息里面的高级状态,指机器狗线速度角速度之类,具体格式得去查这个msg文件
#define PosStopF (2.146E+9f) //定义两个宏,分别表示位置停止阈值和速度停止阈值。用于停止机器人的运动或判断机器人是否处于静止状态
#define VelStopF (16000.f)

namespace unitree_model {//声明一个名为 unitree_model 的命名空间,用于封装和组织相关的函数和变量
//extern 是 C++ 和 C 语言中的一个关键字,用于在程序中声明外部链接的变量或函数。外部链接意味着这些变量或函数的定义在程序的其他地方
extern ros::Publisher servo_pub[12];//声明一个 ROS 发布者数组 servo_pub,用来向12个电机发布命令
extern ros::Publisher highState_pub;//声明另外一个发布者,这个用来发布高级状态
extern unitree_legged_msgs::LowCmd lowCmd;//声明一个变量,存储低级命令,电机的命令,之后会把这个值赋给servo_pub
extern unitree_legged_msgs::LowState lowState;//声明一个变量,存储低级状态

void stand();      //定义站立函数
void motion_init();//定义运动初始化函数
void sendServoCmd();//定义发送伺服电机命令函数
void moveAllPosition(double* jointPositions, double duration);
}//接受一个包含关节位置的数组和持续时间,用于移动所有关节到指定位置。
//比如确定了要移动机器人,但是不能突变,所以用这个函数平滑移动
#endif
2.再来看src文件夹下的c++文件,第一个是body.cpp
//发布节点的文件,用于发布机器人模型的状态:move_publisher,以在Gazebo仿真环境中控制机器人模型的位置和姿态。
//它使用gazebo_msgs::ModelState消息类型来设置机器人模型的位置、方向和参考坐标系。
//根据选择的坐标系,代码实现了一个循环,使机器人模型在世界坐标系中以圆形路径移动,或者在机器人坐标系中以恒定速度移动。

#include <ros/ros.h>
#include <gazebo_msgs/ModelState.h>
#include <gazebo_msgs/SetModelState.h>
#include <string>
#include <stdio.h>  
#include <tf/transform_datatypes.h>
// #include <std_msgs/Float64.h>
#include <math.h>
#include <iostream>

int main(int argc, char **argv)
{   

    enum coord //定义一个枚举类型,coord不是WORLD就是ROBOT
    {
        WORLD,
        ROBOT
    };
    coord def_frame = coord::WORLD;//把坐标系frame设为WORLD

    ros::init(argc, argv, "move_publisher");//这里看不懂就去学ros
    ros::NodeHandle nh;
    ros::Publisher move_publisher = nh.advertise<gazebo_msgs::ModelState>("/gazebo/set_model_state", 1000);

    gazebo_msgs::ModelState model_state_pub;//定义了一个gazebo_msgs::ModelState消息的变量model_state_pub

    std::string robot_name;//定义了一个字符串变量robot_name
    ros::param::get("/robot_name", robot_name);//从参数服务器中找到参数/robot_name,赋给robot_name 
    std::cout << "robot_name: " << robot_name << std::endl;//这行代码的作用是将文本 "robot_name: " 后跟变量robot_name的值,然后是一个换行符输出到控制台。

    model_state_pub.model_name = robot_name + "_gazebo";
    ros::Rate loop_rate(1000);//定义发布消息的频率1000Hz
//如果坐标系是世界,直接修改模型状态中的位置为圆周运动,感觉是用来做测试的
    if(def_frame == coord::WORLD)
    {
        model_state_pub.pose.position.x = 0.0;//设置模型在x轴上的位置为0.0单位(通常在仿真中是米)。
        model_state_pub.pose.position.y = 0.0;
        model_state_pub.pose.position.z = 0.5;
        
        model_state_pub.pose.orientation.x = 0.0;//设置模型的方向四元数的x分量为0.0。四元数用于表示方向,是一种替代欧拉角的方式,可以避免万向节锁。
        model_state_pub.pose.orientation.y = 0.0;
        model_state_pub.pose.orientation.z = 0.0;
        model_state_pub.pose.orientation.w = 1.0;//设置模型的方向四元数的实部(或称为标量)为1.0。这代表模型的初始方向是沿着正z轴,没有旋转。

        model_state_pub.reference_frame = "world";//设置模型状态的参考坐标系为"world"。这意味着模型的位置和方向是相对于世界坐标系定义的。

        long long time_ms = 0;  //time, ms
        const double period = 5000; //ms
        const double radius = 1.5;    //m
        tf::Quaternion q; //声明一个四元数对象,用于后续创建ROS消息中的四元数
        while(ros::ok())
        {
            model_state_pub.pose.position.x = radius * sin(2*M_PI*(double)time_ms/period);//使用圆的参数方程规定其位置
            model_state_pub.pose.position.y = radius * cos(2*M_PI*(double)time_ms/period);
            model_state_pub.pose.orientation = tf::createQuaternionMsgFromRollPitchYaw(0, 0, - 2*M_PI*(double)time_ms/period);

            move_publisher.publish(model_state_pub);
            loop_rate.sleep();
            time_ms += 1;
        }
    }
    else if(def_frame == coord::ROBOT) //如果坐标系是ROBOT,就将模型状态的x方向的线速度设为0.02m/s
    {
        model_state_pub.twist.linear.x= 0.02; //0.02: 2cm/sec
        model_state_pub.twist.linear.y= 0.0;
        model_state_pub.twist.linear.z= 0.08;
        
        model_state_pub.twist.angular.x= 0.0;
        model_state_pub.twist.angular.y= 0.0;
        model_state_pub.twist.angular.z= 0.0;

        model_state_pub.reference_frame = "base";

        while(ros::ok())
        {
            move_publisher.publish(model_state_pub);
            loop_rate.sleep();
        }
    }
    
}
3.然后是src文件夹下的move_publisher.cpp文件
//发布节点的文件,用于发布机器人模型的状态,以在Gazebo仿真环境中控制机器人模型的位置和姿态。
//它使用gazebo_msgs::ModelState消息类型来设置机器人模型的位置、方向和参考坐标系。
//代码中定义了一个枚举类型coord来选择默认坐标系(世界坐标系或机器人坐标系)。
//根据选择的坐标系,代码实现了一个循环,使机器人模型在世界坐标系中以圆形路径移动,或者在机器人坐标系中以恒定速度移动。

#include <ros/ros.h>
#include <gazebo_msgs/ModelState.h>
#include <gazebo_msgs/SetModelState.h>
#include <string>
#include <stdio.h>  
#include <tf/transform_datatypes.h>
// #include <std_msgs/Float64.h>
#include <math.h>
#include <iostream>

int main(int argc, char **argv)
{   

    enum coord
    {
        WORLD,
        ROBOT
    };
    coord def_frame = coord::WORLD;

    ros::init(argc, argv, "move_publisher");
    ros::NodeHandle nh;
    ros::Publisher move_publisher = nh.advertise<gazebo_msgs::ModelState>("/gazebo/set_model_state", 1000);

    gazebo_msgs::ModelState model_state_pub;

    std::string robot_name;
    ros::param::get("/robot_name", robot_name);
    std::cout << "robot_name: " << robot_name << std::endl;//这行代码的作用是将文本 "robot_name: " 后跟变量robot_name的值,然后是一个换行符输出到控制台。

    model_state_pub.model_name = robot_name + "_gazebo";
    ros::Rate loop_rate(1000);

    if(def_frame == coord::WORLD)
    {
        model_state_pub.pose.position.x = 0.0;//设置模型在x轴上的位置为0.0单位(通常在仿真中是米)。
        model_state_pub.pose.position.y = 0.0;
        model_state_pub.pose.position.z = 0.5;
        
        model_state_pub.pose.orientation.x = 0.0;//设置模型的方向四元数的x分量为0.0。四元数用于表示方向,是一种替代欧拉角的方式,可以避免万向节锁。
        model_state_pub.pose.orientation.y = 0.0;
        model_state_pub.pose.orientation.z = 0.0;
        model_state_pub.pose.orientation.w = 1.0;//设置模型的方向四元数的实部(或称为标量)为1.0。这代表模型的初始方向是沿着正z轴,没有旋转。

        model_state_pub.reference_frame = "world";//设置模型状态的参考坐标系为"world"。这意味着模型的位置和方向是相对于世界坐标系定义的。

        long long time_ms = 0;  //time, ms
        const double period = 5000; //ms
        const double radius = 1.5;    //m
        tf::Quaternion q; //声明一个四元数对象,用于后续创建ROS消息中的四元数
        while(ros::ok())
        {
            model_state_pub.pose.position.x = radius * sin(2*M_PI*(double)time_ms/period);//使用圆的参数方程规定其位置
            model_state_pub.pose.position.y = radius * cos(2*M_PI*(double)time_ms/period);
            model_state_pub.pose.orientation = tf::createQuaternionMsgFromRollPitchYaw(0, 0, - 2*M_PI*(double)time_ms/period);

            move_publisher.publish(model_state_pub);
            loop_rate.sleep();
            time_ms += 1;
        }
    }
    else if(def_frame == coord::ROBOT)
    {
        model_state_pub.twist.linear.x= 0.02; //0.02: 2cm/sec
        model_state_pub.twist.linear.y= 0.0;
        model_state_pub.twist.linear.z= 0.08;
        
        model_state_pub.twist.angular.x= 0.0;
        model_state_pub.twist.angular.y= 0.0;
        model_state_pub.twist.angular.z= 0.0;

        model_state_pub.reference_frame = "base";

        while(ros::ok())
        {
            move_publisher.publish(model_state_pub);
            loop_rate.sleep();
        }
    }
    
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值