ardupilot 关于设备车Rover的学习《2》------如何解锁

目录

摘要


本节主要记录ardupilot中ROVER小车是如何进行通过遥控器进行解锁的,欢迎批评指正!


1.序言


ardupilot 中ROVER小车通过遥控器解锁有两种方式:

  1. 通过遥控器的方向舵实现解锁
  2. 通过遥控器上外部开关实现解锁

在进行代码讲解之前需要注意的是小车的遥控器控制通道的映射需要注意:

void Rover::set_control_channels(void)
{
    //检查RCMAP上的更改
    channel_steer    = rc().channel(rcmap.roll()-1);      //横滚通道映射到方向舵
    channel_throttle = rc().channel(rcmap.throttle()-1);  //油门通道映射到油门通道
    channel_lateral  = rc().channel(rcmap.yaw()-1);       //偏航通道映射转向通道

    //设置遥控器的范围
    channel_steer->set_angle(SERVO_MAX); //最大是4500
    channel_throttle->set_angle(100);    //设置0-100
    //横向是空的吗,不是就设置,是的话关闭
    if (channel_lateral != nullptr)
    {
        channel_lateral->set_angle(100); //设置100
    }

    //步行机器人rc输入初始化------ walking robots rc input init
    channel_roll = rc().find_channel_for_option(RC_Channel::AUX_FUNC::ROLL);   //横滚201
    channel_pitch = rc().find_channel_for_option(RC_Channel::AUX_FUNC::PITCH); //俯仰202
    channel_walking_height = rc().find_channel_for_option(RC_Channel::AUX_FUNC::WALKING_HEIGHT);//211
    //设定死区
    if (channel_roll != nullptr) 
    {
        channel_roll->set_angle(SERVO_MAX);
        channel_roll->set_default_dead_zone(30);
    }
    //设定死区
    if (channel_pitch != nullptr) 
    {
        channel_pitch->set_angle(SERVO_MAX);
        channel_pitch->set_default_dead_zone(30);
    }
    //设定死区
    if (channel_walking_height != nullptr) {
        channel_walking_height->set_angle(SERVO_MAX);
        channel_walking_height->set_default_dead_zone(30);
    }    

    //帆船rc输入初始化----- sailboat rc input init
    g2.sailboat.init_rc_in();

    //允许在未启用时重新配置输出------ Allow to reconfigure output when not armed
    if (!arming.is_armed()) 
    {
        g2.motors.setup_servo_output();
        //对于一个漫游者来说,安全是微调油门----- For a rover safety is TRIM throttle
        g2.motors.setup_safety_output();
    }
    // setup correct scaling for ESCs like the UAVCAN ESCs which
    // take a proportion of speed. Default to 1000 to 2000 for systems without
    // a k_throttle output
    //为诸如UAVCAN ESC之类的ESC设置正确的缩放
    //占速度的一部分。对于不带的系统,默认值为1000到2000
    //k_throttle 输出
    hal.rcout->set_esc_scaling(1000, 2000);
    g2.servo_channels.set_esc_scaling_for(SRV_Channel::k_throttle);
}

从这里可以看出,如果我们遥控器是美国手,那么我们之前的横滚通道就是控制小车的方向舵,实现小车左右旋转;我们的油门通道还是控制小车的前进后退。

2.解锁代码实现


1.通过遥控器的方向舵实现解锁

SCHED_TASK(read_radio,             50,    200,   3),//读取遥控器数据
void Rover::read_radio()
{

	//判断有没有遥控器输入数据
    if (!rc().read_input())
    {
        //检测假如我们丢失遥控器信号---- check if we lost RC link
        radio_failsafe_check(channel_throttle->get_radio_in());
        return;
    }

    failsafe.last_valid_rc_ms = AP_HAL::millis();
    //检测RC值是否有根据----- check that RC value are valid
    radio_failsafe_check(channel_throttle->get_radio_in());

    //检测我们尝试做遥控器解锁或者上锁----- check if we try to do RC arm/disarm
    if(g.rc_arm_enable==1)
    {
    	//方向舵解锁上锁操作
    	rudder_arm_disarm_check();	 //只有这个功能打开才能开启
    }

}

由于小车有时候想不通过方向舵来解锁,以及限制解锁延迟时间,这里新增加一个参数g.rc_arm_enable来实现是否开启这个功能。当然默认代码也可以关闭这个功能,可以通过参数RUDDER来实现。


在这里插入图片描述
到这里我们重点只需要关注函数:rudder_arm_disarm_check(); 即可。

void Rover::rudder_arm_disarm_check()
{
    // check if arming/disarm using rudder is allowed
	//检查是否允许使用方向舵进行防护/解除防护
    const AP_Arming::RudderArming arming_rudder = arming.get_rudder_arming_type();
    //如果设置没有使能,直接返回
    if (arming_rudder == AP_Arming::RudderArming::IS_DISABLED)
    {
        return;
    }

    // In Rover we need to check that its set to the throttle trim and within the DZ
    // if throttle is not within trim dz,then pilot cannot rudder arm/disarm
    //在ROVER我们需要检查油门是在中立或者死区范围内
    //如果油门不在死区范围内,则飞行员不能操纵舵/解除舵
    if (!channel_throttle->in_trim_dz())
    {
        rudder_arm_timer = 0;
        return;
    }

    //检查此模式是否允许启用/禁用------ check if arming/disarming allowed from this mode
    if (!control_mode->allows_arming_from_transmitter())
    {
        rudder_arm_timer = 0;
        return;
    }
    //判断是解锁
    if (!arming.is_armed())
    {
        // when not armed, full right rudder starts arming counter
    	//未启用时,右满舵开始启用计数器
        if (channel_steer->get_control_in() > 4000) //方向杆往右边解锁
        {
        	//获取现在时间
            const uint32_t now = millis();
            //数据判断,方向舵/转向装置已运行的时间
            if ((rudder_arm_timer == 0 )||(now - rudder_arm_timer < g.rc_arm_time_ms))
            {
            	//方向舵/转向装置已运行的时间
                if (rudder_arm_timer == 0)
                {
                	//记录限制时间
                    rudder_arm_timer = now;
                }
            } else
            {
                //时间到了开始解锁------ time to arm!
                arming.arm(AP_Arming::Method::RUDDER);
                //记得把数据清零
                rudder_arm_timer = 0;
            }
        } else
        {
            //没有在全右操作------ not at full right rudder
            rudder_arm_timer = 0;
        }
    } else if ((arming_rudder == AP_Arming::RudderArming::ARMDISARM) && !g2.motors.active())
    {
        // when armed and motor not active (not moving), full left rudder starts disarming counter
    	//当解锁和电机没有激活(不运动),全左方向舵开始解除待命计数器
        if (channel_steer->get_control_in() < -4000) //方向杆往左边上锁
        {
        	//获取现在时间
            const uint32_t now = millis();
            //数据判断
            if ((rudder_arm_timer == 0) ||(now - rudder_arm_timer < g.rc_arm_time_ms))
            {
            	//记录下开始记录的时间
                if (rudder_arm_timer == 0)
                {
                	//传递时间,为数据判断做铺垫
                    rudder_arm_timer = now;
                }
            } else
            {
                //时间到了开始上锁----- time to disarm!
                arming.disarm(AP_Arming::Method::RUDDER);
                //数据清零
                rudder_arm_timer = 0;
            }
        } else
        {
            //没有在最左边---- not at full left rudder
            rudder_arm_timer = 0;
        }
    }
}

这段代码相对好懂,重点我增加了一个参数来实现对解锁延迟大小的设定,通过g.rc_arm_time_ms设定这个值就可以来实现解锁延迟了。

2.通过遥控器上外部开关实现解锁

要想实现通过外部开关进行解锁,首先先要把解锁的按键找到,比如我们用遥控器的7通道解锁,那就需要把7通道映射成解锁功能。

在这里插入图片描述
在这里插入图片描述
做好映射之后,我们只需要看代码实现即可:

    //初始化遥控器通道数据------ initialise rc channels
    rc().convert_options(RC_Channel::AUX_FUNC::ARMDISARM_UNUSED, RC_Channel::AUX_FUNC::ARMDISARM);     //转换信息
    rc().convert_options(RC_Channel::AUX_FUNC::SAVE_TRIM, RC_Channel::AUX_FUNC::TRIM_TO_CURRENT_SERVO_RC);
    //初始化
    rc().init();
void RC_Channels::init(void)
{
    //对每个通道进行初始化 setup ch_in on channels
    for (uint8_t i=0; i<NUM_RC_CHANNELS; i++) 
    {
        channel(i)->ch_in = i;
    }
    //初始化外部开关
    init_aux_all();
}

外部通道初始化

void RC_Channels::init_aux_all()
{
    for (uint8_t i=0; i<NUM_RC_CHANNELS; i++) 
    {
        RC_Channel *c = channel(i);
        if (c == nullptr) 
        {
            continue;
        }
        //初始化
        c->init_aux();
    }
    //复位模式
    reset_mode_switch();
}
void RC_Channel::init_aux()
{
	//外部开关的位置信息
    AuxSwitchPos position;
    //读取三段开关信息
    if (!read_3pos_switch(position)) 
    {
    	//没有读取到,应该设置低电平
        position = AuxSwitchPos::LOW;
    }
    //初始化外部开关
    init_aux_function((aux_func_t)option.get(), position);
}
void RC_Channel::init_aux_function(const aux_func_t ch_option, const AuxSwitchPos ch_flag)
{
    //初始化通道对应的功能-----init channel options
    switch(ch_option) {
    //以下功能不需要初始化:----- the following functions do not need to be initialised:
    case AUX_FUNC::ARMDISARM: //这里就是我们的上锁,解锁映射了
    case AUX_FUNC::CAMERA_TRIGGER:
    case AUX_FUNC::CLEAR_WP:
    case AUX_FUNC::COMPASS_LEARN:
    case AUX_FUNC::DISARM:
    case AUX_FUNC::DO_NOTHING:
    case AUX_FUNC::LANDING_GEAR:
    case AUX_FUNC::LOST_VEHICLE_SOUND:
    case AUX_FUNC::RELAY:
    case AUX_FUNC::RELAY2:
    case AUX_FUNC::RELAY3:
    case AUX_FUNC::RELAY4:
    case AUX_FUNC::RELAY5:
    case AUX_FUNC::RELAY6:
    case AUX_FUNC::VISODOM_ALIGN:
    case AUX_FUNC::EKF_LANE_SWITCH:
    case AUX_FUNC::EKF_YAW_RESET:
    case AUX_FUNC::GENERATOR: // don't turn generator on or off initially
    case AUX_FUNC::EKF_POS_SOURCE:
    case AUX_FUNC::TORQEEDO_CLEAR_ERR:
    case AUX_FUNC::SCRIPTING_1:
    case AUX_FUNC::SCRIPTING_2:
    case AUX_FUNC::SCRIPTING_3:
    case AUX_FUNC::SCRIPTING_4:
    case AUX_FUNC::SCRIPTING_5:
    case AUX_FUNC::SCRIPTING_6:
    case AUX_FUNC::SCRIPTING_7:
    case AUX_FUNC::SCRIPTING_8:
    case AUX_FUNC::VTX_POWER:
    case AUX_FUNC::OPTFLOW_CAL:
    case AUX_FUNC::TURBINE_START:
        break;
    case AUX_FUNC::AVOID_ADSB:
    case AUX_FUNC::AVOID_PROXIMITY:
    case AUX_FUNC::FENCE:
    case AUX_FUNC::GPS_DISABLE:
    case AUX_FUNC::GPS_DISABLE_YAW:
    case AUX_FUNC::GRIPPER:
    case AUX_FUNC::KILL_IMU1:
    case AUX_FUNC::KILL_IMU2:
    case AUX_FUNC::MISSION_RESET:
    case AUX_FUNC::MOTOR_ESTOP:
    case AUX_FUNC::RC_OVERRIDE_ENABLE:
    case AUX_FUNC::RUNCAM_CONTROL:
    case AUX_FUNC::RUNCAM_OSD_CONTROL:
    case AUX_FUNC::SPRAYER:
    case AUX_FUNC::DISABLE_AIRSPEED_USE:
#if HAL_MOUNT_ENABLED
    case AUX_FUNC::RETRACT_MOUNT:
#endif
        run_aux_function(ch_option, ch_flag, AuxFuncTriggerSource::INIT);
        break;
    default:
        gcs().send_text(MAV_SEVERITY_WARNING, "Failed to init: RC%u_OPTION: %u\n",
                           (unsigned)(this->ch_in+1), (unsigned)ch_option);
#if CONFIG_HAL_BOARD == HAL_BOARD_SITL
        AP_BoardConfig::config_error("Failed to init: RC%u_OPTION: %u",
                           (unsigned)(this->ch_in+1), (unsigned)ch_option);
#endif
        break;
    }
}

然后会调用

bool RC_Channel::run_aux_function(aux_func_t ch_option, AuxSwitchPos pos, AuxFuncTriggerSource source)
{
	//执行这里
    const bool ret = do_aux_function(ch_option, pos);

    // @LoggerMessage: AUXF
    // @Description: Auxiliary function invocation information
    // @Field: TimeUS: Time since system startup
    // @Field: function: ID of triggered function
    // @Field: pos: switch position when function triggered
    // @Field: source: source of auxillary function invocation
    // @Field: result: true if function was successful
    AP::logger().Write(
        "AUXF",
        "TimeUS,function,pos,source,result",
        "s#---",
        "F----",
        "QHBBB",
        AP_HAL::micros64(),
        uint16_t(ch_option),
        uint8_t(pos),
        uint8_t(source),
        uint8_t(ret)
        );
    return ret;
}
bool RC_Channel::do_aux_function(const aux_func_t ch_option, const AuxSwitchPos ch_flag)
{
    switch(ch_option) {
    case AUX_FUNC::CAMERA_TRIGGER:
        do_aux_function_camera_trigger(ch_flag);
        break;

    case AUX_FUNC::FENCE:
        do_aux_function_fence(ch_flag);
        break;

    case AUX_FUNC::GRIPPER:
        do_aux_function_gripper(ch_flag);
        break;

    case AUX_FUNC::RC_OVERRIDE_ENABLE:
        // Allow or disallow RC_Override
        do_aux_function_rc_override_enable(ch_flag);
        break;

    case AUX_FUNC::AVOID_PROXIMITY:
        do_aux_function_avoid_proximity(ch_flag);
        break;

    case AUX_FUNC::RELAY:
        do_aux_function_relay(0, ch_flag == AuxSwitchPos::HIGH);
        break;
    case AUX_FUNC::RELAY2:
        do_aux_function_relay(1, ch_flag == AuxSwitchPos::HIGH);
        break;
    case AUX_FUNC::RELAY3:
        do_aux_function_relay(2, ch_flag == AuxSwitchPos::HIGH);
        break;
    case AUX_FUNC::RELAY4:
        do_aux_function_relay(3, ch_flag == AuxSwitchPos::HIGH);
        break;
    case AUX_FUNC::RELAY5:
        do_aux_function_relay(4, ch_flag == AuxSwitchPos::HIGH);
        break;
    case AUX_FUNC::RELAY6:
        do_aux_function_relay(5, ch_flag == AuxSwitchPos::HIGH);
        break;

    case AUX_FUNC::RUNCAM_CONTROL:
        do_aux_function_runcam_control(ch_flag);
        break;

    case AUX_FUNC::RUNCAM_OSD_CONTROL:
        do_aux_function_runcam_osd_control(ch_flag);
        break;

    case AUX_FUNC::CLEAR_WP:
        do_aux_function_clear_wp(ch_flag);
        break;
    case AUX_FUNC::MISSION_RESET:
        do_aux_function_mission_reset(ch_flag);
        break;

    case AUX_FUNC::AVOID_ADSB:
        do_aux_function_avoid_adsb(ch_flag);
        break;

#if HAL_GENERATOR_ENABLED
    case AUX_FUNC::GENERATOR:
        do_aux_function_generator(ch_flag);
        break;
#endif

    case AUX_FUNC::SPRAYER:
        do_aux_function_sprayer(ch_flag);
        break;

    case AUX_FUNC::LOST_VEHICLE_SOUND:
        do_aux_function_lost_vehicle_sound(ch_flag);
        break;
    //需要用到的功能
    case AUX_FUNC::ARMDISARM:
        do_aux_function_armdisarm(ch_flag);
        break;

    case AUX_FUNC::DISARM:
        if (ch_flag == AuxSwitchPos::HIGH) {
            AP::arming().disarm(AP_Arming::Method::AUXSWITCH);
        }
        break;

    case AUX_FUNC::COMPASS_LEARN:
        if (ch_flag == AuxSwitchPos::HIGH) {
            Compass &compass = AP::compass();
            compass.set_learn_type(Compass::LEARN_INFLIGHT, false);
        }
        break;

    case AUX_FUNC::LANDING_GEAR: {
        AP_LandingGear *lg = AP_LandingGear::get_singleton();
        if (lg == nullptr) {
            break;
        }
        switch (ch_flag) {
        case AuxSwitchPos::LOW:
            lg->set_position(AP_LandingGear::LandingGear_Deploy);
            break;
        case AuxSwitchPos::MIDDLE:
            // nothing
            break;
        case AuxSwitchPos::HIGH:
            lg->set_position(AP_LandingGear::LandingGear_Retract);
            break;
        }
        break;
    }

    case AUX_FUNC::GPS_DISABLE:
        AP::gps().force_disable(ch_flag == AuxSwitchPos::HIGH);
        break;

    case AUX_FUNC::GPS_DISABLE_YAW:
        AP::gps().set_force_disable_yaw(ch_flag == AuxSwitchPos::HIGH);
        break;

    case AUX_FUNC::DISABLE_AIRSPEED_USE: {
#if AP_AIRSPEED_ENABLED
        AP_Airspeed *airspeed = AP::airspeed();
        if (airspeed == nullptr) {
            break;
        }
        switch (ch_flag) {
        case AuxSwitchPos::HIGH:
            airspeed->force_disable_use(true);
            break;
        case AuxSwitchPos::MIDDLE:
            break;
        case AuxSwitchPos::LOW:
            airspeed->force_disable_use(false);
            break;
        }
#endif
        break;
    }

    case AUX_FUNC::MOTOR_ESTOP:
        switch (ch_flag) {
        case AuxSwitchPos::HIGH: {
            SRV_Channels::set_emergency_stop(true);

            // log E-stop
            AP_Logger *logger = AP_Logger::get_singleton();
            if (logger && logger->logging_enabled()) {
                logger->Write_Event(LogEvent::MOTORS_EMERGENCY_STOPPED);
            }
            break;
        }
        case AuxSwitchPos::MIDDLE:
            // nothing
            break;
        case AuxSwitchPos::LOW: {
            SRV_Channels::set_emergency_stop(false);

            // log E-stop cleared
            AP_Logger *logger = AP_Logger::get_singleton();
            if (logger && logger->logging_enabled()) {
                logger->Write_Event(LogEvent::MOTORS_EMERGENCY_STOP_CLEARED);
            }
            break;
        }
        }
        break;

    case AUX_FUNC::VISODOM_ALIGN:
#if HAL_VISUALODOM_ENABLED
        if (ch_flag == AuxSwitchPos::HIGH) {
            AP_VisualOdom *visual_odom = AP::visualodom();
            if (visual_odom != nullptr) {
                visual_odom->align_sensor_to_vehicle();
            }
        }
#endif
        break;

    case AUX_FUNC::EKF_POS_SOURCE:
        switch (ch_flag) {
        case AuxSwitchPos::LOW:
            // low switches to primary source
            AP::ahrs().set_posvelyaw_source_set(0);
            break;
        case AuxSwitchPos::MIDDLE:
            // middle switches to secondary source
            AP::ahrs().set_posvelyaw_source_set(1);
            break;
        case AuxSwitchPos::HIGH:
            // high switches to tertiary source
            AP::ahrs().set_posvelyaw_source_set(2);
            break;
        }
        break;

    case AUX_FUNC::OPTFLOW_CAL: {
#if AP_OPTICALFLOW_ENABLED
        OpticalFlow *optflow = AP::opticalflow();
        if (optflow == nullptr) {
            gcs().send_text(MAV_SEVERITY_CRITICAL, "OptFlow Cal: failed sensor not enabled");
            break;
        }
        if (ch_flag == AuxSwitchPos::HIGH) {
            optflow->start_calibration();
        } else {
            optflow->stop_calibration();
        }
#endif
        break;
    }

#if !HAL_MINIMIZE_FEATURES
    case AUX_FUNC::KILL_IMU1:
        AP::ins().kill_imu(0, ch_flag == AuxSwitchPos::HIGH);
        break;

    case AUX_FUNC::KILL_IMU2:
        AP::ins().kill_imu(1, ch_flag == AuxSwitchPos::HIGH);
        break;
#endif // HAL_MINIMIZE_FEATURES

    case AUX_FUNC::CAM_MODE_TOGGLE: {
        // Momentary switch to for cycling camera modes
        AP_Camera *camera = AP_Camera::get_singleton();
        if (camera == nullptr) {
            break;
        }
        switch (ch_flag) {
        case AuxSwitchPos::LOW:
            // nothing
            break;
        case AuxSwitchPos::MIDDLE:
            // nothing
            break;
        case AuxSwitchPos::HIGH:
            camera->cam_mode_toggle();
            break;
        }
        break;
    }

    case AUX_FUNC::RETRACT_MOUNT: {
#if HAL_MOUNT_ENABLED
        AP_Mount *mount = AP::mount();
        if (mount == nullptr) {
            break;
        }
        switch (ch_flag) {
            case AuxSwitchPos::HIGH:
                mount->set_mode(MAV_MOUNT_MODE_RETRACT);
                break;
            case AuxSwitchPos::MIDDLE:
                // nothing
                break;
            case AuxSwitchPos::LOW:
                mount->set_mode_to_default();
                break;
        }
#endif
        break;
    }

    case AUX_FUNC::EKF_LANE_SWITCH:
        // used to test emergency lane switch
        AP::ahrs().check_lane_switch();
        break;

    case AUX_FUNC::EKF_YAW_RESET:
        // used to test emergency yaw reset
        AP::ahrs().request_yaw_reset();
        break;

    // clear torqeedo error
    case AUX_FUNC::TORQEEDO_CLEAR_ERR: {
#if HAL_TORQEEDO_ENABLED
        if (ch_flag == AuxSwitchPos::HIGH) {
            AP_Torqeedo *torqeedo = AP_Torqeedo::get_singleton();
            if (torqeedo != nullptr) {
                torqeedo->clear_motor_error();
            }
        }
#endif
        break;
    }

    case AUX_FUNC::SCRIPTING_1:
    case AUX_FUNC::SCRIPTING_2:
    case AUX_FUNC::SCRIPTING_3:
    case AUX_FUNC::SCRIPTING_4:
    case AUX_FUNC::SCRIPTING_5:
    case AUX_FUNC::SCRIPTING_6:
    case AUX_FUNC::SCRIPTING_7:
    case AUX_FUNC::SCRIPTING_8:
        break;

    default:
        gcs().send_text(MAV_SEVERITY_INFO, "Invalid channel option (%u)", (unsigned int)ch_option);
        return false;
    }

    return true;
}

重点关注这个函数:

    case AUX_FUNC::ARMDISARM:
        do_aux_function_armdisarm(ch_flag);
        break;
void RC_Channel::do_aux_function_armdisarm(const AuxSwitchPos ch_flag)
{
    //解锁和上锁这个外设------ arm or disarm the vehicle
    switch (ch_flag) 
    {
    case AuxSwitchPos::HIGH:
        AP::arming().arm(AP_Arming::Method::AUXSWITCH, true); //最高就是解锁
        break;
    case AuxSwitchPos::MIDDLE:
        // nothing
        break;
    case AuxSwitchPos::LOW:
        AP::arming().disarm(AP_Arming::Method::AUXSWITCH); //最低就是上锁
        break;
    }
}

到这里就实现了通过遥控器实现解锁。

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
PX4 Autopilot是一款开源的自动驾驶飞控软件。它具有强大的飞行控制和导航功能,可以应用于多种无人机平台,包括多旋翼、固定翼和辆。PX4 Autopilot的开发历史可以追溯到Pixhawk项目,它是Pixhawk固件的一个分支。Pixhawk是一款流行的飞控硬件平台,而PX4 Autopilot则是为该硬件平台开发的软件。 与其他飞控系统相比,PX4 Autopilot具有许多优势。首先,它具有灵活的架构,可以根据不同的需求进行定制和扩展。其次,PX4 Autopilot支持多种传感器和导航系统,可以适应各种复杂的环境和任务需求。此外,PX4 Autopilot还提供了丰富的飞行模式和自动化功能,使得飞行操作更加简单和安全。 在使用PX4 Autopilot进行开发时,可以参考PX4 Autopilot User Guide和PX4学习笔记等文档,这些文档提供了详细的使用指南和教程。另外,可以在Github上找到PX4 Autopilot的源代码仓库,在这里可以查看最新的代码和提交贡献。 为了编译和构建PX4 Autopilot固件,可以根据不同的硬件平台选择相应的编译命令。例如,使用make px4_fmu-v2_default命令来构建适用于default.px4board的固件。类似地,可以使用make px4_fmu-v2_fixedwing命令构建适用于fixedwing.px4board的固件,使用make px4_fmu-v2_multicopter命令构建适用于multicopter.px4board的固件,使用make px4_fmu-v2_rover命令构建适用于rover.px4board的固件。 总而言之,PX4 Autopilot是一款功能强大的开源自动驾驶飞控软件,可以应用于多种无人机平台。通过参考相关文档和源代码,以及使用适用于不同硬件平台的编译命令,可以进行PX4 Autopilot的开发和定制。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

魔城烟雨

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

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

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

打赏作者

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

抵扣说明:

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

余额充值