Line data Source code
1 : #include "Rover.h"
2 :
3 3990 : Mode::Mode() :
4 3990 : ahrs(rover.ahrs),
5 3990 : g(rover.g),
6 3990 : g2(rover.g2),
7 3990 : channel_steer(rover.channel_steer),
8 3990 : channel_throttle(rover.channel_throttle),
9 3990 : channel_lateral(rover.channel_lateral),
10 3990 : channel_roll(rover.channel_roll),
11 3990 : channel_pitch(rover.channel_pitch),
12 3990 : channel_walking_height(rover.channel_walking_height),
13 3990 : attitude_control(g2.attitude_control)
14 3990 : { }
15 :
16 521 : void Mode::exit()
17 : {
18 : // call sub-classes exit
19 521 : _exit();
20 521 : }
21 :
22 580 : bool Mode::enter()
23 : {
24 580 : const bool ignore_checks = !rover.arming.is_armed(); // allow switching to any mode if disarmed. We rely on the arming check to perform
25 580 : if (!ignore_checks) {
26 :
27 : // get EKF filter status
28 : nav_filter_status filt_status;
29 139 : rover.ahrs.get_filter_status(filt_status);
30 :
31 : // check position estimate. requires origin and at least one horizontal position flag to be true
32 139 : const bool position_ok = rover.ekf_position_ok() && !rover.failsafe.ekf;
33 139 : if (requires_position() && !position_ok) {
34 2 : return false;
35 : }
36 :
37 : // check velocity estimate (if we have position estimate, we must have velocity estimate)
38 137 : if (requires_velocity() && !position_ok && !filt_status.flags.horiz_vel) {
39 0 : return false;
40 : }
41 : }
42 :
43 578 : bool ret = _enter();
44 :
45 : // initialisation common to all modes
46 578 : if (ret) {
47 : // init reversed flag
48 559 : init_reversed_flag();
49 :
50 : // clear sailboat tacking flags
51 559 : g2.sailboat.clear_tack();
52 : }
53 :
54 578 : return ret;
55 : }
56 :
57 : // decode pilot steering and throttle inputs and return in steer_out and throttle_out arguments
58 : // steering_out is in the range -4500 ~ +4500 with positive numbers meaning rotate clockwise
59 : // throttle_out is in the range -100 ~ +100
60 539567 : void Mode::get_pilot_input(float &steering_out, float &throttle_out) const
61 : {
62 : // no RC input means no throttle and centered steering
63 539567 : if (rover.failsafe.bits & FAILSAFE_EVENT_THROTTLE) {
64 601 : steering_out = 0;
65 601 : throttle_out = 0;
66 601 : return;
67 : }
68 :
69 : // apply RC skid steer mixing
70 538966 : switch ((PilotSteerType)g.pilot_steer_type.get())
71 : {
72 538966 : case PilotSteerType::DEFAULT:
73 : case PilotSteerType::DIR_REVERSED_WHEN_REVERSING:
74 : default: {
75 : // by default regular and skid-steering vehicles reverse their rotation direction when backing up
76 538966 : throttle_out = rover.channel_throttle->get_control_in();
77 538966 : const float steering_dir = is_negative(throttle_out) ? -1 : 1;
78 538966 : steering_out = steering_dir * rover.channel_steer->get_control_in();
79 538966 : break;
80 : }
81 :
82 0 : case PilotSteerType::TWO_PADDLES: {
83 : // convert the two radio_in values from skid steering values
84 : // left paddle from steering input channel, right paddle from throttle input channel
85 : // steering = left-paddle - right-paddle
86 : // throttle = average(left-paddle, right-paddle)
87 0 : const float left_paddle = rover.channel_steer->norm_input_dz();
88 0 : const float right_paddle = rover.channel_throttle->norm_input_dz();
89 :
90 0 : throttle_out = 0.5f * (left_paddle + right_paddle) * 100.0f;
91 0 : steering_out = (left_paddle - right_paddle) * 0.5f * 4500.0f;
92 0 : break;
93 : }
94 :
95 0 : case PilotSteerType::DIR_UNCHANGED_WHEN_REVERSING: {
96 0 : throttle_out = rover.channel_throttle->get_control_in();
97 0 : steering_out = rover.channel_steer->get_control_in();
98 0 : break;
99 : }
100 : }
101 : }
102 :
103 : // decode pilot steering and throttle inputs and return in steer_out and throttle_out arguments
104 : // steering_out is in the range -4500 ~ +4500 with positive numbers meaning rotate clockwise
105 : // throttle_out is in the range -100 ~ +100
106 362318 : void Mode::get_pilot_desired_steering_and_throttle(float &steering_out, float &throttle_out) const
107 : {
108 : // do basic conversion
109 362318 : get_pilot_input(steering_out, throttle_out);
110 :
111 : // for skid steering vehicles, if pilot commands would lead to saturation
112 : // we proportionally reduce steering and throttle
113 362318 : if (g2.motors.have_skid_steering()) {
114 41285 : const float steer_normalised = constrain_float(steering_out / 4500.0f, -1.0f, 1.0f);
115 41285 : const float throttle_normalised = constrain_float(throttle_out * 0.01f, -1.0f, 1.0f);
116 41285 : const float saturation_value = fabsf(steer_normalised) + fabsf(throttle_normalised);
117 41285 : if (saturation_value > 1.0f) {
118 0 : steering_out /= saturation_value;
119 0 : throttle_out /= saturation_value;
120 : }
121 : }
122 :
123 : // check for special case of input and output throttle being in opposite directions
124 362318 : float throttle_out_limited = g2.motors.get_slew_limited_throttle(throttle_out, rover.G_Dt);
125 362348 : if ((is_negative(throttle_out) != is_negative(throttle_out_limited)) &&
126 30 : (g.pilot_steer_type == PilotSteerType::DEFAULT ||
127 0 : g.pilot_steer_type == PilotSteerType::DIR_REVERSED_WHEN_REVERSING)) {
128 30 : steering_out *= -1;
129 : }
130 362318 : throttle_out = throttle_out_limited;
131 362318 : }
132 :
133 : // decode pilot steering and return steering_out and speed_out (in m/s)
134 7622 : void Mode::get_pilot_desired_steering_and_speed(float &steering_out, float &speed_out) const
135 : {
136 : float desired_throttle;
137 7622 : get_pilot_input(steering_out, desired_throttle);
138 7622 : speed_out = desired_throttle * 0.01f * calc_speed_max(g.speed_cruise, g.throttle_cruise * 0.01f);
139 : // check for special case of input and output throttle being in opposite directions
140 7622 : float speed_out_limited = g2.attitude_control.get_desired_speed_accel_limited(speed_out, rover.G_Dt);
141 7871 : if ((is_negative(speed_out) != is_negative(speed_out_limited)) &&
142 249 : (g.pilot_steer_type == PilotSteerType::DEFAULT ||
143 0 : g.pilot_steer_type == PilotSteerType::DIR_REVERSED_WHEN_REVERSING)) {
144 249 : steering_out *= -1;
145 : }
146 7622 : speed_out = speed_out_limited;
147 7622 : }
148 :
149 : // decode pilot lateral movement input and return in lateral_out argument
150 362133 : void Mode::get_pilot_desired_lateral(float &lateral_out) const
151 : {
152 : // no RC input means no lateral input
153 362133 : if ((rover.failsafe.bits & FAILSAFE_EVENT_THROTTLE) || (rover.channel_lateral == nullptr)) {
154 217 : lateral_out = 0;
155 217 : return;
156 : }
157 :
158 : // get pilot lateral input
159 361916 : lateral_out = rover.channel_lateral->get_control_in();
160 : }
161 :
162 : // decode pilot's input and return heading_out (in cd) and speed_out (in m/s)
163 0 : void Mode::get_pilot_desired_heading_and_speed(float &heading_out, float &speed_out) const
164 : {
165 : // get steering and throttle in the -1 to +1 range
166 0 : float desired_steering = constrain_float(rover.channel_steer->norm_input_dz(), -1.0f, 1.0f);
167 0 : float desired_throttle = constrain_float(rover.channel_throttle->norm_input_dz(), -1.0f, 1.0f);
168 :
169 : // handle two paddle input
170 0 : if (g.pilot_steer_type == PilotSteerType::TWO_PADDLES) {
171 0 : const float left_paddle = desired_steering;
172 0 : const float right_paddle = desired_throttle;
173 0 : desired_steering = (left_paddle - right_paddle) * 0.5f;
174 0 : desired_throttle = (left_paddle + right_paddle) * 0.5f;
175 : }
176 :
177 : // calculate angle of input stick vector
178 0 : heading_out = wrap_360_cd(rad_to_cd(atan2f(desired_steering, desired_throttle)));
179 :
180 : // calculate throttle using magnitude of input stick vector
181 0 : const float throttle = MIN(safe_sqrt(sq(desired_throttle) + sq(desired_steering)), 1.0f);
182 0 : speed_out = throttle * calc_speed_max(g.speed_cruise, g.throttle_cruise * 0.01f);
183 0 : }
184 :
185 : // decode pilot roll and pitch inputs and return in roll_out and pitch_out arguments
186 : // outputs are in the range -1 to +1
187 362133 : void Mode::get_pilot_desired_roll_and_pitch(float &roll_out, float &pitch_out) const
188 : {
189 362133 : if (channel_roll != nullptr) {
190 0 : roll_out = channel_roll->norm_input();
191 : } else {
192 362133 : roll_out = 0.0f;
193 : }
194 362133 : if (channel_pitch != nullptr) {
195 0 : pitch_out = channel_pitch->norm_input();
196 : } else {
197 362133 : pitch_out = 0.0f;
198 : }
199 362133 : }
200 :
201 : // decode pilot walking_height inputs and return in walking_height_out arguments
202 : // outputs are in the range -1 to +1
203 362133 : void Mode::get_pilot_desired_walking_height(float &walking_height_out) const
204 : {
205 362133 : if (channel_walking_height != nullptr) {
206 0 : walking_height_out = channel_walking_height->norm_input();
207 : } else {
208 362133 : walking_height_out = 0.0f;
209 : }
210 362133 : }
211 :
212 : // return heading (in degrees) to target destination (aka waypoint)
213 95719 : float Mode::wp_bearing() const
214 : {
215 95719 : if (!is_autopilot_mode()) {
216 68683 : return 0.0f;
217 : }
218 27036 : return g2.wp_nav.wp_bearing_cd() * 0.01f;
219 : }
220 :
221 : // return short-term target heading in degrees (i.e. target heading back to line between waypoints)
222 94429 : float Mode::nav_bearing() const
223 : {
224 94429 : if (!is_autopilot_mode()) {
225 68683 : return 0.0f;
226 : }
227 25746 : return g2.wp_nav.nav_bearing_cd() * 0.01f;
228 : }
229 :
230 : // return cross track error (i.e. vehicle's distance from the line between waypoints)
231 95719 : float Mode::crosstrack_error_m() const
232 : {
233 95719 : if (!is_autopilot_mode()) {
234 68683 : return 0.0f;
235 : }
236 27036 : return g2.wp_nav.crosstrack_error_m();
237 : }
238 :
239 : // return desired lateral acceleration
240 83217 : float Mode::get_desired_lat_accel() const
241 : {
242 83217 : if (!is_autopilot_mode()) {
243 67913 : return 0.0f;
244 : }
245 15304 : return g2.wp_nav.get_lat_accel();
246 : }
247 :
248 : // set desired location
249 125 : bool Mode::set_desired_location(const Location &destination, Location next_destination )
250 : {
251 125 : if (!g2.wp_nav.set_desired_location(destination, next_destination)) {
252 0 : return false;
253 : }
254 :
255 : // initialise distance
256 125 : _distance_to_destination = g2.wp_nav.get_distance_to_destination();
257 125 : _reached_destination = false;
258 :
259 125 : return true;
260 : }
261 :
262 : // get default speed for this mode (held in WP_SPEED or RTL_SPEED)
263 1753 : float Mode::get_speed_default(bool rtl) const
264 : {
265 1753 : if (rtl && is_positive(g2.rtl_speed)) {
266 0 : return g2.rtl_speed;
267 : }
268 :
269 1753 : return g2.wp_nav.get_default_speed();
270 : }
271 :
272 : // execute the mission in reverse (i.e. backing up)
273 125 : void Mode::set_reversed(bool value)
274 : {
275 125 : g2.wp_nav.set_reversed(value);
276 125 : }
277 :
278 : // handle tacking request (from auxiliary switch) in sailboats
279 0 : void Mode::handle_tack_request()
280 : {
281 : // autopilot modes handle tacking
282 0 : if (is_autopilot_mode()) {
283 0 : g2.sailboat.handle_tack_request_auto();
284 : }
285 0 : }
286 :
287 218385 : void Mode::calc_throttle(float target_speed, bool avoidance_enabled)
288 : {
289 : // get acceleration limited target speed
290 218385 : target_speed = attitude_control.get_desired_speed_accel_limited(target_speed, rover.G_Dt);
291 :
292 : #if AP_AVOIDANCE_ENABLED
293 : // apply object avoidance to desired speed using half vehicle's maximum deceleration
294 218385 : if (avoidance_enabled) {
295 37524 : g2.avoid.adjust_speed(0.0f, 0.5f * attitude_control.get_decel_max(), ahrs.get_yaw_rad(), target_speed, rover.G_Dt);
296 37524 : if (g2.sailboat.tack_enabled() && g2.avoid.limits_active()) {
297 : // we are a sailboat trying to avoid fence, try a tack
298 0 : if (rover.control_mode != &rover.mode_acro) {
299 0 : rover.control_mode->handle_tack_request();
300 : }
301 : }
302 : }
303 : #endif // AP_AVOIDANCE_ENABLED
304 :
305 : // call throttle controller and convert output to -100 to +100 range
306 218385 : float throttle_out = 0.0f;
307 :
308 218385 : if (g2.sailboat.sail_enabled()) {
309 : // sailboats use special throttle and mainsail controller
310 17468 : g2.sailboat.get_throttle_and_set_mainsail(target_speed, throttle_out);
311 : } else {
312 : // call speed or stop controller
313 200917 : if (is_zero(target_speed) && !rover.is_balancebot()) {
314 : bool stopped;
315 23720 : throttle_out = 100.0f * attitude_control.get_throttle_out_stop(g2.motors.limit.throttle_lower, g2.motors.limit.throttle_upper, g.speed_cruise, g.throttle_cruise * 0.01f, rover.G_Dt, stopped);
316 : } else {
317 177197 : bool motor_lim_low = g2.motors.limit.throttle_lower || attitude_control.pitch_limited();
318 177197 : bool motor_lim_high = g2.motors.limit.throttle_upper || attitude_control.pitch_limited();
319 177197 : throttle_out = 100.0f * attitude_control.get_throttle_out_speed(target_speed, motor_lim_low, motor_lim_high, g.speed_cruise, g.throttle_cruise * 0.01f, rover.G_Dt);
320 : }
321 :
322 : // if vehicle is balance bot, calculate actual throttle required for balancing
323 200917 : if (rover.is_balancebot()) {
324 21785 : rover.balancebot_pitch_control(throttle_out);
325 : }
326 : }
327 :
328 : // send to motor
329 218385 : g2.motors.set_throttle(throttle_out);
330 218385 : }
331 :
332 : // performs a controlled stop without turning
333 44012 : bool Mode::stop_vehicle()
334 : {
335 : // call throttle controller and convert output to -100 to +100 range
336 44012 : bool stopped = false;
337 : float throttle_out;
338 :
339 : // if vehicle is balance bot, calculate throttle required for balancing
340 44012 : if (rover.is_balancebot()) {
341 450 : throttle_out = 100.0f * attitude_control.get_throttle_out_speed(0, g2.motors.limit.throttle_lower, g2.motors.limit.throttle_upper, g.speed_cruise, g.throttle_cruise * 0.01f, rover.G_Dt);
342 450 : rover.balancebot_pitch_control(throttle_out);
343 : } else {
344 43562 : throttle_out = 100.0f * attitude_control.get_throttle_out_stop(g2.motors.limit.throttle_lower, g2.motors.limit.throttle_upper, g.speed_cruise, g.throttle_cruise * 0.01f, rover.G_Dt, stopped);
345 : }
346 :
347 : // relax sails if present
348 44012 : g2.sailboat.relax_sails();
349 :
350 : // send to motor
351 44012 : g2.motors.set_throttle(throttle_out);
352 :
353 : // do not turn while slowing down
354 44012 : float steering_out = 0.0;
355 44012 : if (!stopped) {
356 1705 : steering_out = attitude_control.get_steering_out_rate(0.0, g2.motors.limit.steer_left, g2.motors.limit.steer_right, rover.G_Dt);
357 : }
358 44012 : g2.motors.set_steering(steering_out * 4500.0);
359 :
360 : // return true once stopped
361 44012 : return stopped;
362 : }
363 :
364 : // estimate maximum vehicle speed (in m/s)
365 : // cruise_speed is in m/s, cruise_throttle should be in the range -1 to +1
366 177249 : float Mode::calc_speed_max(float cruise_speed, float cruise_throttle) const
367 : {
368 : float speed_max;
369 :
370 : // sanity checks
371 177249 : if (cruise_throttle > 1.0f || cruise_throttle < 0.05f) {
372 1218 : speed_max = cruise_speed;
373 176031 : } else if (is_positive(g2.speed_max)) {
374 0 : speed_max = g2.speed_max;
375 : } else {
376 : // project vehicle's maximum speed
377 176031 : speed_max = (1.0f / cruise_throttle) * cruise_speed;
378 : }
379 :
380 : // constrain to 100m/s and return
381 177249 : return constrain_float(speed_max, 0.0f, 100.0f);
382 : }
383 :
384 : // calculate pilot input to nudge speed up or down
385 : // target_speed should be in meters/sec
386 : // reversed should be true if the vehicle is intentionally backing up which allows the pilot to increase the backing up speed by pulling the throttle stick down
387 189935 : float Mode::calc_speed_nudge(float target_speed, bool reversed)
388 : {
389 : // sanity checks
390 189935 : if (g.throttle_cruise > 100 || g.throttle_cruise < 5) {
391 20308 : return target_speed;
392 : }
393 :
394 : // convert pilot throttle input to speed
395 : float pilot_steering, pilot_throttle;
396 169627 : get_pilot_input(pilot_steering, pilot_throttle);
397 169627 : float pilot_speed = pilot_throttle * 0.01f * calc_speed_max(g.speed_cruise, g.throttle_cruise * 0.01f);
398 :
399 : // ignore pilot's input if in opposite direction to vehicle's desired direction of travel
400 : // note that the target_speed may be negative while reversed is true (or vice-versa)
401 : // while vehicle is transitioning between forward and backwards movement
402 341250 : if ((is_positive(pilot_speed) && reversed) ||
403 171623 : (is_negative(pilot_speed) && !reversed)) {
404 1996 : return target_speed;
405 : }
406 :
407 : // return the larger of the pilot speed and the original target speed
408 167631 : if (reversed) {
409 800 : return MIN(target_speed, pilot_speed);
410 : } else {
411 166831 : return MAX(target_speed, pilot_speed);
412 : }
413 : }
414 :
415 : // high level call to navigate to waypoint
416 : // uses wp_nav to calculate turn rate and speed to drive along the path from origin to destination
417 : // this function updates _distance_to_destination
418 180861 : void Mode::navigate_to_waypoint()
419 : {
420 : // apply speed nudge from pilot
421 : // calc_speed_nudge's "desired_speed" argument should be negative when vehicle is reversing
422 : // AR_WPNav nudge_speed_max argu,ent should always be positive even when reversing
423 180861 : const float calc_nudge_input_speed = g2.wp_nav.get_speed_max() * (g2.wp_nav.get_reversed() ? -1.0 : 1.0);
424 180861 : const float nudge_speed_max = calc_speed_nudge(calc_nudge_input_speed, g2.wp_nav.get_reversed());
425 180861 : g2.wp_nav.set_nudge_speed_max(fabsf(nudge_speed_max));
426 :
427 : // update navigation controller
428 180861 : g2.wp_nav.update(rover.G_Dt);
429 180861 : _distance_to_destination = g2.wp_nav.get_distance_to_destination();
430 :
431 : #if AP_AVOIDANCE_ENABLED
432 : // sailboats trigger tack if simple avoidance becomes active
433 180861 : if (g2.sailboat.tack_enabled() && g2.avoid.limits_active()) {
434 : // we are a sailboat trying to avoid fence, try a tack
435 0 : rover.control_mode->handle_tack_request();
436 : }
437 : #endif
438 :
439 : // pass desired speed to throttle controller
440 : // do not do simple avoidance because this is already handled in the position controller
441 180861 : calc_throttle(g2.wp_nav.get_speed(), false);
442 :
443 180861 : float desired_heading_cd = g2.wp_nav.oa_wp_bearing_cd();
444 180861 : if (g2.sailboat.use_indirect_route(desired_heading_cd)) {
445 : // sailboats use heading controller when tacking upwind
446 3026 : desired_heading_cd = g2.sailboat.calc_heading(desired_heading_cd);
447 : // use pivot turn rate for tacks
448 3026 : const float turn_rate = g2.sailboat.tacking() ? g2.wp_nav.get_pivot_rate() : 0.0f;
449 3026 : calc_steering_to_heading(desired_heading_cd, turn_rate);
450 : } else {
451 : // retrieve turn rate from waypoint controller
452 177835 : float desired_turn_rate_rads = g2.wp_nav.get_turn_rate_rads();
453 :
454 : // if simple avoidance is active at very low speed do not attempt to turn
455 : #if AP_AVOIDANCE_ENABLED
456 177835 : if (g2.avoid.limits_active() && (fabsf(attitude_control.get_desired_speed()) <= attitude_control.get_stop_speed())) {
457 0 : desired_turn_rate_rads = 0.0f;
458 : }
459 : #endif
460 :
461 : // call turn rate steering controller
462 177835 : calc_steering_from_turn_rate(desired_turn_rate_rads);
463 : }
464 180861 : }
465 :
466 : // calculate steering output given a turn rate
467 : // desired turn rate in radians/sec. Positive to the right.
468 186544 : void Mode::calc_steering_from_turn_rate(float turn_rate)
469 : {
470 : // calculate and send final steering command to motor library
471 186544 : const float steering_out = attitude_control.get_steering_out_rate(turn_rate,
472 186544 : g2.motors.limit.steer_left,
473 186544 : g2.motors.limit.steer_right,
474 : rover.G_Dt);
475 186544 : set_steering(steering_out * 4500.0f);
476 186544 : }
477 :
478 : /*
479 : calculate steering output given lateral_acceleration
480 : */
481 3598 : void Mode::calc_steering_from_lateral_acceleration(float lat_accel, bool reversed)
482 : {
483 : // constrain to max G force
484 3598 : lat_accel = constrain_float(lat_accel, -attitude_control.get_turn_lat_accel_max(), attitude_control.get_turn_lat_accel_max());
485 :
486 : // send final steering command to motor library
487 3598 : const float steering_out = attitude_control.get_steering_out_lat_accel(lat_accel,
488 3598 : g2.motors.limit.steer_left,
489 3598 : g2.motors.limit.steer_right,
490 : rover.G_Dt);
491 3598 : set_steering(steering_out * 4500.0f);
492 3598 : }
493 :
494 : // calculate steering output to drive towards desired heading
495 : // rate_max is a maximum turn rate in deg/s. set to zero to use default turn rate limits
496 23820 : void Mode::calc_steering_to_heading(float desired_heading_cd, float rate_max_degs)
497 : {
498 : // call heading controller
499 23820 : const float steering_out = attitude_control.get_steering_out_heading(radians(desired_heading_cd*0.01f),
500 : radians(rate_max_degs),
501 23820 : g2.motors.limit.steer_left,
502 23820 : g2.motors.limit.steer_right,
503 : rover.G_Dt);
504 23820 : set_steering(steering_out * 4500.0f);
505 23820 : }
506 :
507 218570 : void Mode::set_steering(float steering_value)
508 : {
509 218570 : if (allows_stick_mixing() && g2.stick_mixing > 0) {
510 1073 : steering_value = channel_steer->stick_mixing((int16_t)steering_value);
511 : }
512 218570 : g2.motors.set_steering(steering_value);
513 218570 : }
514 :
515 945 : Mode *Rover::mode_from_mode_num(const enum Mode::Number num)
516 : {
517 945 : Mode *ret = nullptr;
518 945 : switch (num) {
519 767 : case Mode::Number::MANUAL:
520 767 : ret = &mode_manual;
521 767 : break;
522 14 : case Mode::Number::ACRO:
523 14 : ret = &mode_acro;
524 14 : break;
525 10 : case Mode::Number::STEERING:
526 10 : ret = &mode_steering;
527 10 : break;
528 21 : case Mode::Number::HOLD:
529 21 : ret = &mode_hold;
530 21 : break;
531 29 : case Mode::Number::LOITER:
532 29 : ret = &mode_loiter;
533 29 : break;
534 : #if MODE_FOLLOW_ENABLED
535 0 : case Mode::Number::FOLLOW:
536 0 : ret = &mode_follow;
537 0 : break;
538 : #endif
539 0 : case Mode::Number::SIMPLE:
540 0 : ret = &mode_simple;
541 0 : break;
542 0 : case Mode::Number::CIRCLE:
543 0 : ret = &g2.mode_circle;
544 0 : break;
545 40 : case Mode::Number::AUTO:
546 40 : ret = &mode_auto;
547 40 : break;
548 16 : case Mode::Number::RTL:
549 16 : ret = &mode_rtl;
550 16 : break;
551 3 : case Mode::Number::SMART_RTL:
552 3 : ret = &mode_smartrtl;
553 3 : break;
554 40 : case Mode::Number::GUIDED:
555 40 : ret = &mode_guided;
556 40 : break;
557 0 : case Mode::Number::INITIALISING:
558 0 : ret = &mode_initializing;
559 0 : break;
560 : #if MODE_DOCK_ENABLED
561 3 : case Mode::Number::DOCK:
562 3 : ret = (Mode *)g2.mode_dock_ptr;
563 3 : break;
564 : #endif
565 2 : default:
566 2 : break;
567 : }
568 945 : return ret;
569 : }
|