马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
代码
AP_Arming_Sub.h- #pragma once
- #include <AP_Arming/AP_Arming.h>
- class AP_Arming_Sub : public AP_Arming {
- public:
- AP_Arming_Sub() : AP_Arming() { }
- /* Do not allow copies */
- CLASS_NO_COPY(AP_Arming_Sub);
- bool rc_calibration_checks(bool display_failure) override;
- bool pre_arm_checks(bool display_failure) override;
- bool has_disarm_function() const;
- bool disarm(AP_Arming::Method method, bool do_disarm_checks=true) override;
- bool arm(AP_Arming::Method method, bool do_arming_checks=true) override;
- protected:
- bool ins_checks(bool display_failure) override;
- };
复制代码 AP_Arming_Sub.cpp- #include "AP_Arming_Sub.h"
- #include "Sub.h"
- bool AP_Arming_Sub::rc_calibration_checks(bool display_failure)
- {
- const RC_Channel *channels[] = {
- sub.channel_roll,
- sub.channel_pitch,
- sub.channel_throttle,
- sub.channel_yaw
- };
- return rc_checks_copter_sub(display_failure, channels);
- }
- bool AP_Arming_Sub::has_disarm_function() const {
- bool has_shift_function = false;
- // make sure the craft has a disarm button assigned before it is armed
- // check all the standard btn functions
- for (uint8_t i = 0; i < 16; i++) {
- switch (sub.get_button(i)->function(false)) {
- case JSButton::k_shift :
- has_shift_function = true;
- break;
- case JSButton::k_arm_toggle :
- return true;
- case JSButton::k_disarm :
- return true;
- }
- }
- // check all the shift functions if there's shift assigned
- if (has_shift_function) {
- for (uint8_t i = 0; i < 16; i++) {
- switch (sub.get_button(i)->function(true)) {
- case JSButton::k_arm_toggle :
- case JSButton::k_disarm :
- return true;
- }
- }
- }
- return false;
- }
- bool AP_Arming_Sub::pre_arm_checks(bool display_failure)
- {
- if (armed) {
- return true;
- }
- // don't allow arming unless there is a disarm button configured
- if (!has_disarm_function()) {
- check_failed(display_failure, "Must assign a disarm or arm_toggle button");
- return false;
- }
- return AP_Arming::pre_arm_checks(display_failure);
- }
- bool AP_Arming_Sub::ins_checks(bool display_failure)
- {
- // call parent class checks
- if (!AP_Arming::ins_checks(display_failure)) {
- return false;
- }
- // additional sub-specific checks
- if (check_enabled(ARMING_CHECK_INS)) {
- char failure_msg[50] = {};
- if (!AP::ahrs().pre_arm_check(false, failure_msg, sizeof(failure_msg))) {
- check_failed(ARMING_CHECK_INS, display_failure, "AHRS: %s", failure_msg);
- return false;
- }
- }
- return true;
- }
- bool AP_Arming_Sub::arm(AP_Arming::Method method, bool do_arming_checks)
- {
- static bool in_arm_motors = false;
- // exit immediately if already in this function
- if (in_arm_motors) {
- return false;
- }
- in_arm_motors = true;
- if (!AP_Arming::arm(method, do_arming_checks)) {
- AP_Notify::events.arming_failed = true;
- in_arm_motors = false;
- return false;
- }
- #if HAL_LOGGING_ENABLED
- // let logger know that we're armed (it may open logs e.g.)
- AP::logger().set_vehicle_armed(true);
- #endif
- // disable cpu failsafe because initialising everything takes a while
- sub.mainloop_failsafe_disable();
- // notify that arming will occur (we do this early to give plenty of warning)
- AP_Notify::flags.armed = true;
- // call notify update a few times to ensure the message gets out
- for (uint8_t i=0; i<=10; i++) {
- AP::notify().update();
- }
- #if CONFIG_HAL_BOARD == HAL_BOARD_SITL
- send_arm_disarm_statustext("Arming motors");
- #endif
- AP_AHRS &ahrs = AP::ahrs();
- sub.initial_armed_bearing = ahrs.yaw_sensor;
- if (!ahrs.home_is_set()) {
- // Reset EKF altitude if home hasn't been set yet (we use EKF altitude as substitute for alt above home)
- // Always use absolute altitude for ROV
- // ahrs.resetHeightDatum();
- // AP::logger().Write_Event(LogEvent::EKF_ALT_RESET);
- } else if (!ahrs.home_is_locked()) {
- // Reset home position if it has already been set before (but not locked)
- if (!sub.set_home_to_current_location(false)) {
- // ignore this failure
- }
- }
- hal.util->set_soft_armed(true);
- // enable output to motors
- sub.enable_motor_output();
- // finally actually arm the motors
- sub.motors.armed(true);
- #if HAL_LOGGING_ENABLED
- // log flight mode in case it was changed while vehicle was disarmed
- AP::logger().Write_Mode((uint8_t)sub.control_mode, sub.control_mode_reason);
- #endif
- // reenable failsafe
- sub.mainloop_failsafe_enable();
- // perf monitor ignores delay due to arming
- AP::scheduler().perf_info.ignore_this_loop();
- // flag exiting this function
- in_arm_motors = false;
- // if we do not have an ekf origin then we can't use the WMM tables
- if (!sub.ensure_ekf_origin()) {
- gcs().send_text(MAV_SEVERITY_WARNING, "Compass performance degraded");
- if (check_enabled(ARMING_CHECK_PARAMETERS)) {
- check_failed(ARMING_CHECK_PARAMETERS, true, "No world position, check ORIGIN_* parameters");
- return false;
- }
- }
- // return success
- return true;
- }
- bool AP_Arming_Sub::disarm(const AP_Arming::Method method, bool do_disarm_checks)
- {
- // return immediately if we are already disarmed
- if (!sub.motors.armed()) {
- return false;
- }
- if (!AP_Arming::disarm(method, do_disarm_checks)) {
- return false;
- }
- #if CONFIG_HAL_BOARD == HAL_BOARD_SITL
- send_arm_disarm_statustext("Disarming motors");
- #endif
- auto &ahrs = AP::ahrs();
- // save compass offsets learned by the EKF if enabled
- if (ahrs.use_compass() && AP::compass().get_learn_type() == Compass::LEARN_EKF) {
- for (uint8_t i=0; i<COMPASS_MAX_INSTANCES; i++) {
- Vector3f magOffsets;
- if (ahrs.getMagOffsets(i, magOffsets)) {
- AP::compass().set_and_save_offsets(i, magOffsets);
- }
- }
- }
- // send disarm command to motors
- sub.motors.armed(false);
- // reset the mission
- sub.mission.reset();
- #if HAL_LOGGING_ENABLED
- AP::logger().set_vehicle_armed(false);
- #endif
- hal.util->set_soft_armed(false);
- // clear input holds
- sub.clear_input_hold();
- return true;
- }
复制代码 分析
头文件
.h代码界说了一个名为 AP_Arming_Sub 的 C++ 类,它继续自 AP_Arming 类。此类提供了一个子类化 AP_Arming 的例子,此中添加了一些基类的方法。以下是详细表明:
- #pragma once
是一个预处置处罚器指令,用于防止文件被多次包罗。当编译器看到这个指令时,它会确保该文件在一个编译过程中只被包罗一次,纵然它被多次 #include。
- #include <AP_Arming/AP_Arming.h>
复制代码
- 这行代码包罗了 AP_Arming 类界说的头文件。AP_Arming 是一个库负责处置处罚无人机启动和关闭相干的逻辑。
- class AP_Arming_Sub : public AP_Arming {
复制代码
- 这里界说了一个新的类 AP_Arming_Sub,它继续自 AP_Arming 类。public 关键字表现 AP_Arming 是一个公共基类。
- public:
- AP_Arming_Sub() : AP_Arming() { }
复制代码
- 这部分界说了一个公共构造函数 AP_Arming_Sub。构造函数利用成员初始化列表语法 : AP_Arming() 来调用基类 AP_Arming 的构造函数。
- /* Do not allow copies */
- CLASS_NO_COPY(AP_Arming_Sub);
复制代码
- 这一行是一个表明,阐明确不盼望这个类被复制。固然 CLASS_NO_COPY 宏在这里没有被界说,但它通常用于在类界说中禁用复制构造函数和赋值利用符,以防止类的偶然复制。
- bool rc_calibration_checks(bool display_failure) override;
- bool pre_arm_checks(bool display_failure) override;
- bool has_disarm_function() const;
复制代码
- 这些是 AP_Arming_Sub 类的公共成员函数声明。它们覆盖了基类 AP_Arming 中的虚函数。override 关键字明确表现这些函数是覆盖基类的虚函数。
- rc_calibration_checks:用于实行遥控器校准查抄。
- pre_arm_checks:用于实行武器启动前的查抄。
- has_disarm_function:用于查抄是否解锁。
- bool disarm(AP_Arming::Method method, bool do_disarm_checks=true) override;
- bool arm(AP_Arming::Method method, bool do_arming_checks=true) override;
复制代码
- 这些函数覆盖了基类中的武器排除和武器启动功能,允许子类自界说这些活动。Method 是一个属于 AP_Arming 类的摆列范例,用于指定排除或启动武器的方法。
- protected:
- bool ins_checks(bool display_failure) override;
复制代码
- 这部分声明确一个受掩护的成员函数 ins_checks,它覆盖了基类中的虚函数。protected 关键字表现这个函数是供派生类和基类内部利用的,但不供外部访问。这个函数用于实行惯性导航体系(INS)查抄。
源文件
- #include "AP_Arming_Sub.h"
- #include "Sub.h"
复制代码
- 这两行包罗了须要的头文件,以便编译器知道 AP_Arming_Sub 类和 Sub 类(或结构体)的界说。
- "AP_Arming_Sub.h" 是包罗 AP_Arming_Sub 类声明的头文件。
- "Sub.h" 包罗一个名为 Sub 的类或结构体的界说,这个 Sub 类(以下称为“子类”)代表一个特定的无人机子体系的设置。
AP_Arming_Sub::rc_calibration_checks(bool display_failure)
- bool AP_Arming_Sub::rc_calibration_checks(bool display_failure)
- {
复制代码
- 这里界说了 AP_Arming_Sub 类的 rc_calibration_checks 成员函数。此函数担当一个布尔参数 display_failure,它指示是否应该体现校准失败的信息。
- const RC_Channel *channels[] = {
- sub.channel_roll,
- sub.channel_pitch,
- sub.channel_throttle,
- sub.channel_yaw
- };
复制代码
- 这里界说了一个 RC_Channel 范例的指针数组 channels,它包罗指向四个差别通道的指针。这些通道通常代表多旋翼或无人机的遥控器控制通道:
- channel_roll:横滚通道,控制无人机左右倾斜。
- channel_pitch:俯仰通道,控制无人机前后倾斜。
- channel_throttle:油门通道,控制无人机的升力。
- channel_yaw:偏航通道,控制无人机的旋转方向。
- sub 是一个 Sub 范例的对象,它包罗了这些通道的引用或指针。
- return rc_checks_copter_sub(display_failure, channels);
- }
复制代码
- 这行代码调用了 rc_checks_copter_sub 函数(这个函数大概在当前文件或其他文件中界说),并将 display_failure 和 channels 数组作为参数通报。这个函数的目的是实行详细的遥控器校准查抄,并返回一个布尔值,指示查抄是否通过。
- 返回值会被通报回调用 rc_calibration_checks 的地方,指示校准查抄是否乐成。
AP_Arming_Sub::has_disarm_function() const
- bool AP_Arming_Sub::has_disarm_function() const {
复制代码
- has_disarm_function 是 AP_Arming_Sub 类的一个 const 成员函数,这意味着它不会修改类的任何成员变量。const 关键字用在成员函数的声明和界说中,以确保函数调用不会改变对象的状态。
- bool has_shift_function = false;
复制代码
- 界说一个布尔变量 has_shift_function,用于跟踪是否存在“shift”功能按钮。
- // make sure the craft has a disarm button assigned before it is armed
- // check all the standard btn functions
- for (uint8_t i = 0; i < 16; i++) {
- switch (sub.get_button(i)->function(false)) {
- case JSButton::k_shift :
- has_shift_function = true;
- break;
- case JSButton::k_arm_toggle :
- return true;
- case JSButton::k_disarm :
- return true;
- }
- }
复制代码
- 这段代码遍历前16个按钮(假设装备有16个按钮),查抄每个按钮的尺度功能(非“shift”功能)。
- sub.get_button(i) 获取第 i 个按钮对象的指针。
- function(false) 调用按钮对象的 function 方法,通报 false 表现不查抄“shift”功能。
- 假如按钮的功能是 JSButton::k_shift,则设置 has_shift_function 为 true。
- 假如按钮的功能是 JSButton::k_arm_toggle 或 JSButton::k_disarm,则直接返回 true,由于这表现存在排除武器功能。
- // check all the shift functions if there's shift assigned
- if (has_shift_function) {
- for (uint8_t i = 0; i < 16; i++) {
- switch (sub.get_button(i)->function(true)) {
- case JSButton::k_arm_toggle :
- case JSButton::k_disarm :
- return true;
- }
- }
- }
复制代码
- 假如检测到有 shift 功能按钮,则再次遍历全部按钮,这次查抄它们的“shift”功能。
- function(true)这次通报 true 来查抄按钮的“shift”功能。
- 假如任何一个按钮的“shift”功能是 JSButton::k_arm_toggle 或 JSButton::k_disarm,则返回 true。
- 假如遍历全部按钮后没有找到排除武器功能,则返回 false。
AP_Arming_Sub::pre_arm_checks(bool display_failure)
- bool AP_Arming_Sub::pre_arm_checks(bool display_failure)
复制代码
- bool: 表现这个函数返回一个布尔范例的值,即true或false。
- AP_Arming_Sub::: 指定pre_arm_checks函数是AP_Arming_Sub类的成员函数。
- pre_arm_checks: 函数名,意味着实行预启动查抄。
- (bool display_failure): 函数汲取一个名为display_failure的布尔型参数,这个参数用来决定是否体现查抄失败的信息。
- {
- if (armed) {
- return true;
- }
复制代码
- 这段代码查抄一个名为armed的变量(一个成员变量,表现体系是否已经启动)。
- 假如体系已经启动(armed为true),则函数直接返回true,不须要举行进一步的查抄。
- // don't allow arming unless there is a disarm button configured
- if (!has_disarm_function()) {
- check_failed(display_failure, "Must assign a disarm or arm_toggle button");
- return false;
- }
复制代码
- 这部分代码查抄是否存在一个设置好的解锁按钮。
- !has_disarm_function(): 假如has_disarm_function()函数返回false(表现没有设置解锁按钮),则实行以下代码。
- check_failed(display_failure, "Must assign a disarm or arm_toggle button"): 调用一个名为check_failed的函数,它用来记载错误信息或体现错误消息。通报的字符串阐明确错误的缘故因由。
- return false;: 假如没有设置解锁按钮,则返回false,表现预查抄失败。
- return AP_Arming::pre_arm_checks(display_failure);
- }
复制代码
- 这行代码调用基类AP_Arming的pre_arm_checks函数,继续实行进一步的预启动查抄。
- 假如这个基类的预查抄也返回true,则整个pre_arm_checks函数返回true,否则返回false。
AP_Arming_Sub::ins_checks(bool display_failure)
- bool AP_Arming_Sub::ins_checks(bool display_failure)
复制代码
- bool: 表现这个函数返回一个布尔范例的值,即true或false。
- AP_Arming_Sub::: 指定ins_checks函数是AP_Arming_Sub类的成员函数。
- ins_checks: 函数名,意味着实行与INS相干的预启动查抄。
- (bool display_failure): 函数汲取一个名为display_failure的布尔型参数,用来决定是否体现查抄失败的信息。
- {
- // call parent class checks
- if (!AP_Arming::ins_checks(display_failure)) {
- return false;
- }
复制代码
- 这段代码调用基类AP_Arming的ins_checks函数,实行与INS相干的通用预启动查抄。
- 假如基类的查抄返回false,表现查抄失败,那么这个函数也立刻返回false。
- // additional sub-specific checks
- if (check_enabled(ARMING_CHECK_INS)) {
复制代码
- 这段代码查抄是否启用了特定的查抄项ARMING_CHECK_INS。check_enabled根据传入的参数来确定是否实行后续的查抄。
- char failure_msg[50] = {};
- if (!AP::ahrs().pre_arm_check(false, failure_msg, sizeof(failure_msg))) {
- check_failed(ARMING_CHECK_INS, display_failure, "AHRS: %s", failure_msg);
- return false;
- }
- }
复制代码
- char failure_msg[50] = {};: 界说一个字符数组failure_msg,用来存储大概的错误信息,巨细为50个字符。
- AP::ahrs().pre_arm_check(false, failure_msg, sizeof(failure_msg)): 调用AP::ahrs()对象的pre_arm_check方法。AP::ahrs()返回一个AHRS(Attitude and Heading Reference System)类的实例。pre_arm_check方法实行与AHRS相干的查抄,假如查抄失败,它将错误信息写入failure_msg数组,并返回false。
- 假如pre_arm_check返回false,则实行以下代码:
- check_failed(ARMING_CHECK_INS, display_failure, "AHRS: %s", failure_msg);: 调用check_failed函数,它用于记载错误信息或体现错误消息。它汲取查抄项标识符ARMING_CHECK_INS,是否体现失败的标记display_failure,以合格式化的错误信息字符串,此中%s将被failure_msg中的内容更换。
- return false;: 假如查抄失败,则返回false。
AP_Arming_Sub::arm(AP_Arming::Method method, bool do_arming_checks)
- bool AP_Arming_Sub::arm(AP_Arming::Method method, bool do_arming_checks)
- {
- static bool in_arm_motors = false;
复制代码
- 声明一个静态布尔变量in_arm_motors,用于防止函数重入。
- // exit immediately if already in this function
- if (in_arm_motors) {
- return false;
- }
复制代码
- 假如in_arm_motors为true,表现函数已经在实行中,为了制止重入,直接返回false。
- 设置in_arm_motors为true,表现当前正在实行启动过程。
- if (!AP_Arming::arm(method, do_arming_checks)) {
- AP_Notify::events.arming_failed = true;
- in_arm_motors = false;
- return false;
- }
复制代码
- 调用基类AP_Arming的arm方法实验启动。假如返回false,表现启动失败,设置关照变乱,重置in_arm_motors,并返回false。
- #if HAL_LOGGING_ENABLED
- // let logger know that we're armed (it may open logs e.g.)
- AP::logger().set_vehicle_armed(true);
- #endif
复制代码
- 假如启用了日志
记载功能,关照日志 体系车辆已启动。
- // disable cpu failsafe because initialising everything takes a while
- sub.mainloop_failsafe_disable();
复制代码
- 禁用主循环故障安全,由于在初始化过程中大概会有较长时间的耽误。
- // notify that arming will occur (we do this early to give plenty of warning)
- AP_Notify::flags.armed = true;
- // call notify update a few times to ensure the message gets out
- for (uint8_t i=0; i<=10; i++) {
- AP::notify().update();
- }
复制代码
- 设置关照标记表明车辆将要启动,并通过多次调用更新函数确保关照消息被发送。
- #if CONFIG_HAL_BOARD == HAL_BOARD_SITL
- send_arm_disarm_statustext("Arming motors");
- #endif
复制代码
- 假如设置为SITL(软件在环仿真),发送状态文本消息表明正在启动电机。
- AP_AHRS &ahrs = AP::ahrs();
复制代码- sub.initial_armed_bearing = ahrs.yaw_sensor;
复制代码- if (!ahrs.home_is_set()) {
- // Reset EKF altitude if home hasn't been set yet (we use EKF altitude as substitute for alt above home)
- // Always use absolute altitude for ROV
- // ahrs.resetHeightDatum();
- // AP::logger().Write_Event(LogEvent::EKF_ALT_RESET);
- } else if (!ahrs.home_is_locked()) {
- // Reset home position if it has already been set before (but not locked)
- if (!sub.set_home_to_current_location(false)) {
- // ignore this failure
- }
- }
复制代码
- 假如家位置未设置,则重置EKF高度;假如家位置未锁定,则重置为当前位置。
- hal.util->set_soft_armed(true);
复制代码- // enable output to motors
- sub.enable_motor_output();
复制代码- // finally actually arm the motors
- sub.motors.armed(true);
复制代码- #if HAL_LOGGING_ENABLED
- // log flight mode in case it was changed while vehicle was disarmed
- AP::logger().Write_Mode((uint8_t)sub.control_mode, sub.control_mode_reason);
- #endif
复制代码
- 假如启用了日志
记载,记载当前的飞行模式。
- // reenable failsafe
- sub.mainloop_failsafe_enable();
复制代码- // perf monitor ignores delay due to arming
- AP::scheduler().perf_info.ignore_this_loop();
复制代码- // flag exiting this function
- in_arm_motors = false;
复制代码
- 标记退出此函数,将in_arm_motors重置为false。
- // if we do not have an ekf origin then we can't use the WMM tables
- if (!sub.ensure_ekf_origin()) {
- gcs().send_text(MAV_SEVERITY_WARNING, "Compass performance degraded");
- if (check_enabled(ARMING_CHECK_PARAMETERS)) {
- check_failed(ARMING_CHECK_PARAMETERS, true, "No world position, check ORIGIN_* parameters");
- return false;
- }
- }
复制代码
- 假如EKF原点未设置,则发送告诫并查抄是否启用了参数查抄。假如启用了,则记载失败并返回false。
- // return success return true;
- }
复制代码 AP_Arming_Sub::disarm(const AP_Arming::Method method, bool do_disarm_checks)
- bool AP_Arming_Sub::disarm(const AP_Arming::Method method, bool do_disarm_checks)
- {
复制代码
- 声明一个返回布尔值的函数disarm,它汲取两个参数:解锁方法method和一个布尔值do_disarm_checks,后者指定是否实行解锁前的查抄。
- // return immediately if we are already disarmed
- if (!sub.motors.armed()) {
- return false;
- }
复制代码
- 假如电机已经处于未启动状态(即已解锁),则立刻返回false。
- if (!AP_Arming::disarm(method, do_disarm_checks)) {
- return false;
- }
复制代码
- 调用基类AP_Arming的disarm方法实验解锁。假如返回false,表现解锁失败,因此直接返回false。
- #if CONFIG_HAL_BOARD == HAL_BOARD_SITL
- send_arm_disarm_statustext("Disarming motors");
- #endif
复制代码
- 假如设置为SITL(软件在环仿真),发送状态文本消息表明正在解锁电机。
- // save compass offsets learned by the EKF if enabled
- if (ahrs.use_compass() && AP::compass().get_learn_type() == Compass::LEARN_EKF) {
- for (uint8_t i=0; i<COMPASS_MAX_INSTANCES; i++) {
- Vector3f magOffsets;
- if (ahrs.getMagOffsets(i, magOffsets)) {
- AP::compass().set_and_save_offsets(i, magOffsets);
- }
- }
- }
复制代码
- 假如启用了指南针,而且EKF学习了指南针偏移量,则生存这些偏移量。
- // send disarm command to motors
- sub.motors.armed(false);
复制代码- // reset the mission
- sub.mission.reset();
复制代码- #if HAL_LOGGING_ENABLED
- AP::logger().set_vehicle_armed(false);
- #endif
复制代码- hal.util->set_soft_armed(false);
复制代码- // clear input holds
- sub.clear_input_hold();
复制代码
- 扫除输入保持状态,这大概是为了确保在解锁后不会有任何悬挂的输入下令影响体系。
|