Skip to content

Commit aebddf1

Browse files
committed
ArduCopter: MAV_CMD_DO_ORBIT improvements
- Fix orbit completion: use hold_position() instead of pos_control_start() to prevent vehicle flying back to start position and descending - Fix yaw after orbit completion: maintain yaw behaviour instead of always pointing to circle center - Implement param3 (ORBIT_YAW_BEHAVIOUR): 0=face center, 1=hold initial heading, 2=uncontrolled, 3=tangent to circle, 4=RC controlled, 5=unchanged - Fix approach yaw: use set_mode_to_default() during edge approach so vehicle looks in direction of travel
1 parent 307cb10 commit aebddf1

3 files changed

Lines changed: 43 additions & 15 deletions

File tree

ArduCopter/GCS_MAVLink_Copter.cpp

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -899,10 +899,7 @@ MAV_RESULT GCS_MAVLINK_Copter::handle_MAV_CMD_DO_ORBIT(const mavlink_command_int
899899
// param2: tangential velocity (m/s) - optional, 0 or NaN = use default
900900
const float speed_ms = isnan(packet.param2) ? 0.0f : fabsf(packet.param2);
901901

902-
// param3: yaw behaviour - center-facing is default, others are future work
903-
// const ORBIT_YAW_BEHAVIOUR yaw_behaviour = isnan(packet.param3)
904-
// ? ORBIT_YAW_BEHAVIOUR_HOLD_FRONT_TO_CIRCLE_CENTER
905-
// : (ORBIT_YAW_BEHAVIOUR)(int)packet.param3;
902+
// param3: yaw behaviour (ORBIT_YAW_BEHAVIOUR enum), NaN or 0 = face center
906903

907904
// x/y: center coordinates
908905
if (packet.x == INT32_MAX || packet.y == INT32_MAX) {
@@ -922,10 +919,9 @@ MAV_RESULT GCS_MAVLINK_Copter::handle_MAV_CMD_DO_ORBIT(const mavlink_command_int
922919
// NaN means "do not change" - preserve existing turn count
923920
const bool update_turns = !isnan(packet.param4);
924921
const float turns = update_turns ? fabsf(packet.param4) : 0.0f;
925-
copter.mode_guided.circle_start(circle_center, radius_m, ccw, speed_ms, update_turns, turns);
926-
927-
// start orbit
928-
copter.mode_guided.circle_start(circle_center, radius_m, ccw, speed_ms, update_turns, turns);
922+
// param3: yaw behaviour (ORBIT_YAW_BEHAVIOUR enum), NaN or 0 = face center
923+
const uint8_t yaw_behaviour = (isnan(packet.param3) || packet.param3 < 0) ? 0 : (uint8_t)packet.param3;
924+
copter.mode_guided.circle_start(circle_center, radius_m, ccw, speed_ms, update_turns, turns, yaw_behaviour);
929925

930926
return MAV_RESULT_ACCEPTED;
931927
}

ArduCopter/mode.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1180,8 +1180,9 @@ class ModeGuided : public Mode {
11801180
void angle_control_start();
11811181
void angle_control_run();
11821182
#if AC_COPTER_MODEGUIDED_ORBIT_ENABLED
1183-
void circle_start(const Location &circle_center, float radius_m, bool ccw, float speed_ms, bool update_turns, float turns);
1183+
void circle_start(const Location &circle_center, float radius_m, bool ccw, float speed_ms, bool update_turns, float turns, uint8_t yaw_behaviour = 0);
11841184
void orbit_run();
1185+
void orbit_apply_yaw_behaviour();
11851186
bool circle_moving_to_edge() const { return _circle_moving_to_edge; }
11861187
#endif
11871188

@@ -1243,6 +1244,7 @@ class ModeGuided : public Mode {
12431244
void set_yaw_state_rad(bool use_yaw, float yaw_rad, bool use_yaw_rate, float yaw_rate_rads, bool relative_angle);
12441245
#if AC_COPTER_MODEGUIDED_ORBIT_ENABLED
12451246
float _orbit_rate_degs = 20.0f; // desired orbit rate in deg/s (signed for direction)
1247+
uint8_t _orbit_yaw_behaviour = 0; // yaw behaviour during orbit (ORBIT_YAW_BEHAVIOUR enum)
12461248
float _orbit_turns = 0.0f;
12471249
float _orbit_angle_total_at_start = 0.0f;
12481250
bool _orbit_update_turns = true;

ArduCopter/mode_guided.cpp

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ void ModeGuided::wp_control_run()
263263
copter.circle_nav->center_is_terrain_alt(),
264264
_orbit_rate_degs);
265265
_circle_moving_to_edge = false;
266-
auto_yaw.set_mode(AutoYaw::Mode::CIRCLE);
266+
orbit_apply_yaw_behaviour();
267267
guided_mode = SubMode::Orbit;
268268
}
269269
#endif
@@ -1272,7 +1272,7 @@ bool ModeGuided::resume()
12721272

12731273
#if AC_COPTER_MODEGUIDED_ORBIT_ENABLED
12741274
// circle_start - initialise guided controller to fly a circle around a specified location
1275-
void ModeGuided::circle_start(const Location &circle_center, float radius_m, bool ccw, float speed_ms, bool update_turns, float turns)
1275+
void ModeGuided::circle_start(const Location &circle_center, float radius_m, bool ccw, float speed_ms, bool update_turns, float turns, uint8_t yaw_behaviour)
12761276
{
12771277
// set circle center, radius and direction
12781278
copter.circle_nav->set_center(circle_center);
@@ -1296,6 +1296,7 @@ void ModeGuided::circle_start(const Location &circle_center, float radius_m, boo
12961296
_orbit_turns = turns;
12971297
_orbit_angle_total_at_start = copter.circle_nav->get_angle_total_rad();
12981298
}
1299+
_orbit_yaw_behaviour = yaw_behaviour;
12991300

13001301
// check distance to edge of circle
13011302
Vector3p circle_edge_ned_m;
@@ -1311,6 +1312,8 @@ void ModeGuided::circle_start(const Location &circle_center, float radius_m, boo
13111312
copter.failsafe_terrain_on_event();
13121313
return;
13131314
}
1315+
// during approach look in direction of travel (default WP yaw behaviour)
1316+
auto_yaw.set_mode_to_default(false);
13141317
guided_mode = SubMode::Orbit;
13151318
_circle_moving_to_edge = true;
13161319
} else {
@@ -1319,12 +1322,38 @@ void ModeGuided::circle_start(const Location &circle_center, float radius_m, boo
13191322
copter.circle_nav->get_center_NED_m(),
13201323
copter.circle_nav->center_is_terrain_alt(),
13211324
_orbit_rate_degs);
1322-
// point camera/yaw toward circle center
1323-
auto_yaw.set_mode(AutoYaw::Mode::CIRCLE);
1325+
// set yaw behaviour
1326+
orbit_apply_yaw_behaviour();
13241327
guided_mode = SubMode::Orbit;
13251328
}
13261329
}
13271330

1331+
// orbit_apply_yaw_behaviour - set yaw mode based on ORBIT_YAW_BEHAVIOUR parameter
1332+
void ModeGuided::orbit_apply_yaw_behaviour()
1333+
{
1334+
switch (_orbit_yaw_behaviour) {
1335+
case 0: // ORBIT_YAW_BEHAVIOUR_HOLD_FRONT_TO_CIRCLE_CENTER
1336+
default:
1337+
auto_yaw.set_mode(AutoYaw::Mode::CIRCLE);
1338+
break;
1339+
case 1: // ORBIT_YAW_BEHAVIOUR_HOLD_INITIAL_HEADING
1340+
auto_yaw.set_fixed_yaw_rad(AP::ahrs().get_yaw(), 0.0f, 0, false);
1341+
break;
1342+
case 2: // ORBIT_YAW_BEHAVIOUR_UNCONTROLLED
1343+
auto_yaw.set_mode(AutoYaw::Mode::HOLD);
1344+
break;
1345+
case 3: // ORBIT_YAW_BEHAVIOUR_HOLD_FRONT_TANGENT_TO_CIRCLE
1346+
auto_yaw.set_mode(AutoYaw::Mode::LOOK_AHEAD);
1347+
break;
1348+
case 4: // ORBIT_YAW_BEHAVIOUR_RC_CONTROLLED
1349+
auto_yaw.set_mode(AutoYaw::Mode::PILOT_RATE);
1350+
break;
1351+
case 5: // ORBIT_YAW_BEHAVIOUR_UNCHANGED
1352+
// do not change yaw mode
1353+
break;
1354+
}
1355+
}
1356+
13281357
// orbit_run - run circle controller
13291358
void ModeGuided::orbit_run()
13301359
{
@@ -1335,8 +1364,9 @@ void ModeGuided::orbit_run()
13351364
if (is_positive(_orbit_turns)) {
13361365
const float turns_completed = fabsf(copter.circle_nav->get_angle_total_rad() / float(M_2PI));
13371366
if (turns_completed >= _orbit_turns) {
1338-
// orbit complete - hold position
1339-
pos_control_start();
1367+
// orbit complete - hold position and maintain yaw behaviour
1368+
hold_position();
1369+
orbit_apply_yaw_behaviour();
13401370
return;
13411371
}
13421372
}

0 commit comments

Comments
 (0)