分享

PX4代码分析-(二)commander代码分析_px4 actuator_command___Vincent

 netouch 2023-09-03 发布于北京

一、commander的作用

commander相当于整个px4功能的入口, 该模块主要负责对地面站、遥控器以及其它模块发布的cmd命令的处理,还包括设置飞行模式、设置起飞点位置、解锁检测、失控检测、落地检测等功能的处理。

1、遥控器发送了切换land指令,首先是在driver中根据配置的通道信息解析了遥控器的指令并判断是land的指令,driver会生成一条VEHICLE_CMD_NAV_LAND的指令。commander模块接收到该指令后,首先会判断是否具备切换的条件,如果当前状态不能切换到该模式,则拒绝。如果可以,则发出相关的uorb,在navigator模块中进行飞行模式的切换。

2、在收到qgc发送的传感器校准指令时,会切换到校准函数,对陀螺仪、加速度计等传感器进行校准。

3、在处理其他模块发送的信息,如落地检测检测模块检测到已经落地,则commander模块中根据配置的参数进行自动上锁等动作。

二、commandor的思维导图

三、代码结构分析

1、代码位置:commander位于Firmware/src/modules/commander文件夹中。

2、构造函数:

在构造函数中,主要是读取设定的各种参数,然后初始化无人机的状态参数(_vehicle_status),其中包含了机架类型等参数。

3、由头文件commander.hpp可知,class Commander : public ModuleBase<Commander>, public ModuleParams 所以类Commander是继承了ModuleBase类,所以Commander类中的run()函数是该类的主要的执行函数,所以接来下主要分析该函数。

  1. Commander::run()
  2. {
  3. bool sensor_fail_tune_played = false;
  4. const param_t param_airmode = param_find("MC_AIRMODE");//获取对应的参数
  5. const param_t param_rc_map_arm_switch = param_find("RC_MAP_ARM_SW");
  6. /* initialize */
  7. led_init();//led灯初始化,在boards/px4/对应的飞控文件中实现,主要是完成对应的gpio口的初始化
  8. buzzer_init();//蜂鸣器初始化,跟led一样
  9. #if defined(BOARD_HAS_POWER_CONTROL)
  10. {
  11. // we need to do an initial publication to make sure uORB allocates the buffer, which cannot happen
  12. // in IRQ context.
  13. power_button_state_s button_state{};
  14. button_state.timestamp = hrt_absolute_time();
  15. button_state.event = 0xff;
  16. power_button_state_pub = orb_advertise(ORB_ID(power_button_state), &button_state);
  17. _power_button_state_sub.copy(&button_state);
  18. }
  19. if (board_register_power_state_notification_cb(power_button_state_notification_cb) != 0) {
  20. PX4_ERR("Failed to register power notification callback");
  21. }
  22. #endif // BOARD_HAS_POWER_CONTROL
  23. get_circuit_breaker_params();//获取对应的参数
  24. /* init mission state, do it here to allow navigator to use stored mission even if mavlink failed to start */
  25. //初始化任务mission的状态,在mavlink启动失败是,允许navigator导航使用存储的mission数据(mission都是存在sd卡中,通过dm_read()函数来读取)
  26. mission_init();
  27. bool param_init_forced = true;
  28. control_status_leds(&status, &armed, true, _battery_warning);//设置状态灯的状态
  29. thread_running = true;
  30. /* update vehicle status to find out vehicle type (required for preflight checks) */
  31. status.system_type = _param_mav_type.get();
  32. //判断无人机的类型
  33. if (is_rotary_wing(&status) || is_vtol(&status)) {
  34. status.vehicle_type = vehicle_status_s::VEHICLE_TYPE_ROTARY_WING;
  35. } else if (is_fixed_wing(&status)) {
  36. status.vehicle_type = vehicle_status_s::VEHICLE_TYPE_FIXED_WING;
  37. } else if (is_ground_rover(&status)) {
  38. status.vehicle_type = vehicle_status_s::VEHICLE_TYPE_ROVER;
  39. } else {
  40. status.vehicle_type = vehicle_status_s::VEHICLE_TYPE_UNKNOWN;
  41. }
  42. //根据status判断是否是垂直起降固定翼
  43. status.is_vtol = is_vtol(&status);
  44. status.is_vtol_tailsitter = is_vtol_tailsitter(&status);
  45. _boot_timestamp = hrt_absolute_time();
  46. // initially set to failed
  47. _last_lpos_fail_time_us = _boot_timestamp;
  48. _last_gpos_fail_time_us = _boot_timestamp;
  49. _last_lvel_fail_time_us = _boot_timestamp;
  50. // user adjustable duration required to assert arm/disarm via throttle/rudder stick
  51. //用户可调整的持续时间,以通过油门/方向舵杆进行防护/解除防护,就是设置通过油门解锁/上锁需要的时间
  52. uint32_t rc_arm_hyst = _param_rc_arm_hyst.get() * COMMANDER_MONITORING_LOOPSPERMSEC;
  53. int32_t airmode = 0;
  54. int32_t rc_map_arm_switch = 0;
  55. //为创建低优先级的线程初始化好运行环境
  56. /* initialize low priority thread */
  57. pthread_attr_t commander_low_prio_attr;
  58. pthread_attr_init(&commander_low_prio_attr);
  59. pthread_attr_setstacksize(&commander_low_prio_attr, PX4_STACK_ADJUSTED(3304));
  60. #ifndef __PX4_QURT
  61. // This is not supported by QURT (yet).
  62. struct sched_param param;
  63. pthread_attr_getschedparam(&commander_low_prio_attr, &param);
  64. /* low priority */
  65. param.sched_priority = SCHED_PRIORITY_DEFAULT - 50;
  66. pthread_attr_setschedparam(&commander_low_prio_attr, &param);
  67. #endif
  68. pthread_t commander_low_prio_thread;
  69. pthread_create(&commander_low_prio_thread, &commander_low_prio_attr, commander_low_prio_loop, nullptr);//创建新的线程,也就是会有两个线程在执行
  70. pthread_attr_destroy(&commander_low_prio_attr);
  71. status.system_id = _param_mav_sys_id.get();
  72. arm_auth_init(&mavlink_log_pub, &status.system_id);
  73. // run preflight immediately to find all relevant parameters, but don't report
  74. //立即运行飞行前检查以查找所有相关参数,但不要报告
  75. PreFlightCheck::preflightCheck(&mavlink_log_pub, status, status_flags, _arm_requirements.global_position, false, true,
  76. hrt_elapsed_time(&_boot_timestamp));
  77. //各种初始化完成后进入循环,执行主要的程序
  78. while (!should_exit()) {
  79. transition_result_t arming_ret = TRANSITION_NOT_CHANGED;
  80. /* update parameters */
  81. //更新需要的参数
  82. bool params_updated = _parameter_update_sub.updated();
  83. //如果参数更新了,会执行下面程序
  84. if (params_updated || param_init_forced) {
  85. // clear update
  86. parameter_update_s update;
  87. _parameter_update_sub.copy(&update);
  88. // update parameters from storage
  89. updateParams();
  90. // NAV_DLL_ACT value 4 Data Link Auto Recovery (CASA Outback Challenge rules) deleted 2020-03-10
  91. if (_param_nav_dll_act.get() == 4) {
  92. mavlink_log_critical(&mavlink_log_pub, "CASA Outback Challenge rules (NAV_DLL_ACT = 4) retired");
  93. _param_nav_dll_act.set(2); // value 2 Return mode
  94. _param_nav_dll_act.commit_no_notification();
  95. }
  96. // NAV_RCL_ACT value 4 RC Auto Recovery (CASA Outback Challenge rules) deleted 2020-03-10
  97. if (_param_nav_rcl_act.get() == 4) {
  98. mavlink_log_critical(&mavlink_log_pub, "CASA Outback Challenge rules (NAV_RCL_ACT = 4) retired");
  99. _param_nav_rcl_act.set(2); // value 2 Return mode
  100. _param_nav_rcl_act.commit_no_notification();
  101. }
  102. /* update parameters */
  103. if (!armed.armed) {//如果没有解锁,则执行下面程序
  104. status.system_type = _param_mav_type.get();
  105. const bool is_rotary = is_rotary_wing(&status) || (is_vtol(&status) && _vtol_status.vtol_in_rw_mode);
  106. const bool is_fixed = is_fixed_wing(&status) || (is_vtol(&status) && !_vtol_status.vtol_in_rw_mode);
  107. const bool is_ground = is_ground_rover(&status);
  108. /* disable manual override for all systems that rely on electronic stabilization */
  109. if (is_rotary) {
  110. status.vehicle_type = vehicle_status_s::VEHICLE_TYPE_ROTARY_WING;
  111. } else if (is_fixed) {
  112. status.vehicle_type = vehicle_status_s::VEHICLE_TYPE_FIXED_WING;
  113. } else if (is_ground) {
  114. status.vehicle_type = vehicle_status_s::VEHICLE_TYPE_ROVER;
  115. }
  116. /* set vehicle_status.is_vtol flag */
  117. status.is_vtol = is_vtol(&status);
  118. status.is_vtol_tailsitter = is_vtol_tailsitter(&status);
  119. /* check and update system / component ID */
  120. status.system_id = _param_mav_sys_id.get();
  121. status.component_id = _param_mav_comp_id.get();
  122. get_circuit_breaker_params();
  123. _status_changed = true;
  124. }
  125. status_flags.avoidance_system_required = _param_com_obs_avoid.get();
  126. status.rc_input_mode = _param_rc_in_off.get();//通过参数获取遥控的输入模式
  127. // percentage (* 0.01) needs to be doubled because RC total interval is 2, not 1
  128. _min_stick_change = _param_min_stick_change.get() * 0.02f;
  129. rc_arm_hyst = _param_rc_arm_hyst.get() * COMMANDER_MONITORING_LOOPSPERMSEC;
  130. //通过参数配置解锁所需要的条件
  131. _arm_requirements.arm_authorization = _param_arm_auth_required.get();
  132. _arm_requirements.esc_check = _param_escs_checks_required.get();
  133. _arm_requirements.global_position = !_param_arm_without_gps.get();
  134. _arm_requirements.mission = _param_arm_mission_required.get();
  135. /* flight mode slots */
  136. //配置6种飞行模式
  137. _flight_mode_slots[0] = _param_fltmode_1.get();
  138. _flight_mode_slots[1] = _param_fltmode_2.get();
  139. _flight_mode_slots[2] = _param_fltmode_3.get();
  140. _flight_mode_slots[3] = _param_fltmode_4.get();
  141. _flight_mode_slots[4] = _param_fltmode_5.get();
  142. _flight_mode_slots[5] = _param_fltmode_6.get();
  143. _auto_disarm_killed.set_hysteresis_time_from(false, _param_com_kill_disarm.get() * 1_s);
  144. /* check for unsafe Airmode settings: yaw airmode requires the use of an arming switch */
  145. if (param_airmode != PARAM_INVALID && param_rc_map_arm_switch != PARAM_INVALID) {
  146. param_get(param_airmode, &airmode);
  147. param_get(param_rc_map_arm_switch, &rc_map_arm_switch);
  148. if (airmode == 2 && rc_map_arm_switch == 0) {
  149. airmode = 1; // change to roll/pitch airmode
  150. param_set(param_airmode, &airmode);
  151. mavlink_log_critical(&mavlink_log_pub, "Yaw Airmode requires the use of an Arm Switch")
  152. }
  153. }
  154. _offboard_available.set_hysteresis_time_from(true, _param_com_of_loss_t.get());
  155. param_init_forced = false;
  156. }
  157. /* Update OA parameter */
  158. status_flags.avoidance_system_required = _param_com_obs_avoid.get();
  159. #if defined(BOARD_HAS_POWER_CONTROL)
  160. /* handle power button state */
  161. if (_power_button_state_sub.updated()) {
  162. power_button_state_s button_state;
  163. if (_power_button_state_sub.copy(&button_state)) {
  164. if (button_state.event == power_button_state_s::PWR_BUTTON_STATE_REQUEST_SHUTDOWN) {
  165. #if defined(CONFIG_BOARDCTL_POWEROFF)
  166. if (shutdown_if_allowed() && (px4_shutdown_request() == 0)) {
  167. while (1) { px4_usleep(1); }
  168. }
  169. #endif // CONFIG_BOARDCTL_POWEROFF
  170. }
  171. }
  172. }
  173. #endif // BOARD_HAS_POWER_CONTROL
  174. //这个应该是offboard模式控制相关的设置,待分析
  175. offboard_control_update();
  176. //下面是对供电的检查,如果通过usb供电,就不会解锁
  177. if (_system_power_sub.updated()) {
  178. system_power_s system_power{};
  179. _system_power_sub.copy(&system_power);
  180. if (hrt_elapsed_time(&system_power.timestamp) < 1_s) {
  181. if (system_power.servo_valid &&
  182. !system_power.brick_valid &&
  183. !system_power.usb_connected) {
  184. /* flying only on servo rail, this is unsafe */
  185. status_flags.condition_power_input_valid = false;
  186. } else {
  187. status_flags.condition_power_input_valid = true;
  188. }
  189. #if defined(CONFIG_BOARDCTL_RESET)
  190. if (!status_flags.circuit_breaker_engaged_usb_check && status_flags.usb_connected) {
  191. /* if the USB hardware connection went away, reboot */
  192. if (_system_power_usb_connected && !system_power.usb_connected) {
  193. /*
  194. * Apparently the USB cable went away but we are still powered,
  195. * so we bring the system back to a nominal state for flight.
  196. * This is important to unload the USB stack of the OS which is
  197. * a relatively complex piece of software that is non-essential
  198. * for flight and continuing to run it would add a software risk
  199. * without a need. The clean approach to unload it is to reboot.
  200. */
  201. if (shutdown_if_allowed() && (px4_reboot_request(false, 400_ms) == 0)) {
  202. mavlink_log_critical(&mavlink_log_pub, "USB disconnected, rebooting for flight safety");
  203. while (1) { px4_usleep(1); }
  204. }
  205. }
  206. }
  207. #endif // CONFIG_BOARDCTL_RESET
  208. _system_power_usb_connected = system_power.usb_connected;
  209. }
  210. }
  211. /* update safety topic */
  212. //更新有关安全开关
  213. if (_safety_sub.updated()) {
  214. const bool previous_safety_off = _safety.safety_off;
  215. if (_safety_sub.copy(&_safety)) {
  216. // disarm if safety is now on and still armed
  217. if (armed.armed && _safety.safety_switch_available && !_safety.safety_off) {
  218. bool safety_disarm_allowed = (status.hil_state == vehicle_status_s::HIL_STATE_OFF);
  219. // if land detector is available then prevent disarming via safety button if not landed
  220. if (hrt_elapsed_time(&_land_detector.timestamp) < 1_s) {
  221. bool maybe_landing = (_land_detector.landed || _land_detector.maybe_landed);
  222. if (!maybe_landing) {
  223. safety_disarm_allowed = false;
  224. }
  225. }
  226. if (safety_disarm_allowed) {
  227. if (TRANSITION_CHANGED == arm_disarm(false, true, &mavlink_log_pub, arm_disarm_reason_t::SAFETY_BUTTON)) {
  228. _status_changed = true;
  229. }
  230. }
  231. }
  232. // Notify the user if the status of the safety switch changes
  233. if (_safety.safety_switch_available && previous_safety_off != _safety.safety_off) {
  234. if (_safety.safety_off) {
  235. set_tune(TONE_NOTIFY_POSITIVE_TUNE);
  236. } else {
  237. tune_neutral(true);
  238. }
  239. _status_changed = true;
  240. }
  241. }
  242. }
  243. /* update vtol vehicle status*/
  244. //更新垂直起降固定翼的状态
  245. if (_vtol_vehicle_status_sub.updated()) {
  246. /* vtol status changed */
  247. _vtol_vehicle_status_sub.copy(&_vtol_status);
  248. status.vtol_fw_permanent_stab = _vtol_status.fw_permanent_stab;
  249. /* Make sure that this is only adjusted if vehicle really is of type vtol */
  250. if (is_vtol(&status)) {
  251. // Check if there has been any change while updating the flags
  252. const auto new_vehicle_type = _vtol_status.vtol_in_rw_mode ?
  253. vehicle_status_s::VEHICLE_TYPE_ROTARY_WING :
  254. vehicle_status_s::VEHICLE_TYPE_FIXED_WING;
  255. if (new_vehicle_type != status.vehicle_type) {
  256. status.vehicle_type = _vtol_status.vtol_in_rw_mode ?
  257. vehicle_status_s::VEHICLE_TYPE_ROTARY_WING :
  258. vehicle_status_s::VEHICLE_TYPE_FIXED_WING;
  259. _status_changed = true;
  260. }
  261. if (status.in_transition_mode != _vtol_status.vtol_in_trans_mode) {
  262. status.in_transition_mode = _vtol_status.vtol_in_trans_mode;
  263. _status_changed = true;
  264. }
  265. if (status.in_transition_to_fw != _vtol_status.in_transition_to_fw) {
  266. status.in_transition_to_fw = _vtol_status.in_transition_to_fw;
  267. _status_changed = true;
  268. }
  269. if (status_flags.vtol_transition_failure != _vtol_status.vtol_transition_failsafe) {
  270. status_flags.vtol_transition_failure = _vtol_status.vtol_transition_failsafe;
  271. _status_changed = true;
  272. }
  273. const bool should_soft_stop = (status.vehicle_type != vehicle_status_s::VEHICLE_TYPE_ROTARY_WING);
  274. if (armed.soft_stop != should_soft_stop) {
  275. armed.soft_stop = should_soft_stop;
  276. _status_changed = true;
  277. }
  278. }
  279. }
  280. //电调状态检查
  281. if (_esc_status_sub.updated()) {
  282. /* ESCs status changed */
  283. esc_status_s esc_status{};
  284. if (_esc_status_sub.copy(&esc_status)) {
  285. esc_status_check(esc_status);
  286. }
  287. }
  288. //检查位置估计和状态估计是否正常
  289. estimator_check(status_flags);
  290. /* Update land detector */
  291. //落地检查
  292. if (_land_detector_sub.updated()) {
  293. _was_landed = _land_detector.landed;
  294. _land_detector_sub.copy(&_land_detector);
  295. // Only take actions if armed
  296. if (armed.armed) {
  297. if (_was_landed != _land_detector.landed) {
  298. if (_land_detector.landed) {
  299. mavlink_log_info(&mavlink_log_pub, "Landing detected");
  300. } else {
  301. mavlink_log_info(&mavlink_log_pub, "Takeoff detected");
  302. _have_taken_off_since_arming = true;
  303. // Set all position and velocity test probation durations to takeoff value
  304. // This is a larger value to give the vehicle time to complete a failsafe landing
  305. // if faulty sensors cause loss of navigation shortly after takeoff.
  306. _gpos_probation_time_us = _param_com_pos_fs_prob.get() * 1_s;
  307. _lpos_probation_time_us = _param_com_pos_fs_prob.get() * 1_s;
  308. _lvel_probation_time_us = _param_com_pos_fs_prob.get() * 1_s;
  309. }
  310. }
  311. }
  312. }
  313. // Auto disarm when landed or kill switch engaged
  314. //当落地或者停止开关接通时自动上锁
  315. if (armed.armed) {
  316. // Check for auto-disarm on landing or pre-flight
  317. if (_param_com_disarm_land.get() > 0 || _param_com_disarm_preflight.get() > 0) {
  318. if (_param_com_disarm_land.get() > 0 && _have_taken_off_since_arming) {
  319. _auto_disarm_landed.set_hysteresis_time_from(false, _param_com_disarm_land.get() * 1_s);
  320. _auto_disarm_landed.set_state_and_update(_land_detector.landed, hrt_absolute_time());
  321. } else if (_param_com_disarm_preflight.get() > 0 && !_have_taken_off_since_arming) {
  322. _auto_disarm_landed.set_hysteresis_time_from(false, _param_com_disarm_preflight.get() * 1_s);
  323. _auto_disarm_landed.set_state_and_update(true, hrt_absolute_time());
  324. }
  325. if (_auto_disarm_landed.get_state()) {
  326. arm_disarm(false, true, &mavlink_log_pub,
  327. (_have_taken_off_since_arming ? arm_disarm_reason_t::AUTO_DISARM_LAND : arm_disarm_reason_t::AUTO_DISARM_PREFLIGHT));
  328. }
  329. }
  330. // Auto disarm after 5 seconds if kill switch is engaged
  331. _auto_disarm_killed.set_state_and_update(armed.manual_lockdown || armed.lockdown, hrt_absolute_time());
  332. if (_auto_disarm_killed.get_state()) {
  333. if (armed.manual_lockdown) {
  334. arm_disarm(false, true, &mavlink_log_pub, arm_disarm_reason_t::KILL_SWITCH);
  335. } else {
  336. arm_disarm(false, true, &mavlink_log_pub, arm_disarm_reason_t::LOCKDOWN);
  337. }
  338. }
  339. } else {
  340. _auto_disarm_landed.set_state_and_update(false, hrt_absolute_time());
  341. _auto_disarm_killed.set_state_and_update(false, hrt_absolute_time());
  342. }
  343. if (_geofence_warning_action_on
  344. && _internal_state.main_state != commander_state_s::MAIN_STATE_AUTO_RTL
  345. && _internal_state.main_state != commander_state_s::MAIN_STATE_AUTO_LOITER
  346. && _internal_state.main_state != commander_state_s::MAIN_STATE_AUTO_LAND) {
  347. // reset flag again when we switched out of it
  348. _geofence_warning_action_on = false;
  349. }
  350. _cpuload_sub.update(&_cpuload);
  351. //电池状态检查,包括在低电量时自动切换飞行模式
  352. battery_status_check();
  353. /* update subsystem info which arrives from outside of commander*/
  354. //更新来自commander外部的子系统信息
  355. subsystem_info_s info;
  356. while (_subsys_sub.update(&info)) {
  357. set_health_flags(info.subsystem_type, info.present, info.enabled, info.ok, status);
  358. _status_changed = true;
  359. }
  360. /* If in INIT state, try to proceed to STANDBY state */
  361. if (!status_flags.condition_calibration_enabled && status.arming_state == vehicle_status_s::ARMING_STATE_INIT) {
  362. arming_ret = arming_state_transition(&status, _safety, vehicle_status_s::ARMING_STATE_STANDBY, &armed,
  363. true /* fRunPreArmChecks */, &mavlink_log_pub, &status_flags,
  364. _arm_requirements, hrt_elapsed_time(&_boot_timestamp),
  365. arm_disarm_reason_t::TRANSITION_TO_STANDBY);
  366. if (arming_ret == TRANSITION_DENIED) {
  367. /* do not complain if not allowed into standby */
  368. arming_ret = TRANSITION_NOT_CHANGED;
  369. }
  370. }
  371. /* start mission result check */
  372. const auto prev_mission_instance_count = _mission_result_sub.get().instance_count;
  373. //检查任务结果
  374. if (_mission_result_sub.update()) {
  375. const mission_result_s &mission_result = _mission_result_sub.get();
  376. // if mission_result is valid for the current mission
  377. const bool mission_result_ok = (mission_result.timestamp > _boot_timestamp)
  378. && (mission_result.instance_count > 0);
  379. status_flags.condition_auto_mission_available = mission_result_ok && mission_result.valid;
  380. if (mission_result_ok) {
  381. if (status.mission_failure != mission_result.failure) {
  382. status.mission_failure = mission_result.failure;
  383. _status_changed = true;
  384. if (status.mission_failure) {
  385. mavlink_log_critical(&mavlink_log_pub, "Mission cannot be completed");
  386. }
  387. }
  388. /* Only evaluate mission state if home is set */
  389. if (status_flags.condition_home_position_valid &&
  390. (prev_mission_instance_count != mission_result.instance_count)) {
  391. if (!status_flags.condition_auto_mission_available) {
  392. /* the mission is invalid */
  393. tune_mission_fail(true);
  394. } else if (mission_result.warning) {
  395. /* the mission has a warning */
  396. tune_mission_fail(true);
  397. } else {
  398. /* the mission is valid */
  399. tune_mission_ok(true);
  400. }
  401. }
  402. }
  403. }
  404. // update manual_control_setpoint before geofence (which might check sticks or switches)
  405. _manual_control_setpoint_sub.update(&_manual_control_setpoint);
  406. /* start geofence result check */
  407. //检查电子围栏的结果
  408. _geofence_result_sub.update(&_geofence_result);
  409. const bool in_low_battery_failsafe = _battery_warning > battery_status_s::BATTERY_WARNING_LOW;
  410. // Geofence actions
  411. const bool geofence_action_enabled = _geofence_result.geofence_action != geofence_result_s::GF_ACTION_NONE;
  412. if (armed.armed
  413. && geofence_action_enabled
  414. && !in_low_battery_failsafe) {
  415. // check for geofence violation transition
  416. if (_geofence_result.geofence_violated && !_geofence_violated_prev) {
  417. switch (_geofence_result.geofence_action) {
  418. case (geofence_result_s::GF_ACTION_NONE) : {
  419. // do nothing
  420. break;
  421. }
  422. case (geofence_result_s::GF_ACTION_WARN) : {
  423. // do nothing, mavlink critical messages are sent by navigator
  424. break;
  425. }
  426. case (geofence_result_s::GF_ACTION_LOITER) : {
  427. if (TRANSITION_CHANGED == main_state_transition(status, commander_state_s::MAIN_STATE_AUTO_LOITER, status_flags,
  428. &_internal_state)) {
  429. _geofence_loiter_on = true;
  430. }
  431. break;
  432. }
  433. case (geofence_result_s::GF_ACTION_RTL) : {
  434. if (TRANSITION_CHANGED == main_state_transition(status, commander_state_s::MAIN_STATE_AUTO_RTL, status_flags,
  435. &_internal_state)) {
  436. _geofence_rtl_on = true;
  437. }
  438. break;
  439. }
  440. case (geofence_result_s::GF_ACTION_LAND) : {
  441. if (TRANSITION_CHANGED == main_state_transition(status, commander_state_s::MAIN_STATE_AUTO_LAND, status_flags,
  442. &_internal_state)) {
  443. _geofence_land_on = true;
  444. }
  445. break;
  446. }
  447. case (geofence_result_s::GF_ACTION_TERMINATE) : {
  448. PX4_WARN("Flight termination because of geofence");
  449. mavlink_log_critical(&mavlink_log_pub, "Geofence violation! Flight terminated");
  450. armed.force_failsafe = true;
  451. _status_changed = true;
  452. break;
  453. }
  454. }
  455. }
  456. _geofence_violated_prev = _geofence_result.geofence_violated;
  457. // reset if no longer in LOITER or if manually switched to LOITER
  458. const bool in_loiter_mode = _internal_state.main_state == commander_state_s::MAIN_STATE_AUTO_LOITER;
  459. const bool manual_loiter_switch_on = _manual_control_setpoint.loiter_switch == manual_control_setpoint_s::SWITCH_POS_ON;
  460. if (!in_loiter_mode || manual_loiter_switch_on) {
  461. _geofence_loiter_on = false;
  462. }
  463. // reset if no longer in RTL or if manually switched to RTL
  464. const bool in_rtl_mode = _internal_state.main_state == commander_state_s::MAIN_STATE_AUTO_RTL;
  465. const bool manual_return_switch_on = _manual_control_setpoint.return_switch == manual_control_setpoint_s::SWITCH_POS_ON;
  466. if (!in_rtl_mode || manual_return_switch_on) {
  467. _geofence_rtl_on = false;
  468. }
  469. // reset if no longer in LAND or if manually switched to LAND
  470. const bool in_land_mode = _internal_state.main_state == commander_state_s::MAIN_STATE_AUTO_LAND;
  471. if (!in_land_mode) {
  472. _geofence_land_on = false;
  473. }
  474. _geofence_warning_action_on = _geofence_warning_action_on || (_geofence_loiter_on || _geofence_rtl_on
  475. || _geofence_land_on);
  476. } else {
  477. // No geofence checks, reset flags
  478. _geofence_loiter_on = false;
  479. _geofence_rtl_on = false;
  480. _geofence_land_on = false;
  481. _geofence_warning_action_on = false;
  482. _geofence_violated_prev = false;
  483. }
  484. // abort auto mode or geofence reaction if sticks are moved significantly
  485. // but only if not in a low battery handling action
  486. const bool is_rotary_wing = status.vehicle_type == vehicle_status_s::VEHICLE_TYPE_ROTARY_WING;
  487. const bool override_auto_mode =
  488. (_param_rc_override.get() & OVERRIDE_AUTO_MODE_BIT) &&
  489. (_internal_state.main_state == commander_state_s::MAIN_STATE_AUTO_TAKEOFF ||
  490. _internal_state.main_state == commander_state_s::MAIN_STATE_AUTO_LAND ||
  491. _internal_state.main_state == commander_state_s::MAIN_STATE_AUTO_RTL ||
  492. _internal_state.main_state == commander_state_s::MAIN_STATE_AUTO_MISSION ||
  493. _internal_state.main_state == commander_state_s::MAIN_STATE_AUTO_LOITER ||
  494. _internal_state.main_state == commander_state_s::MAIN_STATE_AUTO_FOLLOW_TARGET ||
  495. _internal_state.main_state == commander_state_s::MAIN_STATE_AUTO_PRECLAND);
  496. const bool override_offboard_mode =
  497. (_param_rc_override.get() & OVERRIDE_OFFBOARD_MODE_BIT) &&
  498. _internal_state.main_state == commander_state_s::MAIN_STATE_OFFBOARD;
  499. if ((override_auto_mode || override_offboard_mode) && is_rotary_wing
  500. && !in_low_battery_failsafe && !_geofence_warning_action_on) {
  501. // transition to previous state if sticks are touched
  502. if (hrt_elapsed_time(&_manual_control_setpoint.timestamp) < 1_s && // don't use uninitialized or old messages
  503. ((fabsf(_manual_control_setpoint.x) > _min_stick_change) ||
  504. (fabsf(_manual_control_setpoint.y) > _min_stick_change))) {
  505. // revert to position control in any case
  506. main_state_transition(status, commander_state_s::MAIN_STATE_POSCTL, status_flags, &_internal_state);
  507. mavlink_log_info(&mavlink_log_pub, "Pilot took over control using sticks");
  508. }
  509. }
  510. /* Check for mission flight termination */
  511. if (armed.armed && _mission_result_sub.get().flight_termination &&
  512. !status_flags.circuit_breaker_flight_termination_disabled) {
  513. armed.force_failsafe = true;
  514. _status_changed = true;
  515. if (!_flight_termination_printed) {
  516. mavlink_log_critical(&mavlink_log_pub, "Geofence violation! Flight terminated");
  517. _flight_termination_printed = true;
  518. }
  519. if (_counter % (1000000 / COMMANDER_MONITORING_INTERVAL) == 0) {
  520. mavlink_log_critical(&mavlink_log_pub, "Flight termination active");
  521. }
  522. }
  523. /* RC input check */
  524. //遥控输入检查
  525. if (!status_flags.rc_input_blocked && _manual_control_setpoint.timestamp != 0 &&
  526. (hrt_elapsed_time(&_manual_control_setpoint.timestamp) < (_param_com_rc_loss_t.get() * 1_s))) {
  527. /* handle the case where RC signal was regained */
  528. if (!status_flags.rc_signal_found_once) {
  529. status_flags.rc_signal_found_once = true;
  530. set_health_flags(subsystem_info_s::SUBSYSTEM_TYPE_RCRECEIVER, true, true, status_flags.rc_calibration_valid, status);
  531. _status_changed = true;
  532. } else {
  533. if (status.rc_signal_lost) {
  534. if (_rc_signal_lost_timestamp > 0) {
  535. mavlink_log_info(&mavlink_log_pub, "Manual control regained after %.1fs",
  536. hrt_elapsed_time(&_rc_signal_lost_timestamp) * 1e-6);
  537. }
  538. set_health_flags(subsystem_info_s::SUBSYSTEM_TYPE_RCRECEIVER, true, true, status_flags.rc_calibration_valid, status);
  539. _status_changed = true;
  540. }
  541. }
  542. status.rc_signal_lost = false;
  543. const bool in_armed_state = (status.arming_state == vehicle_status_s::ARMING_STATE_ARMED);
  544. const bool arm_switch_or_button_mapped =
  545. _manual_control_setpoint.arm_switch != manual_control_setpoint_s::SWITCH_POS_NONE;
  546. const bool arm_button_pressed = _param_arm_switch_is_button.get()
  547. && (_manual_control_setpoint.arm_switch == manual_control_setpoint_s::SWITCH_POS_ON);
  548. /* DISARM
  549. * check if left stick is in lower left position or arm button is pushed or arm switch has transition from arm to disarm
  550. * and we are in MANUAL, Rattitude, or AUTO_READY mode or (ASSIST mode and landed)
  551. * do it only for rotary wings in manual mode or fixed wing if landed.
  552. * Disable stick-disarming if arming switch or button is mapped */
  553. //通过遥控器的油门进行解锁操作
  554. const bool stick_in_lower_left = _manual_control_setpoint.r < -STICK_ON_OFF_LIMIT
  555. && (_manual_control_setpoint.z < 0.1f)
  556. && !arm_switch_or_button_mapped;
  557. const bool arm_switch_to_disarm_transition = !_param_arm_switch_is_button.get() &&
  558. (_last_manual_control_setpoint_arm_switch == manual_control_setpoint_s::SWITCH_POS_ON) &&
  559. (_manual_control_setpoint.arm_switch == manual_control_setpoint_s::SWITCH_POS_OFF);
  560. if (in_armed_state &&
  561. (status.rc_input_mode != vehicle_status_s::RC_IN_MODE_OFF) &&
  562. (status.vehicle_type == vehicle_status_s::VEHICLE_TYPE_ROTARY_WING || _land_detector.landed) &&
  563. (stick_in_lower_left || arm_button_pressed || arm_switch_to_disarm_transition)) {
  564. const bool manual_thrust_mode = _internal_state.main_state == commander_state_s::MAIN_STATE_MANUAL
  565. || _internal_state.main_state == commander_state_s::MAIN_STATE_ACRO
  566. || _internal_state.main_state == commander_state_s::MAIN_STATE_STAB
  567. || _internal_state.main_state == commander_state_s::MAIN_STATE_RATTITUDE;
  568. const bool rc_wants_disarm = (_stick_off_counter == rc_arm_hyst && _stick_on_counter < rc_arm_hyst)
  569. || arm_switch_to_disarm_transition;
  570. if (rc_wants_disarm && (_land_detector.landed || manual_thrust_mode)) {
  571. arming_ret = arming_state_transition(&status, _safety, vehicle_status_s::ARMING_STATE_STANDBY, &armed,
  572. true /* fRunPreArmChecks */,
  573. &mavlink_log_pub, &status_flags, _arm_requirements, hrt_elapsed_time(&_boot_timestamp),
  574. (arm_switch_to_disarm_transition ? arm_disarm_reason_t::RC_SWITCH : arm_disarm_reason_t::RC_STICK));
  575. }
  576. _stick_off_counter++;
  577. } else if (!(_param_arm_switch_is_button.get()
  578. && _manual_control_setpoint.arm_switch == manual_control_setpoint_s::SWITCH_POS_ON)) {
  579. /* do not reset the counter when holding the arm button longer than needed */
  580. _stick_off_counter = 0;
  581. }
  582. /* ARM
  583. * check if left stick is in lower right position or arm button is pushed or arm switch has transition from disarm to arm
  584. * and we're in MANUAL mode.
  585. * Disable stick-arming if arming switch or button is mapped */
  586. //通过遥控器的油门进行上锁操作
  587. const bool stick_in_lower_right = _manual_control_setpoint.r > STICK_ON_OFF_LIMIT && _manual_control_setpoint.z < 0.1f
  588. && !arm_switch_or_button_mapped;
  589. /* allow a grace period for re-arming: preflight checks don't need to pass during that time,
  590. * for example for accidential in-air disarming */
  591. const bool in_arming_grace_period = (_last_disarmed_timestamp != 0)
  592. && (hrt_elapsed_time(&_last_disarmed_timestamp) < 5_s);
  593. const bool arm_switch_to_arm_transition = !_param_arm_switch_is_button.get() &&
  594. (_last_manual_control_setpoint_arm_switch == manual_control_setpoint_s::SWITCH_POS_OFF) &&
  595. (_manual_control_setpoint.arm_switch == manual_control_setpoint_s::SWITCH_POS_ON) &&
  596. (_manual_control_setpoint.z < 0.1f || in_arming_grace_period);
  597. if (!in_armed_state &&
  598. (status.rc_input_mode != vehicle_status_s::RC_IN_MODE_OFF) &&
  599. (stick_in_lower_right || arm_button_pressed || arm_switch_to_arm_transition)) {
  600. if ((_stick_on_counter == rc_arm_hyst && _stick_off_counter < rc_arm_hyst) || arm_switch_to_arm_transition) {
  601. /* we check outside of the transition function here because the requirement
  602. * for being in manual mode only applies to manual arming actions.
  603. * the system can be armed in auto if armed via the GCS.
  604. */
  605. if ((_internal_state.main_state != commander_state_s::MAIN_STATE_MANUAL)
  606. && (_internal_state.main_state != commander_state_s::MAIN_STATE_ACRO)
  607. && (_internal_state.main_state != commander_state_s::MAIN_STATE_STAB)
  608. && (_internal_state.main_state != commander_state_s::MAIN_STATE_ALTCTL)
  609. && (_internal_state.main_state != commander_state_s::MAIN_STATE_POSCTL)
  610. && (_internal_state.main_state != commander_state_s::MAIN_STATE_RATTITUDE)
  611. ) {
  612. print_reject_arm("Not arming: Switch to a manual mode first");
  613. } else if (!status_flags.condition_home_position_valid &&
  614. (_param_geofence_action.get() == geofence_result_s::GF_ACTION_RTL)) {
  615. print_reject_arm("Not arming: Geofence RTL requires valid home");
  616. } else if (status.arming_state == vehicle_status_s::ARMING_STATE_STANDBY) {
  617. arming_ret = arming_state_transition(&status, _safety, vehicle_status_s::ARMING_STATE_ARMED, &armed,
  618. !in_arming_grace_period /* fRunPreArmChecks */,
  619. &mavlink_log_pub, &status_flags, _arm_requirements, hrt_elapsed_time(&_boot_timestamp),
  620. (arm_switch_to_arm_transition ? arm_disarm_reason_t::RC_SWITCH : arm_disarm_reason_t::RC_STICK));
  621. if (arming_ret != TRANSITION_CHANGED) {
  622. px4_usleep(100000);
  623. print_reject_arm("Not arming: Preflight checks failed");
  624. }
  625. }
  626. }
  627. _stick_on_counter++;
  628. } else if (!(_param_arm_switch_is_button.get()
  629. && _manual_control_setpoint.arm_switch == manual_control_setpoint_s::SWITCH_POS_ON)) {
  630. /* do not reset the counter when holding the arm button longer than needed */
  631. _stick_on_counter = 0;
  632. }
  633. _last_manual_control_setpoint_arm_switch = _manual_control_setpoint.arm_switch;
  634. if (arming_ret == TRANSITION_DENIED) {
  635. /*
  636. * the arming transition can be denied to a number of reasons:
  637. * - pre-flight check failed (sensors not ok or not calibrated)
  638. * - safety not disabled
  639. * - system not in manual mode
  640. */
  641. tune_negative(true);
  642. }
  643. /* evaluate the main state machine according to mode switches */
  644. //根据模式的改变估计主状态
  645. bool first_rc_eval = (_last_manual_control_setpoint.timestamp == 0) && (_manual_control_setpoint.timestamp > 0);
  646. transition_result_t main_res = set_main_state(status, &_status_changed);
  647. /* store last position lock state */
  648. _last_condition_local_altitude_valid = status_flags.condition_local_altitude_valid;
  649. _last_condition_local_position_valid = status_flags.condition_local_position_valid;
  650. _last_condition_global_position_valid = status_flags.condition_global_position_valid;
  651. /* play tune on mode change only if armed, blink LED always */
  652. if (main_res == TRANSITION_CHANGED || first_rc_eval) {
  653. tune_positive(armed.armed);
  654. _status_changed = true;
  655. } else if (main_res == TRANSITION_DENIED) {
  656. /* DENIED here indicates bug in the commander */
  657. mavlink_log_critical(&mavlink_log_pub, "Switching to this mode is currently not possible");
  658. }
  659. /* check throttle kill switch */
  660. if (_manual_control_setpoint.kill_switch == manual_control_setpoint_s::SWITCH_POS_ON) {
  661. /* set lockdown flag */
  662. if (!armed.manual_lockdown) {
  663. const char kill_switch_string[] = "Kill-switch engaged";
  664. if (_land_detector.landed) {
  665. mavlink_log_info(&mavlink_log_pub, kill_switch_string);
  666. } else {
  667. mavlink_log_critical(&mavlink_log_pub, kill_switch_string);
  668. }
  669. _status_changed = true;
  670. armed.manual_lockdown = true;
  671. }
  672. } else if (_manual_control_setpoint.kill_switch == manual_control_setpoint_s::SWITCH_POS_OFF) {
  673. if (armed.manual_lockdown) {
  674. mavlink_log_info(&mavlink_log_pub, "Kill-switch disengaged");
  675. _status_changed = true;
  676. armed.manual_lockdown = false;
  677. }
  678. }
  679. /* no else case: do not change lockdown flag in unconfigured case */
  680. } else {
  681. // set RC lost
  682. if (status_flags.rc_signal_found_once && !status.rc_signal_lost) {
  683. // ignore RC lost during calibration
  684. if (!status_flags.condition_calibration_enabled && !status_flags.rc_input_blocked) {
  685. mavlink_log_critical(&mavlink_log_pub, "Manual control lost");
  686. status.rc_signal_lost = true;
  687. _rc_signal_lost_timestamp = _manual_control_setpoint.timestamp;
  688. set_health_flags(subsystem_info_s::SUBSYSTEM_TYPE_RCRECEIVER, true, true, false, status);
  689. _status_changed = true;
  690. }
  691. }
  692. }
  693. // data link checks which update the status
  694. //数传检查
  695. data_link_check();
  696. //避障检查
  697. avoidance_check();
  698. // engine failure detection
  699. // TODO: move out of commander
  700. //引擎错误检查
  701. if (_actuator_controls_sub.updated()) {
  702. /* Check engine failure
  703. * only for fixed wing for now
  704. */
  705. if (!status_flags.circuit_breaker_engaged_enginefailure_check &&
  706. status.vehicle_type == vehicle_status_s::VEHICLE_TYPE_FIXED_WING && !status.is_vtol && armed.armed) {
  707. actuator_controls_s actuator_controls{};
  708. _actuator_controls_sub.copy(&actuator_controls);
  709. const float throttle = actuator_controls.control[actuator_controls_s::INDEX_THROTTLE];
  710. const float current2throttle = _battery_current / throttle;
  711. if (((throttle > _param_ef_throttle_thres.get()) && (current2throttle < _param_ef_current2throttle_thres.get()))
  712. || status.engine_failure) {
  713. const float elapsed = hrt_elapsed_time(&_timestamp_engine_healthy) / 1e6f;
  714. /* potential failure, measure time */
  715. if ((_timestamp_engine_healthy > 0) && (elapsed > _param_ef_time_thres.get())
  716. && !status.engine_failure) {
  717. status.engine_failure = true;
  718. _status_changed = true;
  719. PX4_ERR("Engine Failure");
  720. set_health_flags(subsystem_info_s::SUBSYSTEM_TYPE_MOTORCONTROL, true, true, false, status);
  721. }
  722. }
  723. } else {
  724. /* no failure reset flag */
  725. _timestamp_engine_healthy = hrt_absolute_time();
  726. if (status.engine_failure) {
  727. status.engine_failure = false;
  728. _status_changed = true;
  729. }
  730. }
  731. }
  732. /* Reset main state to loiter or auto-mission after takeoff is completed.
  733. * Sometimes, the mission result topic is outdated and the mission is still signaled
  734. * as finished even though we only just started with the takeoff. Therefore, we also
  735. * check the timestamp of the mission_result topic. */
  736. //在起飞任务完成后,转到悬停或者任务模式
  737. if (_internal_state.main_state == commander_state_s::MAIN_STATE_AUTO_TAKEOFF
  738. && (_mission_result_sub.get().timestamp > _internal_state.timestamp)
  739. && _mission_result_sub.get().finished) {
  740. const bool mission_available = (_mission_result_sub.get().timestamp > _boot_timestamp)
  741. && (_mission_result_sub.get().instance_count > 0) && _mission_result_sub.get().valid;
  742. if ((_param_takeoff_finished_action.get() == 1) && mission_available) {
  743. main_state_transition(status, commander_state_s::MAIN_STATE_AUTO_MISSION, status_flags, &_internal_state);
  744. } else {
  745. main_state_transition(status, commander_state_s::MAIN_STATE_AUTO_LOITER, status_flags, &_internal_state);
  746. }
  747. }
  748. /* check if we are disarmed and there is a better mode to wait in */
  749. //检查是否上锁和是否有一个更好的模式在等待
  750. if (!armed.armed) {
  751. /* if there is no radio control but GPS lock the user might want to fly using
  752. * just a tablet. Since the RC will force its mode switch setting on connecting
  753. * we can as well just wait in a hold mode which enables tablet control.
  754. */
  755. if (status.rc_signal_lost && (_internal_state.main_state == commander_state_s::MAIN_STATE_MANUAL)
  756. && status_flags.condition_home_position_valid) {
  757. main_state_transition(status, commander_state_s::MAIN_STATE_AUTO_LOITER, status_flags, &_internal_state);
  758. }
  759. }
  760. /* handle commands last, as the system needs to be updated to handle them */
  761. //解析command命令
  762. if (_cmd_sub.updated()) {
  763. /* got command */
  764. const unsigned last_generation = _cmd_sub.get_last_generation();
  765. vehicle_command_s cmd;
  766. if (_cmd_sub.copy(&cmd)) {
  767. if (_cmd_sub.get_last_generation() != last_generation + 1) {
  768. PX4_ERR("vehicle_command lost, generation %d -> %d", last_generation, _cmd_sub.get_last_generation());
  769. }
  770. //根据当前状态和解锁情况对command进行解析
  771. if (handle_command(&status, cmd, &armed, _command_ack_pub)) {
  772. _status_changed = true;
  773. }
  774. }
  775. }
  776. /* Check for failure detector status */
  777. //无人机失控状态检测
  778. const bool failure_detector_updated = _failure_detector.update(status);
  779. if (failure_detector_updated) {
  780. const uint8_t failure_status = _failure_detector.getStatus();
  781. if (failure_status != status.failure_detector_status) {
  782. status.failure_detector_status = failure_status;
  783. _status_changed = true;
  784. }
  785. }
  786. if (armed.armed &&
  787. failure_detector_updated) {
  788. if (_failure_detector.isFailure()) {
  789. const hrt_abstime time_at_arm = armed.armed_time_ms * 1000;
  790. if (hrt_elapsed_time(&time_at_arm) < 500_ms) {
  791. // 500ms is the PWM spoolup time. Within this timeframe controllers are not affecting actuator_outputs
  792. if (status.failure_detector_status & vehicle_status_s::FAILURE_ARM_ESC) {
  793. arm_disarm(false, true, &mavlink_log_pub, arm_disarm_reason_t::FAILURE_DETECTOR);
  794. _status_changed = true;
  795. mavlink_log_critical(&mavlink_log_pub, "ESCs did not respond to arm request");
  796. }
  797. }
  798. if (hrt_elapsed_time(&_time_at_takeoff) < (1_s * _param_com_lkdown_tko.get())) {
  799. // This handles the case where something fails during the early takeoff phase
  800. if (!_lockdown_triggered) {
  801. armed.lockdown = true;
  802. _lockdown_triggered = true;
  803. _status_changed = true;
  804. mavlink_log_emergency(&mavlink_log_pub, "Critical failure detected: lockdown");
  805. }
  806. } else if (!status_flags.circuit_breaker_flight_termination_disabled &&
  807. !_flight_termination_triggered && !_lockdown_triggered) {
  808. armed.force_failsafe = true;
  809. _flight_termination_triggered = true;
  810. _status_changed = true;
  811. mavlink_log_emergency(&mavlink_log_pub, "Critical failure detected: terminate flight");
  812. set_tune_override(TONE_PARACHUTE_RELEASE_TUNE);
  813. }
  814. }
  815. }
  816. /* Get current timestamp */
  817. const hrt_abstime now = hrt_absolute_time();
  818. // automatically set or update home position
  819. //自动更新或者设置家的位置
  820. if (!_home_pub.get().manual_home) {
  821. const vehicle_local_position_s &local_position = _local_position_sub.get();
  822. // set the home position when taking off, but only if we were previously disarmed
  823. // and at least 500 ms from commander start spent to avoid setting home on in-air restart
  824. if (_should_set_home_on_takeoff && _was_landed && !_land_detector.landed &&
  825. (hrt_elapsed_time(&_boot_timestamp) > INAIR_RESTART_HOLDOFF_INTERVAL)) {
  826. _should_set_home_on_takeoff = false;
  827. set_home_position();
  828. }
  829. if (!armed.armed) {
  830. if (status_flags.condition_home_position_valid) {
  831. if (_land_detector.landed && local_position.xy_valid && local_position.z_valid) {
  832. /* distance from home */
  833. float home_dist_xy = -1.0f;
  834. float home_dist_z = -1.0f;
  835. mavlink_wpm_distance_to_point_local(_home_pub.get().x, _home_pub.get().y, _home_pub.get().z,
  836. local_position.x, local_position.y, local_position.z,
  837. &home_dist_xy, &home_dist_z);
  838. if ((home_dist_xy > local_position.eph * 2.0f) || (home_dist_z > local_position.epv * 2.0f)) {
  839. /* update when disarmed, landed and moved away from current home position */
  840. set_home_position();
  841. }
  842. }
  843. } else {
  844. /* First time home position update - but only if disarmed */
  845. set_home_position();
  846. /* Set home position altitude to EKF origin height if home is not set and the EKF has a global origin.
  847. * This allows home altitude to be used in the calculation of height above takeoff location when GPS
  848. * use has commenced after takeoff. */
  849. if (!status_flags.condition_home_position_valid) {
  850. set_home_position_alt_only();
  851. }
  852. }
  853. }
  854. }
  855. // check for arming state change
  856. //检查解锁状态改变
  857. if (_was_armed != armed.armed) {
  858. _status_changed = true;
  859. if (armed.armed) {
  860. if (!_land_detector.landed) { // check if takeoff already detected upon arming
  861. _have_taken_off_since_arming = true;
  862. }
  863. } else { // increase the flight uuid upon disarming
  864. const int32_t flight_uuid = _param_flight_uuid.get() + 1;
  865. _param_flight_uuid.set(flight_uuid);
  866. _param_flight_uuid.commit_no_notification();
  867. _last_disarmed_timestamp = hrt_absolute_time();
  868. _should_set_home_on_takeoff = true;
  869. }
  870. }
  871. if (!armed.armed) {
  872. /* Reset the flag if disarmed. */
  873. _have_taken_off_since_arming = false;
  874. }
  875. _was_armed = armed.armed;
  876. /* now set navigation state according to failsafe and main state */
  877. //根据失控和主状态设置导航状态
  878. bool nav_state_changed = set_nav_state(&status,
  879. &armed,
  880. &_internal_state,
  881. &mavlink_log_pub,
  882. (link_loss_actions_t)_param_nav_dll_act.get(),
  883. _mission_result_sub.get().finished,
  884. _mission_result_sub.get().stay_in_failsafe,
  885. status_flags,
  886. _land_detector.landed,
  887. (link_loss_actions_t)_param_nav_rcl_act.get(),
  888. (offboard_loss_actions_t)_param_com_obl_act.get(),
  889. (offboard_loss_rc_actions_t)_param_com_obl_rc_act.get(),
  890. (position_nav_loss_actions_t)_param_com_posctl_navl.get());
  891. if (nav_state_changed) {
  892. status.nav_state_timestamp = hrt_absolute_time();
  893. }
  894. if (status.failsafe != _failsafe_old) {
  895. _status_changed = true;
  896. if (status.failsafe) {
  897. mavlink_log_info(&mavlink_log_pub, "Failsafe mode activated");
  898. } else {
  899. mavlink_log_info(&mavlink_log_pub, "Failsafe mode deactivated");
  900. }
  901. _failsafe_old = status.failsafe;
  902. }
  903. //发布一些状态
  904. /* publish states (armed, control_mode, vehicle_status, commander_state, vehicle_status_flags) at 2 Hz or immediately when changed */
  905. if (hrt_elapsed_time(&status.timestamp) >= 500_ms || _status_changed || nav_state_changed) {
  906. update_control_mode();
  907. status.timestamp = hrt_absolute_time();
  908. _status_pub.publish(status);
  909. switch ((PrearmedMode)_param_com_prearm_mode.get()) {
  910. case PrearmedMode::DISABLED:
  911. /* skip prearmed state */
  912. armed.prearmed = false;
  913. break;
  914. case PrearmedMode::ALWAYS:
  915. /* safety is not present, go into prearmed
  916. * (all output drivers should be started / unlocked last in the boot process
  917. * when the rest of the system is fully initialized)
  918. */
  919. armed.prearmed = (hrt_elapsed_time(&_boot_timestamp) > 5_s);
  920. break;
  921. case PrearmedMode::SAFETY_BUTTON:
  922. if (_safety.safety_switch_available) {
  923. /* safety switch is present, go into prearmed if safety is off */
  924. armed.prearmed = _safety.safety_off;
  925. } else {
  926. /* safety switch is not present, do not go into prearmed */
  927. armed.prearmed = false;
  928. }
  929. break;
  930. default:
  931. armed.prearmed = false;
  932. break;
  933. }
  934. armed.timestamp = hrt_absolute_time();
  935. _armed_pub.publish(armed);
  936. /* publish internal state for logging purposes */
  937. _internal_state.timestamp = hrt_absolute_time();
  938. _commander_state_pub.publish(_internal_state);
  939. /* publish vehicle_status_flags */
  940. status_flags.timestamp = hrt_absolute_time();
  941. // Evaluate current prearm status
  942. if (!armed.armed && !status_flags.condition_calibration_enabled) {
  943. bool preflight_check_res = PreFlightCheck::preflightCheck(nullptr, status, status_flags, true, false, true, 30_s);
  944. bool prearm_check_res = PreFlightCheck::preArmCheck(nullptr, status_flags, _safety, _arm_requirements, status, false);
  945. set_health_flags(subsystem_info_s::SUBSYSTEM_TYPE_PREARM_CHECK, true, true, (preflight_check_res
  946. && prearm_check_res), status);
  947. }
  948. _vehicle_status_flags_pub.publish(status_flags);
  949. }
  950. /* play arming and battery warning tunes */
  951. if (!_arm_tune_played && armed.armed &&
  952. (_safety.safety_switch_available || (_safety.safety_switch_available && _safety.safety_off))) {
  953. /* play tune when armed */
  954. set_tune(TONE_ARMING_WARNING_TUNE);
  955. _arm_tune_played = true;
  956. } else if (!status_flags.usb_connected &&
  957. (status.hil_state != vehicle_status_s::HIL_STATE_ON) &&
  958. (_battery_warning == battery_status_s::BATTERY_WARNING_CRITICAL)) {
  959. /* play tune on battery critical */
  960. set_tune(TONE_BATTERY_WARNING_FAST_TUNE);
  961. } else if ((status.hil_state != vehicle_status_s::HIL_STATE_ON) &&
  962. (_battery_warning == battery_status_s::BATTERY_WARNING_LOW)) {
  963. /* play tune on battery warning */
  964. set_tune(TONE_BATTERY_WARNING_SLOW_TUNE);
  965. } else if (status.failsafe) {
  966. tune_failsafe(true);
  967. } else {
  968. set_tune(TONE_STOP_TUNE);
  969. }
  970. /* reset arm_tune_played when disarmed */
  971. if (!armed.armed || (_safety.safety_switch_available && !_safety.safety_off)) {
  972. //Notify the user that it is safe to approach the vehicle
  973. if (_arm_tune_played) {
  974. tune_neutral(true);
  975. }
  976. _arm_tune_played = false;
  977. }
  978. /* play sensor failure tunes if we already waited for hotplug sensors to come up and failed */
  979. status_flags.condition_system_hotplug_timeout = (hrt_elapsed_time(&_boot_timestamp) > HOTPLUG_SENS_TIMEOUT);
  980. if (!sensor_fail_tune_played && (!status_flags.condition_system_sensors_initialized
  981. && status_flags.condition_system_hotplug_timeout)) {
  982. set_tune_override(TONE_GPS_WARNING_TUNE);
  983. sensor_fail_tune_played = true;
  984. _status_changed = true;
  985. }
  986. _counter++;
  987. int blink_state = blink_msg_state();
  988. if (blink_state > 0) {
  989. /* blinking LED message, don't touch LEDs */
  990. if (blink_state == 2) {
  991. /* blinking LED message completed, restore normal state */
  992. control_status_leds(&status, &armed, true, _battery_warning);
  993. }
  994. } else {
  995. /* normal state */
  996. control_status_leds(&status, &armed, _status_changed, _battery_warning);
  997. }
  998. _status_changed = false;
  999. arm_auth_update(now, params_updated || param_init_forced);
  1000. px4_usleep(COMMANDER_MONITORING_INTERVAL);
  1001. }
  1002. thread_should_exit = true;
  1003. /* wait for threads to complete */
  1004. int ret = pthread_join(commander_low_prio_thread, nullptr);
  1005. if (ret) {
  1006. warn("join failed: %d", ret);
  1007. }
  1008. rgbled_set_color_and_mode(led_control_s::COLOR_WHITE, led_control_s::MODE_OFF);
  1009. /* close fds */
  1010. led_deinit();
  1011. buzzer_deinit();
  1012. thread_running = false;
  1013. }

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多