ardupilot/arduplane/takeoff 起飞模式分析(2)-mode_takeoff.cpp

#include "mode.h"
#include "Plane.h"

/*
  起飞模式参数
 */
const AP_Param::GroupInfo ModeTakeoff::var_info[] = {
    // @参数: ALT
    // @显示名称: Takeoff mode altitude
    // @描述: 起飞模式下的目标高度
    // @范围: 0 200
    // @增量: 1
    // @单位: m
    // @优先级: 标准
    AP_GROUPINFO("ALT", 1, ModeTakeoff, target_alt, 50),

    // @参数: LVL_ALT
    // @显示名称: Takeoff mode altitude level altitude
    // @描述: 起飞模式下 无人机机翼保持水平的高度,也就是说,在该高度下,无人机禁止滚转
    // @范围: 0 50
    // @增量: 1
    // @单位: m
    // @优先级: 标准
    AP_GROUPINFO("LVL_ALT", 2, ModeTakeoff, level_alt, 20),

    // @参数: LVL_PITCH
    // @显示名称: Takeoff mode altitude initial pitch
    // @描述: 初始爬升至TKOFF_LVL_ALT的目标俯仰角度
    // @范围: 0 30
    // @增量: 1
    // @单位: deg
    // @优先级: 标准
    AP_GROUPINFO("LVL_PITCH", 3, ModeTakeoff, level_pitch, 15),

    // @参数: DIST
    // @显示名称: Takeoff mode distance
    // @描述: 这是无人机相对起飞位置开始定点盘旋的距离,方位与位于起飞方向相同(发动机启动时飞机所面对的方向)
    // @范围: 0 500
    // @增量: 1
    // @单位: m
    // @优先级: 标准
    AP_GROUPINFO("DIST", 4, ModeTakeoff, target_dist, 200),
    
    AP_GROUPEND
};

ModeTakeoff::ModeTakeoff() :
    Mode()
{
    AP_Param::setup_object_defaults(this, var_info);
}

bool ModeTakeoff::_enter()
{
    takeoff_started = false;

    return true;
}

void ModeTakeoff::update()
{
    if (!takeoff_started) {
        // 判断是否已经在飞行,如果是则跳过自动起飞阶段
        if (plane.is_flying() && (millis() - plane.started_flying_ms > 10000U) && plane.ahrs.groundspeed() > 3) {
            gcs().send_text(MAV_SEVERITY_INFO, "Takeoff skipped - circling");
            plane.prev_WP_loc = plane.current_loc;
            plane.next_WP_loc = plane.current_loc;
            takeoff_started = true;
            plane.set_flight_stage(AP_Vehicle::FixedWing::FLIGHT_NORMAL);
        }
    }

    if (!takeoff_started) {
        //设置目标位置,距离起飞点1.5倍盘旋半径,高度为TKOFF_ALT
        const float dist = target_dist;
        const float alt = target_alt;
        const float direction = degrees(plane.ahrs.yaw);

        start_loc = plane.current_loc;
        plane.prev_WP_loc = plane.current_loc;
        plane.next_WP_loc = plane.current_loc;
        plane.next_WP_loc.alt += alt*100.0;
        plane.next_WP_loc.offset_bearing(direction, dist);

        plane.crash_state.is_crashed = false;

        plane.auto_state.takeoff_pitch_cd = level_pitch * 100;

        plane.set_flight_stage(AP_Vehicle::FixedWing::FLIGHT_TAKEOFF);

        if (!plane.throttle_suppressed) {
            gcs().send_text(MAV_SEVERITY_INFO, "Takeoff to %.0fm at %.1fm to %.1f deg",
                            alt, dist, direction);
            takeoff_started = true;
        }
    }


    //如果高度到达TKOFF_LVL_ALT或通过目标位置,则认为完成了初始水平起飞。如果无法爬升,目标位置的检查将避免永远飞行的情况
    if (plane.flight_stage == AP_Vehicle::FixedWing::FLIGHT_TAKEOFF &&
        (plane.current_loc.alt - start_loc.alt >= level_alt*100 ||
         start_loc.get_distance(plane.current_loc) >= target_dist)) {
        //达到设定高度,重新计算方位以应对无人机在初始起飞时没有罗盘或初始罗盘较差的情况
        float direction = start_loc.get_bearing_to(plane.current_loc) * 0.01;
        float dist_done = start_loc.get_distance(plane.current_loc);
        const float dist = target_dist;

        plane.next_WP_loc = plane.current_loc;
        plane.next_WP_loc.offset_bearing(direction, MAX(dist-dist_done, 0));
        plane.next_WP_loc.alt = start_loc.alt + target_alt*100.0;

        plane.set_flight_stage(AP_Vehicle::FixedWing::FLIGHT_NORMAL);
        
#if AP_FENCE_ENABLED
        plane.fence.auto_enable_fence_after_takeoff();
#endif
    }

    if (plane.flight_stage == AP_Vehicle::FixedWing::FLIGHT_TAKEOFF) {
        SRV_Channels::set_output_scaled(SRV_Channel::k_throttle, 100.0);
        plane.takeoff_calc_roll();
        plane.takeoff_calc_pitch();
    } else {
        plane.calc_nav_roll();
        plane.calc_nav_pitch();
        plane.calc_throttle();
    }
}

void ModeTakeoff::navigate()
{

    //0表示使用WP_LOITER_RAD
    plane.update_loiter(0);
}

要使用C++代码使mavros起飞并悬停,你需要使用mavros库和ROS(Robot Operating System)。 以下是一个简单的代码示例,可以让mavros起飞并悬停: ```cpp #include <ros/ros.h> #include <mavros_msgs/CommandBool.h> #include <mavros_msgs/CommandTOL.h> #include <mavros_msgs/SetMode.h> #include <geometry_msgs/TwistStamped.h> int main(int argc, char **argv) { ros::init(argc, argv, "mavros_takeoff_and_hover"); ros::NodeHandle nh; // 发布器和服务客户端 ros::Publisher velocity_pub = nh.advertise<geometry_msgs::TwistStamped>("/mavros/setpoint_velocity/cmd_vel", 10); ros::ServiceClient arming_client = nh.serviceClient<mavros_msgs::CommandBool>("/mavros/cmd/arming"); ros::ServiceClient takeoff_client = nh.serviceClient<mavros_msgs::CommandTOL>("/mavros/cmd/takeoff"); ros::ServiceClient set_mode_client = nh.serviceClient<mavros_msgs::SetMode>("/mavros/set_mode"); // 等待连接到mavros ros::Rate rate(20.0); // 设置循环频率为20hz while (ros::ok() && !ros::service::waitForService("/mavros/set_mode", 1000)) { ROS_INFO("等待连接到mavros..."); } // 设置起飞高度 double takeoff_height = 3.0; // 设置飞行模式 mavros_msgs::SetMode offb_set_mode; offb_set_mode.request.custom_mode = "OFFBOARD"; // 设置起飞命令 mavros_msgs::CommandTOL takeoff_cmd; takeoff_cmd.request.altitude = takeoff_height; // 设置武器状态 mavros_msgs::CommandBool arm_cmd; arm_cmd.request.value = true; // 等待mavros就绪 while (ros::ok() && !arming_client.call(arm_cmd) && arm_cmd.response.success) { ROS_WARN("武器状态设置失败,重试中..."); ros::Duration(1.0).sleep(); } // 等待mavros就绪 while (ros::ok() && !takeoff_client.call(takeoff_cmd) && takeoff_cmd.response.success) { ROS_WARN("起飞命令发送失败,重试中..."); ros::Duration(1.0).sleep(); } // 等待mavros就绪 while (ros::ok() && !set_mode_client.call(offb_set_mode) && offb_set_mode.response.mode_sent) { ROS_WARN("模式设置失败,重试中..."); ros::Duration(1.0).sleep(); } // 悬停 geometry_msgs::TwistStamped velocity_cmd; velocity_cmd.twist.linear.x = 0.0; velocity_cmd.twist.linear.y = 0.0; velocity_cmd.twist.linear.z = 0.0; velocity_cmd.twist.angular.x = 0.0; velocity_cmd.twist.angular.y = 0.0; velocity_cmd.twist.angular.z = 0.0; while (ros::ok()) { velocity_pub.publish(velocity_cmd); ros::spinOnce(); rate.sleep(); } return 0; } ``` 这个代码使用了mavros库,通过发布速度话题来控制飞行器的运动。在起飞后,它发送了一个速度命令,使飞行器悬停在空中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

陕西华兴通盛航空科技有限公司

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值