基于单目视觉的四旋翼定点降落——如何通过mavros控制pixhawk(二)(这个我觉得讲得很详细)(2021.3.1现在回看发现也是对PX4官方手册里mavros-offboard代码的讲解)

8月9日,我决定把这篇文章置顶了,我i现在回看这篇文章和最开始看又不一样了。现在是我对MAVROS有了一定了解之后

告诉了我MAVROS  wiki是MAVROS最好的地方。

而且告诉你MAVROS订阅和发布的消息类型都规定好了。

===========================

这个我觉得讲得很详细,如何通过mavros去控制pixhawk  mavros就是mavlink的一个封装    用mavros使无人机进入offboard模式,不是在地面站去设置的,这个我看了这篇文章才明白。

 

其实发现操控Pixahwk似乎并不难,应该又很多开发者已经开发了这方面的功能,这可能是acfly抵不上的,怪不得他们选Pixhawk来做无人机SLAM,有很多现成的东西可以用,比如mavros已经封装好了mavlink。

怪不得,阿木,智能无人机,GAAS,都是用的pixhawk来做SLAM,而不是用一些个人开发的飞控。pixhawk也应该有全球开发者的支持。

我发觉这些是大家的常规操作,可能基本是弄无人机+SLAM的基本方案,哪有双目保密可言呢,大家基本都是这样弄的,都是Pixhawk  都是offboard   都是mavros   都是TX2    是痛无人机+SLAM的基础常规操作,就像你弄无人机驾驶用ROS一样。只可惜你不知道,也没人带你,所以只能买课了。

 

现在再让我用T265去做我觉得可能思路也会清晰许多,至少mavros控制pxihawk这块我觉得是有点把握的。T265本身之前也知道怎么获取位置信息了。

 

这里面说到的Macros和piahawk连接的方法感觉和智能无人机课程里说到的一样。

这是智能无人机课程的。,它的第二个地址是地面站的,是用来让mavros和地面站通信的。

这是这篇文章的

https://blog.csdn.net/zhengyuxin0507/article/details/80357405

 

基于单目视觉的四旋翼定点降落——如何通过mavros控制pixhawk(二)

 

zheng_zju 2018-05-17 22:53:30 9173 收藏 37

最后发布:2018-05-17 22:53:30首发:2018-05-17 22:53:30

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

本文链接:https://blog.csdn.net/zhengyuxin0507/article/details/80357405

版权

    一直拖了这么久没有更新,怪我太懒啦~~~ 今天要特别感谢舒仔仔同学,我的好队友帮我写了这篇博文。这篇文章主要讲了如何通过mavros来控制pixhawk。硬件逻辑是这样子,我们先搞一个odroid(土豪上TX2),再用usb线将odroid与pixhawk连接。所以,odroid发送控制指令来控制pixhawk飞行。pixhawk与外界的通信协议是mavlink。ROS下面有个包叫mavros,说到底就是mavlink的封装,用起来非常简单。话不多说,上正文。

mavros安装:

使用apt-get安装即可:

 
sudo apt-get install ros-kinetic-mavros ros-kinetic-mavros-extras ros‐kinetic‐control‐toolbox

 

我所安装的ros版本是kinetic。

其安装过程非常简单,在网上查询使用方法却说得很笼统,大多是按照官方教程,但实际上并没有详细的讲如何使用。

 

1.  官方例程:

参考:https://dev.px4.io/zh/ros/mavros_offboard.html

在ROS包中创建offb_node.cpp文件(具体怎么建立ROS包,可参考ROS的Wiki教程,写得很详细),并粘贴下面内容:

/**
 * @file offb_node.cpp
 * @brief offboard example node, written with mavros version 0.14.2, px4 flight
 * stack and tested in Gazebo SITL
 */

#include <ros/ros.h>
#include <geometry_msgs/PoseStamped.h>
#include <mavros_msgs/CommandBool.h>
#include <mavros_msgs/SetMode.h>
#include <mavros_msgs/State.h>

mavros_msgs::State current_state;
void state_cb(const mavros_msgs::State::ConstPtr& msg){
    current_state = *msg;
}

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

    ros::Subscriber state_sub = nh.subscribe<mavros_msgs::State>
            ("mavros/state", 10, state_cb);
    ros::Publisher local_pos_pub = nh.advertise<geometry_msgs::PoseStamped>
            ("mavros/setpoint_position/local", 10);
    ros::ServiceClient arming_client = nh.serviceClient<mavros_msgs::CommandBool>
            ("mavros/cmd/arming");
    ros::ServiceClient set_mode_client = nh.serviceClient<mavros_msgs::SetMode>
            ("mavros/set_mode");

    //the setpoint publishing rate MUST be faster than 2Hz
    ros::Rate rate(20.0);

    // wait for FCU connection
    while(ros::ok() && current_state.connected){
        ros::spinOnce();
        rate.sleep();
    }

    geometry_msgs::PoseStamped pose;
    pose.pose.position.x = 0;
    pose.pose.position.y = 0;
    pose.pose.position.z = 2;

    //send a few setpoints before starting
    for(int i = 100; ros::ok() && i > 0; --i){
        local_pos_pub.publish(pose);
        ros::spinOnce();
        rate.sleep();
    }

    mavros_msgs::SetMode offb_set_mode;
    offb_set_mode.request.custom_mode = "OFFBOARD";

    mavros_msgs::CommandBool arm_cmd;
    arm_cmd.request.value = true;

    ros::Time last_request = ros::Time::now();

    while(ros::ok()){
        if( current_state.mode != "OFFBOARD" &&
            (ros::Time::now() - last_request > ros::Duration(5.0))){
            if( set_mode_client.call(offb_set_mode) &&
                offb_set_mode.response.mode_sent){
                ROS_INFO("Offboard enabled");
            }
            last_request = ros::Time::now();
        } else {
            if( !current_state.armed &&
                (ros::Time::now() - last_request > ros::Duration(5.0))){
                if( arming_client.call(arm_cmd) &&
                    arm_cmd.response.success){
                    ROS_INFO("Vehicle armed");
                }
                last_request = ros::Time::now();
            }
        }

        local_pos_pub.publish(pose);

        ros::spinOnce();
        rate.sleep();
    }

    return 0;
}

 

 

该程序的主要功能是:使无人机缓慢飞到2米的高度。

这是一段复制上去就可以直接用的程序,但想要理解深刻,需要对ROS有一定的了解,在了解后,才能看懂下面的内容。下面将对代码的每一部分进行分析,使其能够实现自己想要实现的功能。

 

需要注意的是:对于用于发送接收的mavros的结构体变量的使用,最好还是查看mavros包中的变量定义,这有助于灵活的对代码进行调整。

2.     消息的订阅和发布

首先讲述一下以上程序所实现的功能。首先使飞机进入offboard模式,再进行解锁,最后发布指令使飞机飞到2米的高度。这一系列功能的实现就用到了ROS强大的发布订阅机制。

可以参照这两个网页:

 

http://wiki.ros.org/mavros

 

https://404warehouse.net/2015/12/20/autopilot-offboard-control-using-mavros-package-on-ros/

这两个网站上都详细说明了mavros可发布和订阅的消息以及变量类型,举例说明:

 

2.1 消息订阅(注意:所订阅的消息需要有回调函数去接收它):

 

可以看到截图中清楚地写明了订阅消息所需要地信息,那为什么这里是发布呢?这是因为这是站在mavros的角度看的呀~

//回调函数
mavros_msgs::State current_state;
void state_cb(const mavros_msgs::State::ConstPtr& msg){
    current_state = *msg;
}

//消息订阅
ros::Subscriber state_sub = nh.subscribe <mavros_msgs::State> ("mavros/state", 10, state_cb); 

2.2 消息发布:

ros::Publisher local_pos_pub = nh.advertise<geometry_msgs::PoseStamped>
            ("mavros/setpoint_position/local", 10);
geometry_msgs::PoseStamped pose;
pose.pose.position.x = 0;
pose.pose.position.y = 0;
pose.pose.position.z = 2;

//消息发布
local_pos_pub.publish(pose);

同理,在下面截图中也有非常清楚的说明:

上面的代码意思是将坐标从初始点飞到2米的高度,同时该结构体中还有另外4个给定姿态的量,就是四元数,x,y,z,w。从下面这张图可以看出:

使用方法嘛~~~

pose.pose.quaternion.x = 0;
pose.pose.quaternion.y = 0;
pose.pose.quaternion.z = 0;
pose.pose.quaternion.w = 0;

想好你的姿态,换算成四元数复制进去就好啦~

所以!mavros的维基是入手mavros控制的最好的教程,不然看其它的都没有用,当然首先还是要掌握ROS的发布订阅机制才行。

发布消息的时候有一点需要注意:

 

local_pos_pub.publish(pose);

都看得出来,这一句是发布消息的。那是不是有人问,怎么一段代码里发布了这么多遍?

这在上面的链接里也写得很清楚,我们所使用的pixhawk需要以至少2Hz的频率接收消息,否则将会从offboard模式切回RTL模式。

开始的一段,是为了告诉pixhawk有消息要传过来啦~

中间在切换状态和arm的时候,是为了保持其pixhawk接收寄存器里有值,通俗点嘛,就是既然我要用offboard模式了,你总得先告诉我要怎么搞吧,不然刚切过去那会怎么办呢?随意嘛?哈哈~

那当其正常运行的时候,当然要通过发布消息来尽情的控制你的小飞机啦~

3 怎么和pixhawk连接?

Emm,很简单,直接用USB就可以哈哈~

新打开一个终端,运行:

roslaunch mavros px4.launch fcu_url:=/dev/ttyACM0;

再把上面offboard的节点运行起来就可以啦~

 

当然,要想搞实物,需要先仿真,下面一节我们就来讲讲仿真怎么搞~

 

参考文献:

1.    http://wiki.ros.org/mavros

2.    https://404warehouse.net/2015/12/20/autopilot-offboard-control-using-mavros-package-on-ros/

好的,以下是一个简单的四旋翼无人机定点控制的C++代码示例: ```c++ #include <iostream> #include <cmath> using namespace std; // 定义四旋翼无人机的状态变量 double x, y, z; // 位置坐标 double vx, vy, vz; // 速度 double ax, ay, az; // 加速度 double roll, pitch, yaw; // 姿态角 double p, q, r; // 角速度 // 定义定点控制参数 double kpx, kpy, kpz; // 比例控制参数 double kdx, kdy, kdz; // 微分控制参数 // 定义目标位置 double target_x, target_y, target_z; // 定义控制输入 double u1, u2, u3, u4; // 计算控制输入 void computeControlInput() { double err_x = target_x - x; // 位置误差 double err_y = target_y - y; double err_z = target_z - z; double err_vx = 0 - vx; // 速度误差 double err_vy = 0 - vy; double err_vz = 0 - vz; // 计算控制输入 u1 = kpx * err_x + kdx * err_vx; u2 = kpy * err_y + kdy * err_vy; u3 = kpz * err_z + kdz * err_vz; u4 = 0; // 四旋翼无人机定点控制中,不需要控制偏航角 // 限制控制输入范围 u1 = max(u1, 0.0); u2 = max(u2, 0.0); u3 = max(u3, 0.0); u4 = max(u4, 0.0); u1 = min(u1, 1.0); u2 = min(u2, 1.0); u3 = min(u3, 1.0); u4 = min(u4, 1.0); } // 更新四旋翼无人机状态 void updateQuadrotorState(double dt) { // 根据控制输入计算加速度和角加速度 double g = 9.8; // 重力加速度 ax = (u1 + u2 + u3) * sin(pitch) / cos(roll) - g * sin(pitch); ay = (u1 + u2 + u3) * sin(roll) / cos(pitch) - g * sin(roll); az = u1 + u2 + u3 + u4 - g; // 根据加速度和角速度计算速度和位置 vx += ax * dt; vy += ay * dt; vz += az * dt; x += vx * dt; y += vy * dt; z += vz * dt; // 根据控制输入计算姿态角和角速度 double l = 0.25; // 旋翼到质心的距离 double mx = u1 - u2; // 滚转控制输入 double my = u3 - u4; // 俯仰控制输入 double mz = (u2 + u4 - u1 - u3) / 2; // 偏航控制输入 roll = atan2(my, sqrt(pow(mx, 2) + pow(mz, 2))); pitch = atan2(-mx, sqrt(pow(my, 2) + pow(mz, 2))); r = mz / l; // 根据姿态角和角速度计算角加速度 double Ixx = 0.01; // 滚转惯量 double Iyy = 0.01; // 俯仰惯量 double Izz = 0.02; // 偏航惯量 double p_err = 0 - p; // 角速度误差 double q_err = 0 - q; double r_err = 0 - r; double Mx = Ixx * (kpx * p_err - kdx * p) + (Iyy - Izz) * q * r; double My = Iyy * (kpy * q_err - kdy * q) + (Izz - Ixx) * p * r; double Mz = Izz * (kpz * r_err - kdz * r) + (Ixx - Iyy) * p * q; // 根据角加速度计算角速度 p += Mx / Ixx * dt; q += My / Iyy * dt; r += Mz / Izz * dt; // 将角速度限制在一定范围内 p = max(p, -2.0); q = max(q, -2.0); r = max(r, -2.0); p = min(p, 2.0); q = min(q, 2.0); r = min(r, 2.0); } int main() { // 初始化状态变量和控制参数 x = 0; y = 0; z = 0; vx = 0; vy = 0; vz = 0; ax = 0; ay = 0; az = 0; roll = 0; pitch = 0; yaw = 0; p = 0; q = 0; r = 0; kpx = 0.1; kpy = 0.1; kpz = 0.1; kdx = 0.01; kdy = 0.01; kdz = 0.01; // 设定目标位置 target_x = 1; target_y = 1; target_z = 1; // 模拟飞行过程 double dt = 0.01; for (int i = 0; i < 1000; i++) { computeControlInput(); updateQuadrotorState(dt); cout << "x: " << x << ", y: " << y << ", z: " << z << endl; } return 0; } ``` 该代码实现了一个简单的四旋翼无人机定点控制程序。其中,控制输入为四个旋翼的转速,由比例控制参数和微分控制参数计算得出。同时,根据控制输入和四旋翼的物理模型,计算出加速度、角加速度、姿态角、角速度等状态变量,并将其用于更新无人机状态。在该代码中,我们假设无人机只需要在三个自由度上控制,因此不需要控制偏航角。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值