旋翼回收火箭系列博客3——控制系统设计(PX4火箭)

立创开源:基于Arduino Nano与JY61P/WTGPS-300的有控探空火箭飞控系统全解析 本文详细解析了基于Arduino Nano、JY61P姿态传感器和WTGPS-300导航模块的探空火箭飞控系统。项目开源了完整的硬件设计、软件代码与组装指南,涵盖传感器数据融合、PID控制算法实现及LoRa无线通信等关键技术,为嵌入式控制与业余火箭爱好者提供了可复现的实战参考。 阅读详情

绪论

为了缩短研制周期和提高产品可靠性,本系统采用商用开源自动驾驶仪PX4,实现旋翼空中展开并回收的功能。PX4是全球最为成熟的开源自动驾驶仪,可实现自动起飞、降落、执行航点等基本任务。然而此次火箭比赛要求能够实现自动展开和降落至指定区域,所以需要对现有飞行硬件进行改造。其困难和解决方案如下:

困难:

  1. 火箭发射过载一般大于5g,商用GPS会自动锁定,导致飞控无法解析出全球定位信息。这种情况下,自动飞行的功能将全部丧失,会导致整个飞行任务的失败;
  2. 火箭要求自动飞行,地面人员不能参与手动控制。然而对于一般的旋翼飞机来讲,为了保证安全,会要求有遥控器连接到飞控,以便随时切换回手动飞行。所以解除掉手动飞行的限制也是关键之一;
  3. 火箭要求达到最高点以后再展开机械臂,这就要求首先飞控输出相关的作动信号,然后飞机再进行螺旋桨的起旋,最后执行降落至指定区域。

解决方案:

  1. 针对GPS上锁问题,我们采用国产高精度、高动态特性的GPS模块,保证火箭起飞过程中的定位连续性和可靠性;
  2. 针对解除手动控制,应当对飞控源码进行更改,并时刻让飞控保持在offboard模式下,接受来自地面站的指令;
  3. 对于上述复杂功能,飞控自身是难以完成的,因此需要借助上位机的协助。为了减小火箭质量、简化系统复杂度,我们采用地面电脑作为上位机,实时向飞控发送指令。协议采用MAVLINK,使用MAVSDK进行开发。
    下面将针对硬件和软件两方面进行详细阐述:

硬件

飞控

采用CUAV公司开发生产的CUAV V5 Nano作为核心控制系统,它是PX4的FMU V5版本,因此具有强大的数据处理能力和多冗余系统,保证了飞行任务的可靠性和稳定性。还有一个原因是它尺寸极小,可以为模型火箭节省空间和质量。其外形如下图所示。

在这里插入图片描述

数传

飞控需要接受地面的实时指令,因此需要高带宽、低时延的通讯方式。我们采用CUAV公司开发生产的P9超远程数传,其最远传输距离达30KM,支持902-928MHZ的跳频传输,输出功率达1W。其外形及接口定义如图所示。
在这里插入图片描述

GPS模块

使用和芯星通公司专门针对弹载领域应用推出的高性能小型化卫星导航定位OEM板卡。支持GPSL1、GLOL1、BD2B1、B2、B3信号,使用RS232串口输出,尺寸仅38mm。热启动时间小于6秒,重启捕获时间小于2秒;轴向速度在2000m/s,加速度20~30g以下能保持良好的定位精度。水平和高程精度均小于10m,测速精度小于0.2m/s。其外形尺寸如图所示:

在这里插入图片描述

软件部分

自动驾驶仪 PX4

采用最新的PX4 V12 beta版本,此版本支持最新的MAVLINK拓展功能和取消起飞怠速功能。在Ubuntu18.0系统上对固件进行编译,然后通过USB烧写至飞控。由于上述GPS板卡输出格式与PX4内部格式不一致,需要进行源码的更改。(PX4无法识别标准NMEA格式GPS,在最新的V13版本上已得到解决)
火箭实物飞行成本高、危险性大,因此必要的仿真验证和室内测试是必要的。采用PX4 sitl+Gazebo的方式进行仿真,以验证程序代码的完整性,仿真过程如下图。其后进行室内测试,保证数据获取完整、相关硬件能够按照规定启动。

在这里插入图片描述
在这里插入图片描述

通讯协议 MAVSDK

采用轻量级通讯协议MAVLINK进行地面电脑与火箭上飞控的串口通讯,使用MAVSDK进行开发。MAVSDK是针对MAVLINK的开发套件,封装了常用的功能,包括数据获取、自动飞行等。所有的代码均已开源,详见个人Github主页
在软件中,其飞行时序如下:

时间/秒动作
00:00检测过载超过3g时,触发计时
05:00打开降落伞,将火箭拉直
06:00折叠机构展开
07:00螺旋桨起旋
07:30开始自动飞向目标点上空
unknow启动自动着陆
unknow降落后飞行器上锁

代码

/*************************Summary***************************
Function: Rocket recycle throught MAVSDK
1. Connect to PX4 through Serial serial:///dev/ttyUSB0:57600;
2. Check the overload of PX4, if it is over 3g, start timing;
3. 00:05:00, fired the parachute;
3. 00:06:00, unfold the arms;
4. 00:07:00, armed the vehicle;
5. 00:07:30, started the return mission;
6. after the mission, disarmed the vehicle;
Author: YDM <1779876755@qq.com>
************************************************************/

/*****************Subscribe Message Frequency*******************
        NAME          Frequency            Rate Function            Callback
LOCAL_POSITION_NED      1HZ     set_rate_position_velocity_ned  subscribe_position_velocity_ned
GLOBAL_POSITION_INT     1HZ     set_rate_position               subscribe_position
HIGHRES_IMU             5HZ     set_rate_imu                    subscribe_imu
***************************************************************/

/*****************Advertise Message Frequency*******************
        NAME          Frequency            Rate Function            Callback
LOCAL_POSITION_NED      1HZ     set_rate_position_velocity_ned  subscribe_position_velocity_ned
***************************************************************/

/*****************Heard file and Namespace*********************/
#include <chrono>
#include <cstdint>
#include <functional>
#include <iostream>
#include <future>
#include <memory>
#include <thread>
#include <mavsdk/mavsdk.h>
#include <mavsdk/plugins/action/action.h>
#include <mavsdk/plugins/mission/mission.h>
#include <mavsdk/plugins/telemetry/telemetry.h>


using namespace mavsdk;
using namespace std::placeholders; // for `_1`
using namespace std::chrono; // for seconds(), milliseconds()
using namespace std::this_thread; // for sleep_for()

#define ERROR_CONSOLE_TEXT "\033[31m" // Turn text on console red
#define TELEMETRY_CONSOLE_TEXT "\033[34m" // Turn text on console blue
#define NORMAL_CONSOLE_TEXT "\033[0m" // Restore normal console colour
/**************************************************************/

/**************************Exit Function*********************/
// Handles Action's result
inline void handle_action_err_exit(Action::Result result, const std::string& message);
// Handles Mission's result
inline void handle_mission_err_exit(Mission::Result result, const std::string& message);
// Handles Connection result
inline void handle_connection_err_exit(ConnectionResult result, const std::string& message);
/**************************************************************/

static Mission::MissionItem make_mission_item(
    double latitude_deg,
    double longitude_deg,
    float relative_altitude_m,
    float speed_m_s,
    bool is_fly_through,
    float gimbal_pitch_deg,
    float gimbal_yaw_deg,
    Mission::MissionItem::CameraAction camera_action);

/*************************How to use it************************/
void usage(std::string bin_name)
{
    std::cout << NORMAL_CONSOLE_TEXT << "Usage : " << bin_name << " <connection_url>" << std::endl
              << "Connection URL format should be :" << std::endl
              << " For TCP : tcp://[server_host][:server_port]" << std::endl
              << " For UDP : udp://[bind_host][:bind_port]" << std::endl
              << " For Serial : serial:///path/to/serial/dev[:baudrate]" << std::endl
              << "For example, to connect to the simulator use URL: udp://:14540" << std::endl;
}

/*************************Main Function**************************/
int main(int argc, char** argv)
{
    // Initialing variable
    Mavsdk mavsdk;
    std::string connection_url;
    ConnectionResult connection_result;
    Telemetry::AccelerationFrd imu_current;
    float acc_x = 0.0;
    float acc_y = 0.0;
    float acc_z = 0.0;

/**************************Connecting the vehicle*********************************/

    if (argc == 2) {
        connection_url = argv[1];
        connection_result = mavsdk.add_any_connection(connection_url);
    } else {
        usage(argv[0]);
        return 1;
    }

    if (connection_result != ConnectionResult::Success) {
        std::cout << ERROR_CONSOLE_TEXT << "Connection failed: " << connection_result
                  << NORMAL_CONSOLE_TEXT << std::endl;
        return 1;
    }

    std::cout << "Waiting to discover system..." << std::endl;
    auto prom = std::promise<std::shared_ptr<System>>{};
    auto fut = prom.get_future();

    mavsdk.subscribe_on_new_system([&mavsdk, &prom]() {
        auto system = mavsdk.systems().back();

        if (system->has_autopilot()) {
            std::cout << "Discovered autopilot" << std::endl;

            // Unsubscribe again as we only want to find one system.
            mavsdk.subscribe_on_new_system(nullptr);
            prom.set_value(system);
        }
    });

    // We usually receive heartbeats at 1Hz, therefore we should find a
    // system after around 3 seconds.
    if (fut.wait_for(seconds(3)) == std::future_status::timeout) {
        std::cout << ERROR_CONSOLE_TEXT << "No autopilot found, exiting." << NORMAL_CONSOLE_TEXT
                  << std::endl;
        return 1;
    }

    auto system = fut.get();

    auto telemetry = Telemetry{system};
    auto action = Action{system};
    auto mission = Mission(system);

/***********************************************************************************/

/**************************Subscribe Message and Callback***************************/

    // We want to listen to the altitude of the drone at 1 Hz in local coordinate system.
    const Telemetry::Result set_local_position_rate_result = telemetry.set_rate_position_velocity_ned(1.0);
    if (set_local_position_rate_result != Telemetry::Result::Success) {
        std::cout << ERROR_CONSOLE_TEXT << "Setting rate failed:" << set_local_position_rate_result
                  << NORMAL_CONSOLE_TEXT << std::endl;
        return 1;
    }

    // Set up callback to monitor altitude while the vehicle is in flight
    telemetry.subscribe_position_velocity_ned([](Telemetry::PositionVelocityNed local_position) {
        std::cout << TELEMETRY_CONSOLE_TEXT // set to blue
                  << "Local Altitude: " << local_position.position.down_m << " m"
                  << NORMAL_CONSOLE_TEXT // set to default color again
                  << std::endl;
    });

    // We want to listen to the altitude of the drone at 1 Hz in global coordinate system.
    const Telemetry::Result set_rate_result = telemetry.set_rate_position(1.0);
    if (set_rate_result != Telemetry::Result::Success) {
        std::cout << ERROR_CONSOLE_TEXT << "Setting rate failed:" << set_rate_result
                  << NORMAL_CONSOLE_TEXT << std::endl;
        return 1;
    }

    // Set up callback to monitor altitude while the vehicle is in flight
    telemetry.subscribe_position([](Telemetry::Position position) {
        std::cout << TELEMETRY_CONSOLE_TEXT // set to blue
                  << "Global Altitude: " << position.relative_altitude_m << " m"
                  << NORMAL_CONSOLE_TEXT // set to default color again
                  << std::endl;
    });

    // We want to listen to the acceleration of the drone at 5 Hz in body coordinate system(frd).
    const Telemetry::Result set_imu_rate_result = telemetry.set_rate_imu(5.0);
    if (set_imu_rate_result != Telemetry::Result::Success) {
        std::cout << ERROR_CONSOLE_TEXT << "Setting rate failed:" << set_imu_rate_result
                  << NORMAL_CONSOLE_TEXT << std::endl;
        return 1;
    }

    // Set up callback to monitor altitude while the vehicle is in flight
    telemetry.subscribe_imu([&acc_x, &acc_y, &acc_z](Telemetry::Imu imu) {
        acc_x = imu.acceleration_frd.forward_m_s2 ;
        acc_y = imu.acceleration_frd.right_m_s2 ;
        acc_z = imu.acceleration_frd.down_m_s2 ;
        // std::cout << TELEMETRY_CONSOLE_TEXT // set to blue
        //           << "ACC_X: " << acc_x << " m/s^2"
        //           << "ACC_Y: " << acc_y << " m/s^2"
        //           << "ACC_Z: " << acc_z << " m/s^2"
        //           << NORMAL_CONSOLE_TEXT // set to default color again
        //           << std::endl;

    });

/***********************************************************************************/

/********************************Flight Timing*************************************/
    // Check if vehicle is ready to arm
    // while (telemetry.health_all_ok() != true) {
    //     std::cout << "Vehicle is getting ready to arm" << std::endl;
    //     sleep_for(seconds(1));
    // }

/*************************Check for the fire signal**********************************/
    while(sqrt(acc_x * acc_x + acc_y * acc_y + acc_z * acc_z) < 15)
    {
        sleep_for(std::chrono::milliseconds(200));
        std::cout << "Waiting for launch..." << std::endl;
    }
/********************************Unfold Arms*************************************/
    std::cout << "Sleeping for 10 seconds..." << std::endl;
    sleep_for(seconds(10));

    std::cout << "Unfolding Arms...\n";
    const Action::Result set_actuator0_result = action.set_actuator(1, 1.0);

    if (set_actuator0_result != Action::Result::Success) {
        std::cerr << "Setting actuator failed:" << set_actuator0_result << '\n';
        return 1;
    }
    std::cout << "Unfolded Arms !!!\n";
/*************************Arm vehicle**********************************/
    std::cout << "Sleeping for 2 seconds..." << std::endl;
    sleep_for(seconds(2));
    std::cout << "Arming..." << std::endl;
    const Action::Result arm_result = action.arm();

    if (arm_result != Action::Result::Success) {
        std::cout << ERROR_CONSOLE_TEXT << "Arming failed:" << arm_result << NORMAL_CONSOLE_TEXT
                  << std::endl;
        return 1;
    }

/********************************Fire Parachute*************************************/
    std::cout << "Sleeping for 1 seconds..." << std::endl;
    sleep_for(seconds(1));

    std::cout << "Firing Parachute...\n";
    const Action::Result set_actuator1_result = action.set_actuator(2, 0.8);

    if (set_actuator1_result != Action::Result::Success) {
        std::cerr << "Setting actuator failed:" << set_actuator1_result << '\n';
        return 1;
    }
    std::cout << "Fired Parachute !!!\n";

/***************************Started Mission***************************************/
{
    std::cout << "Creating and uploading mission" << std::endl;

    std::vector<Mission::MissionItem> mission_items;

    mission_items.push_back(make_mission_item(
        47.398570327054473,
        8.5459490218639658,
        0.0f,
        5.0f,
        false,
        20.0f,
        60.0f,
        Mission::MissionItem::CameraAction::None));

    {
        std::cout << "Uploading mission..." << std::endl;
        // We only have the upload_mission function asynchronous for now, so we wrap it using
        // std::future.
        auto prom = std::make_shared<std::promise<Mission::Result>>();
        auto future_result = prom->get_future();
        Mission::MissionPlan mission_plan{};
        mission_plan.mission_items = mission_items;
        mission.upload_mission_async(
            mission_plan, [prom](Mission::Result result) { prom->set_value(result); });

        const Mission::Result result = future_result.get();
        if (result != Mission::Result::Success) {
            std::cout << "Mission upload failed (" << result << "), exiting." << std::endl;
            return 1;
        }
        std::cout << "Mission uploaded." << std::endl;
    }


    // Before starting the mission, we want to be sure to subscribe to the mission progress.
    mission.subscribe_mission_progress([](Mission::MissionProgress mission_progress) {
        std::cout << "Mission status update: " << mission_progress.current << " / "
                  << mission_progress.total << std::endl;
    });

    {
        std::cout << "Starting mission." << std::endl;
        auto prom = std::make_shared<std::promise<Mission::Result>>();
        auto future_result = prom->get_future();
        mission.start_mission_async([prom](Mission::Result result) {
            prom->set_value(result);
            std::cout << "Started mission." << std::endl;
        });

        const Mission::Result result = future_result.get();
        handle_mission_err_exit(result, "Mission start failed: ");
    }


    while (!mission.is_mission_finished().second) {
        sleep_for(seconds(1));
    }
}
    /**************************************************************/

    std::cout << "Landing..." << std::endl;
    const Action::Result land_result = action.land();
    if (land_result != Action::Result::Success) {
        std::cout << ERROR_CONSOLE_TEXT << "Land failed:" << land_result << NORMAL_CONSOLE_TEXT
                  << std::endl;
        return 1;
    }

    // Check if vehicle is still in air
    while (telemetry.in_air()) {
        std::cout << "Vehicle is landing..." << std::endl;
        sleep_for(seconds(1));
    }
    std::cout << "Landed!" << std::endl;

    // We are relying on auto-disarming but let's keep watching the telemetry for a bit longer.
    sleep_for(seconds(3));
    std::cout << "Finished..." << std::endl;

    return 0;
}

inline void handle_action_err_exit(Action::Result result, const std::string& message)
{
    if (result != Action::Result::Success) {
        std::cerr << ERROR_CONSOLE_TEXT << message << result << NORMAL_CONSOLE_TEXT << std::endl;
        exit(EXIT_FAILURE);
    }
}

inline void handle_mission_err_exit(Mission::Result result, const std::string& message)
{
    if (result != Mission::Result::Success) {
        std::cerr << ERROR_CONSOLE_TEXT << message << result << NORMAL_CONSOLE_TEXT << std::endl;
        exit(EXIT_FAILURE);
    }
}

// Handles connection result
inline void handle_connection_err_exit(ConnectionResult result, const std::string& message)
{
    if (result != ConnectionResult::Success) {
        std::cerr << ERROR_CONSOLE_TEXT << message << result << NORMAL_CONSOLE_TEXT << std::endl;
        exit(EXIT_FAILURE);
    }
}

Mission::MissionItem make_mission_item(
    double latitude_deg,
    double longitude_deg,
    float relative_altitude_m,
    float speed_m_s,
    bool is_fly_through,
    float gimbal_pitch_deg,
    float gimbal_yaw_deg,
    Mission::MissionItem::CameraAction camera_action)
{
    Mission::MissionItem new_item{};
    new_item.latitude_deg = latitude_deg;
    new_item.longitude_deg = longitude_deg;
    new_item.relative_altitude_m = relative_altitude_m;
    new_item.speed_m_s = speed_m_s;
    new_item.is_fly_through = is_fly_through;
    new_item.gimbal_pitch_deg = gimbal_pitch_deg;
    new_item.gimbal_yaw_deg = gimbal_yaw_deg;
    new_item.camera_action = camera_action;
    return new_item;
}
立创开源:基于STM32F103的鸭式布局制导探空火箭飞控系统全解析 本文详细解析了一个基于STM32F103C8T6的鸭式布局制导探空火箭飞控系统开源项目。该系统采用三层PCB堆叠硬件架构,集成ICM42688P六轴传感器与SPL06气压计,通过卡尔曼滤波融合数据实现姿态解算与定高控制,并利用PWM驱动舵机完成飞行姿态纠正与开伞回收。项目涵盖了从硬件设计、传感器驱动到控制算法的完整嵌入式开发流程,为航模与嵌入式爱好者提供了宝贵的学习参考。 阅读详情

相关推荐

BetaFlight开源飞控源码分析

BetaFlight是穿越机领域比较成熟的开源飞控,本篇文章主要分析一下源代码以及如何使用这个开源代码

weixin_43811044的博客 1万+

PX4装机教程(八)常用硬件

PX4 1.13.0 PIXHAWK4超声波传感器为淘宝上类似下图这种 将超声波连接到飞控的IIC口 将参数,然后重启飞控 在Mavlink控制台输入 输出如下打印信息说明连接正常 在地面站上添加以下测距传感器的显示 可以在地面站上看到超声波测得的距离 选用的是北醒的tfmini plus 将tfmini plus接到飞控的串口上,我这里接在uart4上 将SENS_TFMINI_CFG设置为自己连接的串口 将改成传感器的波特率(默认是115200) 修改完参数重启飞控。 然后在QGC上添加测

超维空间科技的博客 1万+

PX4飞控实战:如何将RS232输出的NMEA协议GPS模块接入雷迅Nora+(附完整配置流程)

本文详细介绍了如何将RS232接口输出的NMEA协议GPS模块接入雷迅Nora+飞控的完整实战流程。通过RS232转TTL模块解决电平不匹配问题,并逐步解析硬件连接、独立验证GPS输出、PX4参数配置(如设置SER_GPS2_BAUD和GPS_2_CONFIG)以及故障排查方法,帮助开发者成功集成老款GPS模块,提升无人机系统的兼容性与可靠性。

weixin_28331555的博客 150

transfer.py就是把vins的坐标系转为PX4的坐标系,其实也是个ROS功能包,包含代码分析。(最后发现是改成GAAS里pose的消息形式)

transfer.py 这个脚本干什么工作呢,这个脚本就是之前我跟大家说的(他可能前面讲了看来基础要听听),它把vins它的那个世界坐标系跟px4它定义的北东地,mavros对应的是东北天,它的那个坐标系做了一个转换,然后同时以mavros vins pose 的形式发出去了,这样的话PX4就能接受到你vins发出的数据,就干这样一件事。 ...

自主无人机 PX4 ROS SLAM 路径规划 MVS等技术分享 1935

在PX4中如何使用offboard模式以及对c_uart_interface_example程序的分析

这个程序(mavlink-examles/c_uart_interface_example)演示了如何用c语言调用mavlink API做offboard控制。 这个程序仅针对串口和udp口通讯,目前pixhawk飞控计算机与外部计算机的通讯只支持串口,而udp口是针对PX4放在仿真环境里时的通讯接口,本文只针对uart进行分析。 c_uart_interface_example在打开串口(port.start())后,就启动了2个线程,一个是读线程,一个是写线程,顾名思义,写线..........

weixin_39472686的博客 2488

无人机飞控必知:为什么90%的开源项目都选择NED而非ENU坐标系?

本文深入探讨了无人机飞控系统中NED坐标系为何成为开源项目(如PX4)的首选,分析了其历史沿革、技术优势及生态系统效应。NED坐标系在传感器融合、控制算法稳定性等方面具有显著优势,已成为无人机飞控领域的事实标准。

weixin_29273849的博客 134

阿木实验室PX4开发课程整理

加载带有激光雷达的场景(加载模型)/volans/src/simulation/launch/px4 roslaunch 2Dlidar_px4.launch (其中urdf_px4.launch模型可显示在rviz上,打开rviz—Add—RobotState。可在板载计算机开发上级应用。/volans/src/simulation/launch/Demo/px4_quadrotor 2D定位,地图建立,3D定位,走圆,kcf跟踪,moveit(路径规划) obstacle(避障联调)

qq_52526542的博客 1674

PX4飞控调试进阶:如何利用QGC的MAVLink控制台和日志分析快速定位飞行问题

本文深入探讨了PX4飞控调试的高级技巧,重点介绍了如何利用QGC地面站的MAVLink控制台、实时数据流监控和日志分析工具快速定位飞行问题。通过实战案例演示,帮助开发者掌握从现象到根源的系统化分析方法,提升无人机调试效率与精准度。

weixin_26876073的博客 248

基于Pixhawk和ROS搭建自主无人车(四):MAVROS详解篇

基于Pixhawk和ROS搭建自主无人车(四):MAVROS详解篇

qq_42994487的博客 6575

利用px4flow实现四旋翼室内定点悬停

    最近博主在玩一个无人机比赛,需要完成一些室内飞行的任务。于是,为了增强飞行的可靠性,用到了px4flow光流模块,当然这需要和pixhawk飞控来配套使用。首先简单介绍一下这个模块,它是基于光流不不变性假设,求解xy平面的速度。px4flow还自带超声波模块,用于测量高度。所以,飞控只要使xy平面速度为0,且高度不变,就能实现室内定点悬停。该模块的详细说明可以参考http://www.pi...

zhengyuxin0507的博客 1万+

px4接入模拟NMEA

链接:https://www.jianshu.com/p/6c49f707dce9。SERIAL3_PROTOCOL 5 输入设备类型为GPS。商业转载请联系作者获得授权,非商业转载请注明出处。默认GPS_TYPE=1,GPS模块输出UBLOX协议。修改为GPS_TYPE=5,GPS模块输出NMEA协议。SERIAL3_BAUD 38 通信波特率。ArduPliot固件中GPS默认的串口为3。ArduPliot中切换GPS协议。由uBlox协议更换为NMEA。作者:WilsonGuo。

z1872385的博客 852

2.1 mavros发布位置指令控制px4

记录使用ros控制px4无人机进入offboard模式的飞行,包括仿真和真机实验

weixin_43705900的博客 4224

PX4的电路原理图

这是Pixhawk硬件板的原理图,具体为stm32和飞控相关的外围部件的连接图。

具体实现时的一些注意事项,检查坐标系是否对上,起飞时的机头朝向。

这个坐标系变换很重要,因为咱的这个vins天然地不带磁罗盘,所以它都是以它初试那一刻作为正方向的,就是X的正方向的,那在这种情况下的话你起飞之前一定要把机头永远朝向一个方向,就是你的这个transfer.py的这个脚本,它对应的是某一个方向,比如你每次起飞之前都是机头朝北,那你就每次都从机头朝北起飞,因为咱的这个数据融合做得比较简单,没有把磁罗盘的信息先拉进来,跟vins做完一套融合之后,然后再搞,所以只能你的机头每次起飞都只能朝向一个方向,这样才能保证你的坐标系变换是对的,如果你这次指的是...

自主无人机 PX4 ROS SLAM 路径规划 MVS等技术分享 1145

uniapp自定义tabbar闪屏?3步搞定原生tabbar隐藏+自定义占位(附完整代码)

本文针对UniApp开发中自定义TabBar切换页面闪烁的痛点,提供了一套根治方案。通过隐藏原生TabBar并利用自定义组件进行视觉占位,巧妙结合原生切换的无闪烁优势与自定义设计的灵活性。文章详细解析了闪屏根源,并附上完整的page.json配置与代码实现,帮助开发者彻底解决此问题,提升小程序应用质感。

postgres8guard的博客 1531

UDP_千兆光通信(四)Tri Mode Ethernet MAC ip核

其中 Transmit Engine 从 AXI-Stream TX 接口接收数据,并添加前导码 Preamble、帧起始界定符 SFD、帧校验序列 FSC 等,并在必要时(长度小于最小 MAC 帧长度)填充数据,因此在使用 TEMAC 时,MAC 帧的这几个部分就不需要我们自己添加了(不过其他的 MAC 帧部分,可选的帧过滤器 Frame Filter 用于过滤与一组可配置过滤器匹配的帧,一般用于过滤掉目的 MAC 地址与本设备不一致的帧,TEMAC 默认开启帧过滤器。默认值为使用64位宽的计数器。

lzr232的博客 1777

【PX4-AutoPilot教程-TIPS】PX4中MAVLink话题频率修改

注意,飞控上电后,USB接口只有接入电脑或机载电脑后才启动,飞控先启动再接入USB接口,将导致在执行该脚本文件时指令执行失败,设置发送频率不成功。连接PX4飞控后,打开QGC地面站,进入【Analyze Tools】,选择【MAVLink 检测】界面。修改好预设发送频率后,重新编译飞控固件并烧录至飞控板,重新连接QGC地面站,即可看到修改后的数据发送频率。下的设置,找到对应的话题名称,后面对应的数字为预设发送频率。下的设置,找到对应的话题名称,后面对应的数字为预设发送频率。话题的频率已经修改为100Hz。

在后厂村路努力科研搬砖的无人机控制方向练习生一名~ 3018

3步搞定专利数据爬取:用Selenium绕过国家知识产权局反爬(附完整代码)

本文详细介绍了3种高效获取专利数据的技术方案,重点解析了使用Selenium绕过国家知识产权局反爬的实战方法,并提供了完整代码示例。文章还探讨了Requests+lxml轻量级方案和混合技术策略,帮助开发者根据需求选择最佳数据爬取方案,特别适合需要专利统计数据的开发者参考。

weixin_29029995的博客 1112

基于XTdrone 改变mavros消息发布频率的方法

使用XTdrone时修改mavros消息发布频率的方法

weixin_42659026的博客 1285

Unity游戏开发客户端面经——网络(初级)

Unity游戏开发客户端面经 之 网络 篇

Sea3752的博客 1万+

【Creo】关于Creo一换网络就报错许可证丢失问题解决方案

依照我的个人理解,Creo只要一更换网络,则其许可证里面的网卡参数和现在的网络就对不上了,所以就会出现报错,并且有可能是报错代码(-9),提示许可证激活有问题。

weixin_52002180的博客 6042

PX4代码学习系列博客(6)——offboard模式位置控制代码分析

摘自:https://blog.youkuaiyun.com/iamqianrenzhan/article/details/78066369 PX4代码学习系列博客(6)——offboard模式位置控制代码分析 仟人斩 2017-09-22 19:49:03 2651 收藏 6 分类专栏: px4 版权 分析offboard模式的代码需要用到以下几个模块 local_position_estimator mavlink mc_pos_control mc_att_control mixer ...

自主无人机 PX4 ROS SLAM 路径规划 MVS等技术分享 2288

数据分析必问:Pandas面试题及参考答案

DataFrame是Pandas库中的一个核心数据结构,它类似于Excel中的表格,可以存储不同类型的数据。在Pandas中,抽样操作通常很简单,但是需要根据数据的特点和分析的需求来选择合适的抽样方法。数据标准化和归一化是数据预处理中常用的技术,目的是将数据调整到一个合适的范围内,以消除不同特征量纲和数值范围的差异,从而保证模型训练的有效性。CSV文件是一种文本文件,其中的数据以逗号分隔。不平衡数据集指的是数据集中各类别样本的数量差异较大的情况,这可能导致模型训练出现偏差,影响模型的泛化能力。

大模型大数据攻城狮的专栏 3011

PX4从放弃到精通(一):开源飞控PX4简介+系列文章大纲

文章目录前言一、PX4是什么?二、PX4能做什么?1.支持的载具2.支持的飞控硬件二、PX4架构二、如何开发PX4?二、基于PX4的集群开发二、基于PX4的避障开发总结 前言 设计无人机的飞控是一个非常复杂的工程,因此对于很多做无人机的同学来说,使用开源飞控更加方便高效.本文主要介绍有"开源飞控之王"之称的PX4飞控,主要使想研究这一飞控的同学对此有一个初步的认识. 一、PX4是什么? PX4是由苏黎世联邦理工学院的计算机视觉与几何实验室的一个软硬件项目PIXHAWK演变而来,目的在于为学术、爱好和工业团体

超维空间科技的博客 8万+

华为OD机试双机位C卷-魔法收积木 (C/C++/Py/Java/Js/Go)

华为OD机试(机考)双机位C卷 【魔法收积木】,提供C语言、Java、C++、Python、Go、JavaScript源码实现,并提供完整思路讲解,以及在线OJ模拟做题。华为od - 魔法收积木。

qq_45776114的博客 1941

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

上一篇: 旋翼回收火箭系列博客-火箭总体设计
下一篇: OpenFOAM安装提示FlexLexer.h文件缺失
pix-QGC
博客等级 码龄9年 57粉丝 14原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值