ArduPilot开源飞控之AP_Mount

1. 源由

AP_Mount主要是挂的云台设备,配合相机使用。

当前云台也有各种硬件总线连接方式,并且软件协议也不尽相同,Ardupilot对这方面的支持还是不错的。

为了更好的选择云台,有必要从代码层面了解下目前支持的情况。

2. 框架设计

2.1 启动代码

传统Ardupilot启动方式。

Copter::init_ardupilot
 └──> AP_Mount::init

2.2 任务代码 update

命令状态更新。

SCHED_TASK_CLASS(AP_Mount,             &copter.camera_mount,        update,          50,  75, 108)
 └──> AP_Mount::update

2.3 任务代码 update_fast

云台姿态更新。

FAST_TASK_CLASS(AP_Mount, &copter.camera_mount, update_fast),
 └──> AP_Mount::update_fast

2.4 任务代码 handle_message

MMAVLink命令处理管道。

SCHED_TASK_CLASS(GCS,                  (GCS*)&copter._gcs,          update_receive, 400, 180, 102)
 └──> GCS::update_receive
     └──> GCS_MAVLINK::update_receive
         └──> GCS_MAVLINK_Copter::packetReceived
             └──> GCS_MAVLINK::packetReceived
                 └──> GCS_MAVLINK_Copter::handle_mount_message
                     └──> GCS_MAVLINK::handle_mount_message
                         └──> AP_Mount::handle_message

3. 重要例程

3.1 init

支持以下类型的云台:

  1. AP_Mount_Servo
  2. AP_Mount_SoloGimbal
  3. AP_Mount_Alexmos
  4. AP_Mount_SToRM32
  5. AP_Mount_SToRM32_serial
  6. AP_Mount_Gremsy
  7. AP_Mount_Siyi
  8. AP_Mount_Scripting
  9. AP_Mount_Xacti
  10. AP_Mount_Viewpro
// init - detect and initialise all mounts
void AP_Mount::init()
 │  // check init has not been called before
 ├──> <_num_instances != 0>
 │   └──> return
 │
 │  // perform any required parameter conversion
 ├──> convert_params()
 │
 │  // primary is reset to the first instantiated mount
 ├──> bool primary_set = false
 │
 │  // create mount instance
 ├──> <for (uint8_t instance=0 instance<AP_MOUNT_MAX_INSTANCES instance++)>
 │   ├──> <case Type::Servo> <HAL_MOUNT_SERVO_ENABLED>
 │   │   ├──> _backends[instance] = new AP_Mount_Servo(*this, _params[instance], true, instance)
 │   │   ├──> _num_instances++
 │   │   └──> break
 │   ├──> <case Type::SoloGimbal> <HAL_SOLO_GIMBAL_ENABLED>
 │   │   ├──> _backends[instance] = new AP_Mount_SoloGimbal(*this, _params[instance], instance)
 │   │   ├──> _num_instances++
 │   │   └──> break
 │   ├──> <case Type::Alexmos> <HAL_MOUNT_ALEXMOS_ENABLED>
 │   │   ├──> _backends[instance] = new AP_Mount_Alexmos(*this, _params[instance], instance)
 │   │   ├──> _num_instances++
 │   │   └──> break
 │   ├──> <case Type::SToRM32> <HAL_MOUNT_STORM32MAVLINK_ENABLED>  // check for SToRM32 mounts using MAVLink protocol
 │   │   ├──> _backends[instance] = new AP_Mount_SToRM32(*this, _params[instance], instance)
 │   │   ├──> _num_instances++
 │   │   └──> break
 │   ├──> <case Type::SToRM32_serial> <HAL_MOUNT_STORM32SERIAL_ENABLED>  // check for SToRM32 mounts using serial protocol
 │   │   ├──> _backends[instance] = new AP_Mount_SToRM32_serial(*this, _params[instance], instance)
 │   │   ├──> _num_instances++
 │   │   └──> break
 │   ├──> <case Type::Gremsy> <HAL_MOUNT_GREMSY_ENABLED> // check for Gremsy mounts
 │   │   ├──> _backends[instance] = new AP_Mount_Gremsy(*this, _params[instance], instance)
 │   │   ├──> _num_instances++
 │   │   └──> break
 │   ├──> <case Type::BrushlessPWM> <HAL_MOUNT_SERVO_ENABLED> // check for BrushlessPWM mounts (uses Servo backend)
 │   │   ├──> _backends[instance] = new AP_Mount_Servo(*this, _params[instance], false, instance)
 │   │   ├──> _num_instances++
 │   │   └──> break
 │   ├──> <case Type::Siyi> <HAL_MOUNT_SIYI_ENABLED> // check for Siyi gimbal
 │   │   ├──> _backends[instance] = new AP_Mount_Siyi(*this, _params[instance], instance)
 │   │   ├──> _num_instances++
 │   │   └──> break
 │   ├──> <case Type::Scripting> <HAL_MOUNT_SCRIPTING_ENABLED> // check for Scripting gimbal
 │   │   ├──> _backends[instance] = new AP_Mount_Scripting(*this, _params[instance], instance)
 │   │   ├──> _num_instances++
 │   │   └──> break
 │   ├──> <case Type::Xacti> <HAL_MOUNT_XACTI_ENABLED> // check for Xacti gimbal
 │   │   ├──> _backends[instance] = new AP_Mount_Xacti(*this, _params[instance], instance)
 │   │   ├──> _num_instances++
 │   │   └──> break
 │   ├──> <case Type::Viewpro> <HAL_MOUNT_VIEWPRO_ENABLED> // check for Xacti gimbal
 │   │   ├──> _backends[instance] = new AP_Mount_Viewpro(*this, _params[instance], instance)
 │   │   ├──> _num_instances++
 │   │   └──> break
 │   │
 │   │  // init new instance
 │   └──> <_backends[instance] != nullptr> <!primary_set>
 │       ├──> _primary = instance
 │       └──> primary_set = true
 │
 │  // init each instance, do it after all instances were created, so that they all know things
 └──> <for (uint8_t instance=0 instance<AP_MOUNT_MAX_INSTANCES instance++)>
     └──> <_backends[instance] != nullptr>
         ├──> _backends[instance]->init()
         └──> set_mode_to_default(instance)

3.2 update

直接调用驱动更新云台状态。

// update - give mount opportunity to update servos.  should be called at 10hz or higher
AP_Mount::update
 │  // update each instance
 └──> <for (uint8_t instance=0 instance<AP_MOUNT_MAX_INSTANCES instance++)>
     └──> <_backends[instance] != nullptr>
         └──> _backends[instance]->update()

3.3 update_fast

直接调用驱动更新云台姿态。

// used for gimbals that need to read INS data at full rate
void AP_Mount::update_fast()
 │  // update each instance
 └──> <for (uint8_t instance=0 instance<AP_MOUNT_MAX_INSTANCES instance++)>
     └──> <_backends[instance] != nullptr>
         └──> _backends[instance]->update_fast()

3.4 handle_message

支持MAVLink命令:

  1. MAVLINK_MSG_ID_GIMBAL_REPORT
  2. MAVLINK_MSG_ID_MOUNT_CONFIGURE
  3. MAVLINK_MSG_ID_MOUNT_CONTROL
  4. MAVLINK_MSG_ID_GLOBAL_POSITION_INT
  5. MAVLINK_MSG_ID_GIMBAL_MANAGER_SET_ATTITUDE
  6. MAVLINK_MSG_ID_GIMBAL_MANAGER_SET_PITCHYAW
  7. MAVLINK_MSG_ID_GIMBAL_DEVICE_INFORMATION
  8. MAVLINK_MSG_ID_GIMBAL_DEVICE_ATTITUDE_STATUS
AP_Mount::handle_message
 ├──> <case MAVLINK_MSG_ID_GIMBAL_REPORT>
 │   ├──> handle_gimbal_report(chan, msg)
 │   └──> break
 ├──> <case MAVLINK_MSG_ID_MOUNT_CONFIGURE> <AP_MAVLINK_MSG_MOUNT_CONFIGURE_ENABLED>
 │   ├──> handle_mount_configure(msg)
 │   └──> break
 ├──> <case MAVLINK_MSG_ID_MOUNT_CONTROL> <AP_MAVLINK_MSG_MOUNT_CONTROL_ENABLED>
 │   ├──> handle_mount_control(msg)
 │   └──> break
 ├──> <case MAVLINK_MSG_ID_GLOBAL_POSITION_INT>
 │   ├──> handle_global_position_int(msg)
 │   └──> break
 ├──> <case MAVLINK_MSG_ID_GIMBAL_MANAGER_SET_ATTITUDE>
 │   ├──> handle_gimbal_manager_set_attitude(msg)
 │   └──> break
 ├──> <case MAVLINK_MSG_ID_GIMBAL_MANAGER_SET_PITCHYAW>
 │   ├──> handle_command_gimbal_manager_set_pitchyaw(msg)
 │   └──> break
 ├──> <case MAVLINK_MSG_ID_GIMBAL_DEVICE_INFORMATION>
 │   ├──> handle_gimbal_device_information(msg)
 │   └──> break
 ├──> <case MAVLINK_MSG_ID_GIMBAL_DEVICE_ATTITUDE_STATUS>
 │   ├──> handle_gimbal_device_attitude_status(msg)
 │   └──> break
 └──> <default> <HAL_BOARD_SITL>
     ├──> AP_HAL::panic("Unhandled mount case")
     └──> break

4. 总结

根据AP_Mount的代码实现上,总体可以归纳以下几个方面:

  1. 硬件总线
  2. MAVLink命令分类
  3. 驱动协议格式

因硬件的差异,需要根据代码支持情况进行选择,以便Ardupilot对云台的兼容性支持。

5. 参考资料

【1】ArduPilot开源飞控系统之简单介绍
【2】ArduPilot之开源代码Task介绍
【3】ArduPilot飞控启动&运行过程简介
【4】ArduPilot之开源代码Library&Sketches设计
【5】ArduPilot之开源代码Sensor Drivers设计
【6】ArduPilot开源飞控之AP_Mount_Backend
【7】ArduPilot开源飞控之AP_Mount_Backend_Serial

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值