forked from ArduPilot/ardupilot
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmode_auto.cpp
189 lines (163 loc) · 5.82 KB
/
mode_auto.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
#include "mode.h"
#include "Plane.h"
bool ModeAuto::_enter()
{
#if HAL_QUADPLANE_ENABLED
// check if we should refuse auto mode due to a missing takeoff in
// guided_wait_takeoff state
if (plane.previous_mode == &plane.mode_guided &&
quadplane.guided_wait_takeoff_on_mode_enter) {
if (!plane.mission.starts_with_takeoff_cmd()) {
gcs().send_text(MAV_SEVERITY_ERROR,"Takeoff waypoint required");
quadplane.guided_wait_takeoff = true;
return false;
}
}
if (plane.quadplane.available() && plane.quadplane.enable == 2) {
plane.auto_state.vtol_mode = true;
} else {
plane.auto_state.vtol_mode = false;
}
#else
plane.auto_state.vtol_mode = false;
#endif
plane.next_WP_loc = plane.prev_WP_loc = plane.current_loc;
// start or resume the mission, based on MIS_AUTORESET
plane.mission.start_or_resume();
if (hal.util->was_watchdog_armed()) {
if (hal.util->persistent_data.waypoint_num != 0) {
gcs().send_text(MAV_SEVERITY_INFO, "Watchdog: resume WP %u", hal.util->persistent_data.waypoint_num);
plane.mission.set_current_cmd(hal.util->persistent_data.waypoint_num);
hal.util->persistent_data.waypoint_num = 0;
}
}
#if HAL_SOARING_ENABLED
plane.g2.soaring_controller.init_cruising();
#endif
return true;
}
void ModeAuto::_exit()
{
if (plane.mission.state() == AP_Mission::MISSION_RUNNING) {
plane.mission.stop();
bool restart = plane.mission.get_current_nav_cmd().id == MAV_CMD_NAV_LAND;
#if HAL_QUADPLANE_ENABLED
if (plane.quadplane.is_vtol_land(plane.mission.get_current_nav_cmd().id)) {
restart = false;
}
#endif
if (restart) {
plane.landing.restart_landing_sequence();
}
}
plane.auto_state.started_flying_in_auto_ms = 0;
}
void ModeAuto::update()
{
if (plane.mission.state() != AP_Mission::MISSION_RUNNING) {
// this could happen if AP_Landing::restart_landing_sequence() returns false which would only happen if:
// restart_landing_sequence() is called when not executing a NAV_LAND or there is no previous nav point
plane.set_mode(plane.mode_rtl, ModeReason::MISSION_END);
gcs().send_text(MAV_SEVERITY_INFO, "Aircraft in auto without a running mission");
return;
}
uint16_t nav_cmd_id = plane.mission.get_current_nav_cmd().id;
#if HAL_QUADPLANE_ENABLED
if (plane.quadplane.in_vtol_auto()) {
plane.quadplane.control_auto();
return;
}
#endif
if (nav_cmd_id == MAV_CMD_NAV_TAKEOFF ||
(nav_cmd_id == MAV_CMD_NAV_LAND && plane.flight_stage == AP_FixedWing::FlightStage::ABORT_LANDING)) {
plane.takeoff_calc_roll();
plane.takeoff_calc_pitch();
plane.calc_throttle();
} else if (nav_cmd_id == MAV_CMD_NAV_LAND) {
plane.calc_nav_roll();
plane.calc_nav_pitch();
// allow landing to restrict the roll limits
plane.nav_roll_cd = plane.landing.constrain_roll(plane.nav_roll_cd, plane.g.level_roll_limit*100UL);
if (plane.landing.is_throttle_suppressed()) {
// if landing is considered complete throttle is never allowed, regardless of landing type
SRV_Channels::set_output_scaled(SRV_Channel::k_throttle, 0.0);
} else {
plane.calc_throttle();
}
#if AP_SCRIPTING_ENABLED
} else if (nav_cmd_id == MAV_CMD_NAV_SCRIPT_TIME) {
// NAV_SCRIPTING has a desired roll and pitch rate and desired throttle
plane.nav_roll_cd = ahrs.roll_sensor;
plane.nav_pitch_cd = ahrs.pitch_sensor;
#endif
} else {
// we are doing normal AUTO flight, the special cases
// are for takeoff and landing
if (nav_cmd_id != MAV_CMD_NAV_CONTINUE_AND_CHANGE_ALT) {
plane.steer_state.hold_course_cd = -1;
}
plane.calc_nav_roll();
plane.calc_nav_pitch();
plane.calc_throttle();
}
}
void ModeAuto::navigate()
{
if (AP::ahrs().home_is_set()) {
plane.mission.update();
}
}
bool ModeAuto::does_auto_navigation() const
{
#if AP_SCRIPTING_ENABLED
return (!plane.nav_scripting_active());
#endif
return true;
}
bool ModeAuto::does_auto_throttle() const
{
#if AP_SCRIPTING_ENABLED
return (!plane.nav_scripting_active());
#endif
return true;
}
// returns true if the vehicle can be armed in this mode
bool ModeAuto::_pre_arm_checks(size_t buflen, char *buffer) const
{
#if HAL_QUADPLANE_ENABLED
if (plane.quadplane.enabled()) {
if (plane.quadplane.option_is_set(QuadPlane::OPTION::ONLY_ARM_IN_QMODE_OR_AUTO) &&
!plane.quadplane.is_vtol_takeoff(plane.mission.get_current_nav_cmd().id)) {
hal.util->snprintf(buffer, buflen, "not in VTOL takeoff");
return false;
}
if (!plane.mission.starts_with_takeoff_cmd()) {
hal.util->snprintf(buffer, buflen, "missing takeoff waypoint");
return false;
}
}
#endif
// Note that this bypasses the base class checks
return true;
}
bool ModeAuto::is_landing() const
{
return (plane.flight_stage == AP_FixedWing::FlightStage::LAND);
}
void ModeAuto::run()
{
if (plane.mission.get_current_nav_cmd().id == MAV_CMD_NAV_ALTITUDE_WAIT) {
wiggle_servos();
SRV_Channels::set_output_scaled(SRV_Channel::k_throttle, 0.0);
SRV_Channels::set_output_scaled(SRV_Channel::k_throttleLeft, 0.0);
SRV_Channels::set_output_scaled(SRV_Channel::k_throttleRight, 0.0);
SRV_Channels::set_output_to_trim(SRV_Channel::k_throttle);
SRV_Channels::set_output_to_trim(SRV_Channel::k_throttleLeft);
SRV_Channels::set_output_to_trim(SRV_Channel::k_throttleRight);
// Relax attitude control
reset_controllers();
} else {
// Normal flight, run base class
Mode::run();
}
}