ArduPilot开源飞控之AP_Mount_Siyi

ArduPilot开源飞控之AP_Mount_Siyi

  • 1. 源由
  • 2. 框架设计
    • 2.1 类和继承
    • 2.2 公共方法
    • 2.3 保护方法
    • 2.4 私有成员和方法
    • 2.5 解析状态
    • 2.6 重要成员变量
  • 3. 重要方法
    • 3.1 AP_Mount_Siyi::init
    • 3.2 AP_Mount_Siyi::update
    • 3.3 AP_Mount_Siyi::read_incoming_packets
    • 3.4 AP_Mount_Siyi::process_packet
    • 3.5 AP_Mount_Siyi::update_zoom_control
    • 3.6 AP_Mount_Backend::set_rctargeting_on_rcinput_change
  • 4. 辅助函数
    • 4.1 基本能力
    • 4.2 摄像头&红外测距功能
    • 4.3 云台操作
  • 4. 总结
  • 5. 参考资料

1. 源由

AP_Mount_Siyi主要是挂载SIYI云台,配合SIYI的产品,比如相机。

  • SIYI Gimbal Camera

目前,SIYI云台摄像头还是挺不错的,而且在开源社区也是蛮热门的。另外,有专业的团队进行代码维护,相对来说应用代码涉及的内容会更加全面。

2. 框架设计

  • 继承自 AP_Mount_Backend
  • 用于控制摄像头和万向节的类

这个类是一个复杂的云台和摄像头控制系统,提供了初始化、更新、健康检查以及各种摄像头操作(如拍照、录像、变焦、对焦等)的方法。它还定义了一些用于处理和发送数据包的私有方法和变量。

2.1 类和继承

class AP_Mount_Siyi : public AP_Mount_Backend
{// 使用基类构造函数using AP_Mount_Backend::AP_Mount_Backend;// 禁止拷贝构造和赋值CLASS_NO_COPY(AP_Mount_Siyi);
  • AP_Mount_Siyi 继承自 AP_Mount_Backend
  • 使用 using 关键字继承了基类的构造函数。
  • 使用宏 CLASS_NO_COPY 禁止类的拷贝构造和赋值操作。

2.2 公共方法

public:void init() override;void update() override;bool healthy() const override;bool has_roll_control() const override { return false; }bool has_pan_control() const override { return yaw_range_valid(); }bool take_picture() override;bool record_video(bool start_recording) override;bool set_zoom(ZoomType zoom_type, float zoom_value) override;SetFocusResult set_focus(FocusType focus_type, float focus_value) override;bool set_lens(uint8_t lens) override;bool set_camera_source(uint8_t primary_source, uint8_t secondary_source) override;void send_camera_information(mavlink_channel_t chan) const override;void send_camera_settings(mavlink_channel_t chan) const override;bool get_rangefinder_distance(float& distance_m) const override;
  • initupdatehealthy 等方法是重载基类的虚函数。
  • has_roll_control 返回 false,表示该设备不支持滚动控制。
  • has_pan_control 返回 yaw_range_valid() 的结果,表示是否支持平移控制。

2.3 保护方法

protected:bool get_attitude_quaternion(Quaternion& att_quat) override;bool get_angular_velocity(Vector3f& rates) override {rates = _current_rates_rads;return true;}
  • get_attitude_quaternion 获取姿态四元数。
  • get_angular_velocity 获取角速度,这里直接返回 _current_rates_rads

2.4 私有成员和方法

private:enum class SiyiCommandId { ... };enum class FunctionFeedbackInfo : uint8_t { ... };enum class PhotoFunction : uint8_t { ... };enum class ParseState : uint8_t { ... };enum class HardwareModel : uint8_t { ... } _hardware_model;enum class HdrStatus : uint8_t { OFF = 0, ON = 1 };enum class RecordingStatus : uint8_t { OFF = 0, ON = 1, NO_CARD = 2, DATA_LOSS = 3 };enum class GimbalMotionMode : uint8_t { LOCK = 0, FOLLOW = 1, FPV = 2 };enum class GimbalMountingDirection : uint8_t { UNDEFINED = 0, NORMAL = 1, UPSIDE_DOWN = 2 };enum class VideoOutputStatus : uint8_t { HDMI = 0, CVBS = 1 };typedef struct { ... } GimbalConfigInfo;static_assert(sizeof(GimbalConfigInfo) == 7, "GimbalConfigInfo must be 7 bytes");enum class CameraImageType : uint8_t { ... };typedef struct { ... } Version;typedef struct { ... } FirmwareVersion;void read_incoming_packets();void process_packet();bool send_packet(SiyiCommandId cmd_id, const uint8_t* databuff, uint8_t databuff_len);bool send_1byte_packet(SiyiCommandId cmd_id, uint8_t data_byte);void request_firmware_version();void request_hardware_id();void request_configuration();void request_function_feedback_info();void request_gimbal_attitude();void request_rangefinder_distance();void rotate_gimbal(int8_t pitch_scalar, int8_t yaw_scalar, bool yaw_is_ef);bool set_motion_mode(const GimbalMotionMode mode, const bool force=false);void send_target_rates(float pitch_rads, float yaw_rads, bool yaw_is_ef);void send_target_angles(float pitch_rad, float yaw_rad, bool yaw_is_ef);bool send_zoom_rate(float zoom_value);bool send_zoom_mult(float zoom_mult);float get_zoom_mult_max() const;void update_zoom_control();const char* get_model_name() const;void check_firmware_version() const;AP_HAL::UARTDriver *_uart;bool _initialised;bool _got_hardware_id;FirmwareVersion _fw_version;uint8_t _msg_buff[AP_MOUNT_SIYI_PACKETLEN_MAX];uint8_t _msg_buff_len;const uint8_t _msg_buff_data_start = 8;struct PACKED {uint16_t data_len;uint8_t command_id;uint16_t data_bytes_received;uint16_t crc16;ParseState state;} _parsed_msg;uint32_t _last_send_ms;uint16_t _last_seq;Vector3f _current_angle_rad;Vector3f _current_rates_rads;uint32_t _last_current_angle_rad_ms;uint32_t _last_req_current_angle_rad_ms;ZoomType _zoom_type;float _zoom_rate_target;float _zoom_mult;uint32_t _last_zoom_control_ms;GimbalConfigInfo _config_info;uint32_t _last_rangefinder_req_ms;uint32_t _last_rangefinder_dist_ms;float _rangefinder_dist_m;uint32_t _last_attitude_send_ms;void send_attitude(void);struct HWInfo {uint8_t hwid[2];const char* model_name;};static const HWInfo hardware_lookup_table[];uint8_t sent_time_count;
};
  • 枚举 SiyiCommandIdFunctionFeedbackInfo 等定义了各种命令和状态。
  • GimbalConfigInfo 结构体存储云台配置信息,并用 static_assert 确保其大小为 7 字节。
  • 各种私有方法用于发送、处理和读取数据包,管理云台的运动模式和摄像头的控制。

2.5 解析状态

enum class ParseState : uint8_t {WAITING_FOR_HEADER_LOW,WAITING_FOR_HEADER_HIGH,WAITING_FOR_CTRL,WAITING_FOR_DATALEN_LOW,WAITING_FOR_DATALEN_HIGH,WAITING_FOR_SEQ_LOW,WAITING_FOR_SEQ_HIGH,WAITING_FOR_CMDID,WAITING_FOR_DATA,WAITING_FOR_CRC_LOW,WAITING_FOR_CRC_HIGH,
};
  • ParseState 枚举表示数据包解析的不同状态。

2.6 重要成员变量

  • _uart:指向用于通信的 UART 驱动程序。
  • _initialised:标志驱动程序是否已初始化。
  • _got_hardware_id:标志是否已收到硬件 ID。
  • _fw_version:固件版本信息。
  • _msg_buff_msg_buff_len:用于存储消息缓冲区和其长度。
  • _parsed_msg:结构体,用于存储解析消息的状态。
  • _current_angle_rad_current_rates_rads:存储从云台接收到的当前角度和角速度。

3. 重要方法

3.1 AP_Mount_Siyi::init

该初始化例程在AP_Mount::init中调用。

AP_Mount_Siyi::init()
├── 定义 `serial_manager` 变量,并获取 `AP_SerialManager` 的实例
│   ├── `const AP_SerialManager& serial_manager = AP::serialmanager();`
├── 通过 `serial_manager` 查找串口并赋值给 `_uart`
│   ├── `_uart = serial_manager.find_serial(AP_SerialManager::SerialProtocol_Gimbal, 0);`
│   ├── 检查 `_uart` 是否为 `nullptr`
│       ├── 如果是 `nullptr`
│       │   ├── `return;`
├── 设置 `_initialised` 为 `true`
│   ├── `_initialised = true;`
├── 调用基类的 `init()` 方法├── `AP_Mount_Backend::init();`

3.2 AP_Mount_Siyi::update

该定时更新例程在AP_Mount::update中调用。

AP_Mount_Siyi::update
├── 检查是否初始化 _initialised
│   ├── 如果未初始化,立即退出
├── 读取云台的传入数据包 read_incoming_packets()
├── 获取当前时间 now_ms
├── 定期请求固件版本或配置
│   ├── 如果自上次发送以来已过1000毫秒
│   │   ├── 更新最后发送时间 _last_send_ms
│   │   ├── 如果未获取硬件ID,则请求硬件ID request_hardware_id()
│   │   ├── 否则如果固件版本未收到,则请求固件版本 request_firmware_version()
│   │   ├── 否则请求配置 request_configuration()
│   │   └── 发送UTC时间给摄像头 (AP_RTC_ENABLED)
│       └── 如果已发送时间计数 sent_time_count 小于 5
│           ├── 获取UTC时间
│           └── 发送时间数据包 send_packet()
├── 定期请求姿态 request_gimbal_attitude()
│   ├── 如果自上次请求姿态以来已过50毫秒
│       ├── 请求云台姿态
│       └── 更新最后请求姿态时间 _last_req_current_angle_rad_ms
├── 定期请求测距仪距离 request_rangefinder_distance()
│   ├── 如果硬件型号为 ZT30 且自上次请求以来已过100毫秒
│       └── 请求测距仪距离
│       └── 更新最后请求时间 _last_rangefinder_req_ms
├── 定期发送姿态 send_attitude()
│   ├── 如果自上次发送姿态以来已过100毫秒
│       ├── 更新最后发送姿态时间 _last_attitude_send_ms
│       └── 发送姿态
├── 运行变焦控制 update_zoom_control()
├── RC输入改变时切换到 RC_TARGETING 模式 set_rctargeting_on_rcinput_change()
├── 获取当前云台模式 get_mode()
│   ├── 根据模式设定目标角度或速率
│       ├── MAV_MOUNT_MODE_RETRACT 模式
│           ├── 获取收回角度 _params.retract_angles
│           ├── 设置目标类型为角度
│           └── 将角度从度转换为弧度并设置
│       ├── MAV_MOUNT_MODE_NEUTRAL 模式
│           ├── 获取中立角度 _params.neutral_angles
│           ├── 设置目标类型为角度
│           └── 将角度从度转换为弧度并设置
│       ├── MAV_MOUNT_MODE_MAVLINK_TARGETING 模式
│           └── 处理传入消息时存储MAVLINK目标
│       ├── MAV_MOUNT_MODE_RC_TARGETING 模式
│           ├── 使用飞行员的RC输入更新目标
│           ├── 获取RC目标 get_rc_target()
│           └── 根据目标类型更新角度或速率
│       ├── MAV_MOUNT_MODE_GPS_POINT 模式
│           ├── 获取指向ROI的角度目标 get_angle_target_to_roi()
│           └── 设置目标类型为角度
│       ├── MAV_MOUNT_MODE_HOME_LOCATION 模式
│           ├── 获取指向Home位置的角度目标 get_angle_target_to_home()
│           └── 设置目标类型为角度
│       ├── MAV_MOUNT_MODE_SYSID_TARGET 模式
│           ├── 获取指向其他车辆的角度目标 get_angle_target_to_sysid()
│           └── 设置目标类型为角度
│       └── 其他模式
│           └── 引发内部错误 INTERNAL_ERROR()
├── 根据目标类型发送目标角度或速率
│   ├── 目标类型为角度
│       └── 发送目标角度 send_target_angles()
│   └── 目标类型为速率
│       └── 发送目标速率 send_target_rates()

3.3 AP_Mount_Siyi::read_incoming_packets

AP_Mount_Siyi::update时,调用该函数,对SIYI云台串口数据报文进行解析。

AP_Mount_Siyi::read_incoming_packets
|
|-- 检查串口接口上是否有数据可读
|   |-- 获取可读的字节数 `nbytes`
|   |-- 如果没有字节可读,则返回
|
|-- 初始化重置解析器状态的标志 `reset_parser`
|
|-- 遍历接收到的每个字节
|   |-- 读取一个字节 `b`
|   |-- 将字节添加到消息缓冲区 `_msg_buff`
|   |-- 检查消息是否过长,如果过长则重置解析器状态
|
|   |-- 根据当前解析状态处理字节
|       |-- `WAITING_FOR_HEADER_LOW`
|           |-- 如果字节为头部低字节 `AP_MOUNT_SIYI_HEADER1`,则转到 `WAITING_FOR_HEADER_HIGH` 状态
|           |-- 否则,重置解析器状态
|
|       |-- `WAITING_FOR_HEADER_HIGH`
|           |-- 如果字节为头部高字节 `AP_MOUNT_SIYI_HEADER2`,则转到 `WAITING_FOR_CTRL` 状态
|           |-- 否则,重置解析器状态
|
|       |-- `WAITING_FOR_CTRL`
|           |-- 转到 `WAITING_FOR_DATALEN_LOW` 状态
|
|       |-- `WAITING_FOR_DATALEN_LOW`
|           |-- 保存数据长度低字节,转到 `WAITING_FOR_DATALEN_HIGH` 状态
|
|       |-- `WAITING_FOR_DATALEN_HIGH`
|           |-- 保存数据长度高字节,并进行数据长度合理性检查
|           |-- 如果数据长度合理,转到 `WAITING_FOR_SEQ_LOW` 状态
|           |-- 否则,重置解析器状态并输出调试信息
|
|       |-- `WAITING_FOR_SEQ_LOW`
|           |-- 转到 `WAITING_FOR_SEQ_HIGH` 状态
|
|       |-- `WAITING_FOR_SEQ_HIGH`
|           |-- 转到 `WAITING_FOR_CMDID` 状态
|
|       |-- `WAITING_FOR_CMDID`
|           |-- 保存命令ID,如果有数据则转到 `WAITING_FOR_DATA` 状态,否则转到 `WAITING_FOR_CRC_LOW` 状态
|
|       |-- `WAITING_FOR_DATA`
|           |-- 接收数据字节,如果所有数据接收完毕,则转到 `WAITING_FOR_CRC_LOW` 状态
|
|       |-- `WAITING_FOR_CRC_LOW`
|           |-- 保存CRC低字节,转到 `WAITING_FOR_CRC_HIGH` 状态
|
|       |-- `WAITING_FOR_CRC_HIGH`
|           |-- 保存CRC高字节,进行CRC校验
|           |-- 如果CRC校验成功,则处理接收到的封包 `process_packet()`
|           |-- 否则,输出调试信息
|           |-- 重置解析器状态
|
|-- 重置解析器状态
|   |-- 重置解析状态为 `WAITING_FOR_HEADER_LOW`
|   |-- 清空消息缓冲区长度 `_msg_buff_len`
|   |-- 重置 `reset_parser` 标志

3.4 AP_Mount_Siyi::process_packet

云台摄像机报文处理,支持以下命令:

  • SiyiCommandId::ACQUIRE_FIRMWARE_VERSION(0x01)
  • SiyiCommandId::HARDWARE_ID(0x02)
  • SiyiCommandId::AUTO_FOCUS(0x04)
  • SiyiCommandId::MANUAL_ZOOM_AND_AUTO_FOCUS(0x05)
  • SiyiCommandId::MANUAL_FOCUS(0x06)
  • SiyiCommandId::GIMBAL_ROTATION(0x07)
  • SiyiCommandId::CENTER(0x08)
  • SiyiCommandId::ACQUIRE_GIMBAL_CONFIG_INFO(0x0A)
  • SiyiCommandId::FUNCTION_FEEDBACK_INFO(0x0B)
  • SiyiCommandId::PHOTO(0x0C)
  • SiyiCommandId::ACQUIRE_GIMBAL_ATTITUDE(0x0D)
  • SiyiCommandId::READ_RANGEFINDER(0x15)
AP_Mount_Siyi::process_packet
└── switch ((SiyiCommandId)_parsed_msg.command_id)├── case SiyiCommandId::ACQUIRE_FIRMWARE_VERSION│   ├── 检查 _parsed_msg.data_bytes_received 是否为 128│   ├── 解析并显示固件版本│   ├── 检查摄像机固件版本是否全为零│   ├── 设置 _fw_version.received 为 true│   ├── 显示摄像机和云台固件版本│   ├── 显示变焦固件版本(如果存在)│   └── 检查固件版本是否为最新├── case SiyiCommandId::HARDWARE_ID│   ├── 查找硬件 ID 的前两位│   ├── 设置 _hardware_model│   └── 设置 _got_hardware_id 为 true├── case SiyiCommandId::AUTO_FOCUS│   └── #if AP_MOUNT_SIYI_DEBUG│       ├── 检查 _parsed_msg.data_bytes_received 是否为 1│       └── 调试输出自动对焦信息├── case SiyiCommandId::MANUAL_ZOOM_AND_AUTO_FOCUS│   ├── 检查 _parsed_msg.data_bytes_received 是否为 2│   └── 解析变焦倍数并调试输出├── case SiyiCommandId::MANUAL_FOCUS│   └── #if AP_MOUNT_SIYI_DEBUG│       ├── 检查 _parsed_msg.data_bytes_received 是否为 1│       └── 调试输出手动对焦信息├── case SiyiCommandId::GIMBAL_ROTATION│   └── #if AP_MOUNT_SIYI_DEBUG│       ├── 检查 _parsed_msg.data_bytes_received 是否为 1│       └── 调试输出云台旋转信息├── case SiyiCommandId::CENTER│   └── #if AP_MOUNT_SIYI_DEBUG│       ├── 检查 _parsed_msg.data_bytes_received 是否为 1│       └── 调试输出居中信息├── case SiyiCommandId::ACQUIRE_GIMBAL_CONFIG_INFO│   ├── 保存之前的录制状态│   ├── 更新云台配置信息│   ├── 如果录制状态变化,向用户警报│   └── 调试输出云台配置信息├── case SiyiCommandId::FUNCTION_FEEDBACK_INFO│   ├── 检查 _parsed_msg.data_bytes_received 是否为 1│   ├── 解析功能反馈信息│   └── 根据反馈信息进行相应操作├── case SiyiCommandId::PHOTO│   └── 不执行任何操作├── case SiyiCommandId::ACQUIRE_GIMBAL_ATTITUDE│   ├── 检查 _parsed_msg.data_bytes_received 是否为 12│   ├── 更新当前角度和速率│   └── 解析并转换角度和速率信息├── case SiyiCommandId::READ_RANGEFINDER│   ├── 解析测距仪距离│   └── 更新最后一次测距时间└── default└── 调试输出未处理的命令 ID#if AP_MOUNT_SIYI_DEBUG
└── 如果存在意外的数据长度└── 调试输出意外长度信息

3.5 AP_Mount_Siyi::update_zoom_control

对摄像头使用SiyiCommandId::MANUAL_ZOOM_AND_AUTO_FOCUS进行光学调焦。

AP_Mount_Siyi::update_zoom_control
└── if (_zoom_type == ZoomType::RATE)├── const uint32_t now_ms = AP_HAL::millis();├── if (now_ms - _last_zoom_control_ms < 1000)│   └── return;├── _last_zoom_control_ms = now_ms;├── if (!is_zero(_zoom_rate_target))│   └── send_zoom_rate(_zoom_rate_target);└── // 如果 _zoom_rate_target 是零,则不会发送缩放率,因为这会触发自动对焦

3.6 AP_Mount_Backend::set_rctargeting_on_rcinput_change

当RC控制配置辅助功能RC_Channel::AUX_FUNC::MOUNT1_ROLLRC_Channel::AUX_FUNC::MOUNT1_PITCHRC_Channel::AUX_FUNC::MOUNT1_YAW时,可以直接通过RC功能键进行手动控制。

AP_Mount_Backend::set_rctargeting_on_rcinput_change
├── 如果 (!rc().has_valid_input())
│   └── 返回;
├── roll_ch = rc().find_channel_for_option(...)
├── pitch_ch = rc().find_channel_for_option(...)
├── yaw_ch = rc().find_channel_for_option(...)
├── 如果 (!last_rc_input.initialised)
│   └── 初始化 last_rc_input
└── 如果 (get_mode() != MAV_MOUNT_MODE_RC_TARGETING && get_mode() != MAV_MOUNT_MODE_RETRACT)├── roll_dz = MAX(roll_ch->get_dead_zone(), 10)├── pitch_dz = MAX(pitch_ch->get_dead_zone(), 10)├── yaw_dz = MAX(yaw_ch->get_dead_zone(), 10)└── 如果 (遥控器输入发生变化条件)└── 设置模式为 MAV_MOUNT_MODE_RC_TARGETING
└── 如果 (get_mode() == MAV_MOUNT_MODE_RC_TARGETING || get_mode() == MAV_MOUNT_MODE_RETRACT)└── 更新 last_rc_input

4. 辅助函数

4.1 基本能力

检查SIYI云台摄像头:

  1. 健康状态(无串口通信,认为设备不健康)
  2. 是否具备roll方向旋转能力
  3. 是否具备yaw方向旋转能力

注:ZT30具备3维光学吊舱;A2 mini仅具有Pitch。

    // return true if healthybool healthy() const override;// return true if this mount accepts roll targetsbool has_roll_control() const override { return false; }// has_pan_control - returns true if this mount can control its pan (required for multicopters)bool has_pan_control() const override { return yaw_range_valid(); };
    // returns true if user has configured a valid yaw angle range// allows user to disable yaw even on 3-axis gimbalbool yaw_range_valid() const { return (_params.yaw_angle_min < _params.yaw_angle_max); }

4.2 摄像头&红外测距功能

  • 摄像头
    //// camera controls//// take a picture.  returns true on successbool take_picture() override;// start or stop video recording// set start_recording = true to start record, false to stop recordingbool record_video(bool start_recording) override;// set zoom specified as a rate or percentagebool set_zoom(ZoomType zoom_type, float zoom_value) override;// set focus specified as rate, percentage or auto// focus in = -1, focus hold = 0, focus out = 1SetFocusResult set_focus(FocusType focus_type, float focus_value) override;// set camera lens as a value from 0 to 8.  ZT30 onlybool set_lens(uint8_t lens) override;// set_camera_source is functionally the same as set_lens except primary and secondary lenses are specified by type// primary and secondary sources use the AP_Camera::CameraSource enum cast to uint8_tbool set_camera_source(uint8_t primary_source, uint8_t secondary_source) override;// send camera information message to GCSvoid send_camera_information(mavlink_channel_t chan) const override;// send camera settings message to GCSvoid send_camera_settings(mavlink_channel_t chan) const override;
  • 红外测距
    //// rangefinder//// get rangefinder distance.  Returns true on successbool get_rangefinder_distance(float& distance_m) const override;

4.3 云台操作

  • 云台控制相关操作&功能
    // send packet to gimbal// returns true on success, false if outgoing serial buffer is fullbool send_packet(SiyiCommandId cmd_id, const uint8_t* databuff, uint8_t databuff_len);bool send_1byte_packet(SiyiCommandId cmd_id, uint8_t data_byte);// request info from gimbalvoid request_firmware_version() { send_packet(SiyiCommandId::ACQUIRE_FIRMWARE_VERSION, nullptr, 0); }void request_hardware_id() { send_packet(SiyiCommandId::HARDWARE_ID, nullptr, 0); }void request_configuration() { send_packet(SiyiCommandId::ACQUIRE_GIMBAL_CONFIG_INFO, nullptr, 0); }void request_function_feedback_info() { send_packet(SiyiCommandId::FUNCTION_FEEDBACK_INFO, nullptr, 0); }void request_gimbal_attitude() { send_packet(SiyiCommandId::ACQUIRE_GIMBAL_ATTITUDE, nullptr, 0); }void request_rangefinder_distance() { send_packet(SiyiCommandId::READ_RANGEFINDER, nullptr, 0); }// rotate gimbal.  pitch_rate and yaw_rate are scalars in the range -100 ~ +100// yaw_is_ef should be true if gimbal should maintain an earth-frame target (aka lock)void rotate_gimbal(int8_t pitch_scalar, int8_t yaw_scalar, bool yaw_is_ef);// Set gimbal's motion mode if it has changed. Use force=true to always send.//   FOLLOW: roll and pitch are in earth-frame, yaw is in body-frame//   LOCK: roll, pitch and yaw are all in earth-frame//   FPV: roll, pitch and yaw are all in body-frame// Returns true if message successfully sent to Gimbalbool set_motion_mode(const GimbalMotionMode mode, const bool force=false);// send target pitch and yaw rates to gimbal// yaw_is_ef should be true if yaw_rads target is an earth frame rate, false if body_framevoid send_target_rates(float pitch_rads, float yaw_rads, bool yaw_is_ef);// send target pitch and yaw angles to gimbal// yaw_is_ef should be true if yaw_rad target is an earth frame angle, false if body_framevoid send_target_angles(float pitch_rad, float yaw_rad, bool yaw_is_ef);// send zoom rate command to camera. zoom out = -1, hold = 0, zoom in = 1bool send_zoom_rate(float zoom_value);// send zoom multiple command to camera. e.g. 1x, 10x, 30xbool send_zoom_mult(float zoom_mult);// get zoom multiple maxfloat get_zoom_mult_max() const;// update zoom controllervoid update_zoom_control();// get model name string, returns nullptr if hardware id is unknownconst char* get_model_name() const;// Checks that the firmware version on the Gimbal meets the minimum supported version.void check_firmware_version() const;

4. 总结

AP_Mount_Siyi是在云台基础上集成了摄像头、红外测距等诸多功能的复合设备。

  • 云台摄像头 串口接 飞控
  • AI模块 串口接 飞控

其中云台摄像头 串口接 飞控,走的就是本文所描述的协议。而AI模块 串口接飞控侧重的伴机电脑的目标跟踪。

在这里插入图片描述

5. 参考资料

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/44675.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

哈斯机床采集数据

哈斯自身也有一套设备采集监控系统&#xff0c;但是软件和架构功能都比较老&#xff0c;再加上不能兼容其他数控系统&#xff0c;所以即使免费送给客户&#xff0c;客户的使用意愿也十分有限。 哈斯系统市面上常见就串口和网口两种形式。关于市面上机床采集的问题&#xff1a;网…

Bash ——shell

Bash作为用户与操作系统之间的接口&#xff0c;让用户通过命令行输入各种指令来控制和操作计算机系统。 shell的两种解释&#xff1a; 1.linux命令解释器 Terminal 终端 ——》shell命令 ——》 Linux kernel &#xff08;内核&#xff09; Linux内核的作用&#xff1a; 1.…

15、电科院FTU检测标准学习笔记-基本性能

作者简介&#xff1a; 本人从事电力系统多年&#xff0c;岗位包含研发&#xff0c;测试&#xff0c;工程等&#xff0c;具有丰富的经验 在配电自动化验收测试以及电科院测试中&#xff0c;本人全程参与&#xff0c;积累了不少现场的经验 ———————————————————…

简单状压dp(以力扣464为例)

目录 1.状态压缩dp是啥&#xff1f; 2.题目分析 3.解题思路 4.算法分析 5.代码分析 6.代码一览 7.结语 1.状态压缩dp是啥&#xff1f; 顾名思义&#xff0c;状态压缩dp就是将原本会超出内存限制的存储改用更加有效的存储方式。简而言之&#xff0c;就是压缩dp的空间。 …

jdk中自带的并发类

1、seamplore 信号量 countDownLaunch&#xff1a;等待所有线程都完成&#xff0c;主线程在执行 CyclicBarrirer 内存屏障 exchanger 线程之间交换数据 phaser 阶段协同器 阻塞队列

AWS-WAF-Log S3存放,通过Athena查看

1.创建好waf-cdn 并且设置好规则和log存储方式为s3 2. Amazon Athena 服务 使用 &#xff08;注意s3桶位置相同得区域&#xff09; https://docs.aws.amazon.com/zh_cn/athena/latest/ug/waf-logs.html#waf-example-count-matched-ip-addresses 官方文档参考,建一个分区查询表…

C. Earning on Bets

题目 个人补充&#xff1a; #include <bits/stdc.h> using namespace std; #define int long long #define pb push_back #define fi first #define se second #define lson p << 1 #define rson p << 1 | 1 #define ll long longconst int maxn 1e6 5, in…

C语言 | Leetcode C语言题解之第228题汇总区间

题目&#xff1a; 题解&#xff1a; char** summaryRanges(int* nums, int numsSize, int* returnSize) {char** ret malloc(sizeof(char*) * numsSize);*returnSize 0;int i 0;while (i < numsSize) {int low i;i;while (i < numsSize && nums[i] nums[i …

算法通关:004_1选择排序

代码一定要自己手敲理解 public class _004 {//选择排序&#xff0c;冒泡排序&#xff0c;插入排序//交换public static void swap(int[] arr,int i ,int j){int temp arr[i];arr[i] arr[j];arr[j] temp;}//选择排序public static void selectSort(int[] arr){if(arr null…

YOLOv10改进 | Conv篇 | 利用FasterBlock二次创新C2f提出一种全新的结构(全网独家首发,参数量下降70W)

一、本文介绍 本文给大家带来的改进机制是利用FasterNet的FasterBlock改进特征提取网络&#xff0c;将其用来改进ResNet网络&#xff0c;其旨在提高计算速度而不牺牲准确性&#xff0c;特别是在视觉任务中。它通过一种称为部分卷积&#xff08;PConv&#xff09;的新技术来减少…

NLP入门——词袋语言模型的搭建、训练与预测

卷积语言模型实际上是取了句子最后ctx_len个词作为上下文输入模型来预测之后的分词。但更好的选择是我们做一个词袋&#xff0c;将所有分词装在词袋中作为上下文&#xff0c;这样预测的分词不只根据最后ctx_len个分词&#xff0c;而是整个词袋中的所有分词。 例如我们的序列是&…

javaweb图书商城系统带万字文档网上书城java项目java课程设计java毕业设计

文章目录 图书商城系统一、项目演示二、项目介绍三、万字项目文档四、部分功能截图五、部分代码展示六、底部获取项目源码带万字文档&#xff08;9.9&#xffe5;带走&#xff09; 图书商城系统 一、项目演示 网上书城 二、项目介绍 语言&#xff1a;java 数据库&#xff1a;…

typora 两边太宽,设置宽度

步骤&#xff1a; 查看目前使用主题类型 文件 —> 偏好设置 —> 外观 —> 打开主题文件夹 修改对应的主题&#xff1a;max-width

MySQL 数据库支持存储emoji表情

当你通过node.js&#xff0c;往mysql存储emoji表情的时候&#xff0c;可能会遇到报错&#xff1a; code: ‘ER_TRUNCATED_WRONG_VALUE_FOR_FIELD’, errno: 1366, sqlMessage: “Incorrect string value: ‘\xF0\x9F\x8D\x94’ for column ‘nick_name’ at row 1”, sqlState…

MySQL数据库主从复制+mycat读写分离+MHA实操

目录 一、主从复制 1.1 主从复制简介 1.2 MySQL支持的复制类型 1.3 主从复制的工作过程 1.4 主从复制的同步模式 1.4.1 异步复制&#xff08;Asynchronous replication&#xff09; 1.4.2 全同步复制&#xff08;Fully synchronous replication&#xff09; 1.4.3 半同…

力扣2356.二维差分模板——子矩阵元素加1

力扣2356.二维差分模板——子矩阵元素加1 模板题 最后将n2*n2的矩阵删去周围一圈变成n*n矩阵的操作 class Solution {public:vector<vector<int>> rangeAddQueries(int n, vector<vector<int>>& queries) {vector<vector<int>> res…

【JavaWeb程序设计】Servlet(二)

目录 一、改进上一篇博客Servlet&#xff08;一&#xff09;的第一题 1. 运行截图 2. 建表 3. 实体类 4. JSP页面 4.1 login.jsp 4.2 loginSuccess.jsp 4.3 loginFail.jsp 5. mybatis-config.xml 6. 工具类&#xff1a;创建SqlSessionFactory实例&#xff0c;进行 My…

UI设计工具选择指南:Sketch、XD、Figma、即时设计

在数字产品设计产业链中&#xff0c;UI设计师往往起着连接前后的作用。产品经理从一个“需求”开始&#xff0c;制定一个抽象的产品概念原型。UI设计师通过视觉呈现将抽象概念具体化&#xff0c;完成线框图交互逻辑视觉用户体验&#xff0c;最终输出高保真原型&#xff0c;并将…

threadx netxduo stm32f407上实现http server

这次用的是CubeIDE CubeMX 要把NX_APP的mem分配的大一些&#xff0c;在app_azure_rtos.c中&#xff0c;我给的是40*1024&#xff0c;如果给的不够&#xff0c;会导致后面无法分配pool和thread等等 需要用到filex 要在CubeMX里面勾选上&#xff0c;还要用到http_server和dhcp …

1. InternLM - 入门岛

第1关 Linux 基础知识 1. 完成SSH连接与端口映射并运行hello_world.py SSH连接配置 # wsl2中生成密钥对&#xff08;~/.ssh/id_rsa, ~/.ssh/id_rsa.pub&#xff09; ssh-keygen -t rsa# 将id_rsa.pub在internStudio作为公钥导入SSH登录 $ ssh -p 38871 rootssh.intern-ai.o…