CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
Ardupilot

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.

GitHub Repository: Ardupilot/ardupilot
Path: blob/master/Rover/mode_dock.cpp
Views: 1798
1
#include "Rover.h"
2
3
#if MODE_DOCK_ENABLED
4
5
const AP_Param::GroupInfo ModeDock::var_info[] = {
6
// @Param: _SPEED
7
// @DisplayName: Dock mode speed
8
// @Description: Vehicle speed limit in dock mode
9
// @Units: m/s
10
// @Range: 0 100
11
// @Increment: 0.1
12
// @User: Standard
13
AP_GROUPINFO("_SPEED", 1, ModeDock, speed, 0.0f),
14
15
// @Param: _DIR
16
// @DisplayName: Dock mode direction of approach
17
// @Description: Compass direction in which vehicle should approach towards dock. -1 value represents unset parameter
18
// @Units: deg
19
// @Range: 0 360
20
// @Increment: 1
21
// @User: Advanced
22
AP_GROUPINFO("_DIR", 2, ModeDock, desired_dir, -1.00f),
23
24
// @Param: _HDG_CORR_EN
25
// @DisplayName: Dock mode heading correction enable/disable
26
// @Description: When enabled, the autopilot modifies the path to approach the target head-on along desired line of approch in dock mode
27
// @Values: 0:Disabled,1:Enabled
28
// @User: Advanced
29
AP_GROUPINFO("_HDG_CORR_EN", 3, ModeDock, hdg_corr_enable, 0),
30
31
// @Param: _HDG_CORR_WT
32
// @DisplayName: Dock mode heading correction weight
33
// @Description: This value describes how aggressively vehicle tries to correct its heading to be on desired line of approach
34
// @Range: 0.00 0.90
35
// @Increment: 0.05
36
// @User: Advanced
37
AP_GROUPINFO("_HDG_CORR_WT", 4, ModeDock, hdg_corr_weight, 0.75f),
38
39
// @Param: _STOP_DIST
40
// @DisplayName: Distance from docking target when we should stop
41
// @Description: The vehicle starts stopping when it is this distance away from docking target
42
// @Units: m
43
// @Range: 0 2
44
// @Increment: 0.01
45
// @User: Standard
46
AP_GROUPINFO("_STOP_DIST", 5, ModeDock, stopping_dist, 0.30f),
47
48
AP_GROUPEND
49
};
50
51
ModeDock::ModeDock(void) : Mode()
52
{
53
AP_Param::setup_object_defaults(this, var_info);
54
}
55
56
#define AR_DOCK_ACCEL_MAX 20.0 // acceleration used when user has specified no acceleration limit
57
58
// initialize dock mode
59
bool ModeDock::_enter()
60
{
61
// refuse to enter the mode if dock is not in sight
62
if (!rover.precland.enabled() || !rover.precland.target_acquired()) {
63
gcs().send_text(MAV_SEVERITY_NOTICE, "Dock: target not acquired");
64
return false;
65
}
66
67
if (hdg_corr_enable && is_negative(desired_dir)) {
68
// DOCK_DIR is required for heading correction
69
gcs().send_text(MAV_SEVERITY_NOTICE, "Dock: Set DOCK_DIR or disable heading correction");
70
return false;
71
}
72
73
// set speed limit to dock_speed param if available
74
// otherwise the vehicle uses wp_nav default speed limit
75
const float speed_max = is_positive(speed) ? speed : g2.wp_nav.get_default_speed();
76
float atc_accel_max = MIN(g2.attitude_control.get_accel_max(), g2.attitude_control.get_decel_max());
77
if (!is_positive(atc_accel_max)) {
78
// accel_max of zero means no limit so use maximum acceleration
79
atc_accel_max = AR_DOCK_ACCEL_MAX;
80
}
81
const float accel_max = is_positive(g2.wp_nav.get_default_accel()) ? MIN(g2.wp_nav.get_default_accel(), atc_accel_max) : atc_accel_max;
82
const float jerk_max = is_positive(g2.wp_nav.get_default_jerk()) ? g2.wp_nav.get_default_jerk() : accel_max;
83
84
// initialise position controller
85
g2.pos_control.set_limits(speed_max, accel_max, g2.attitude_control.get_turn_lat_accel_max(), jerk_max);
86
g2.pos_control.init();
87
88
// set the position controller reversed in case the camera is mounted on vehicle's back
89
g2.pos_control.set_reversed(rover.precland.get_orient() == 4);
90
91
// construct unit vector in the desired direction from where we want the vehicle to approach the dock
92
// this helps to dock the vehicle head-on even when we enter the dock mode at an angle towards the dock
93
_desired_heading_NE = Vector2f{cosf(radians(desired_dir)), sinf(radians(desired_dir))};
94
95
_docking_complete = false;
96
97
return true;
98
}
99
100
void ModeDock::update()
101
{
102
// if docking is complete, rovers stop and boats loiter
103
if (_docking_complete) {
104
// rovers stop, boats loiter
105
// note that loiter update must be called after successfull initialisation on mode loiter
106
if (_loitering) {
107
// mode loiter must be initialised before calling update method
108
rover.mode_loiter.update();
109
} else {
110
stop_vehicle();
111
}
112
return;
113
}
114
115
const bool real_dock_in_sight = rover.precland.get_target_position_cm(_dock_pos_rel_origin_cm);
116
Vector2f dock_pos_rel_vehicle_cm;
117
if (!calc_dock_pos_rel_vehicle_NE(dock_pos_rel_vehicle_cm)) {
118
g2.motors.set_throttle(0.0f);
119
g2.motors.set_steering(0.0f);
120
return;
121
}
122
123
_distance_to_destination = dock_pos_rel_vehicle_cm.length() * 0.01f;
124
125
// we force the vehicle to use real dock as target when we are too close to the dock
126
// note that heading correction does not work when we force real target
127
const bool force_real_target = _distance_to_destination < _force_real_target_limit_cm * 0.01f;
128
129
// if we are close enough to the dock or the target is not in sight when we strictly require it
130
// we mark the docking to be completed so that the vehicle stops
131
if (_distance_to_destination <= stopping_dist || (force_real_target && !real_dock_in_sight)) {
132
_docking_complete = true;
133
134
// send a one time notification to GCS
135
gcs().send_text(MAV_SEVERITY_INFO, "Dock: Docking complete");
136
137
// initialise mode loiter if it is a boat
138
if (rover.is_boat()) {
139
// if we fail to enter, we set _loitering to false
140
_loitering = rover.mode_loiter.enter();
141
}
142
return;
143
}
144
145
Vector2f target_cm = _dock_pos_rel_origin_cm;
146
147
// ***** HEADING CORRECTION *****
148
// to make to vehicle dock from a given direction we simulate a virtual moving target on the line of approach
149
// this target is always at DOCK_HDG_COR_WT times the distance from dock to vehicle (along the line of approach)
150
// For e.g., if the dock is 100 m away form dock, DOCK_HDG_COR_WT is 0.75
151
// then the position target is 75 m from the dock, i.e., 25 m from the vehicle
152
// as the vehicle tries to reach this target, this target appears to move towards the dock and at last it is sandwiched b/w dock and vehicle
153
// since this target is moving along desired direction of approach, the vehicle also comes on that line while following it
154
if (!force_real_target && hdg_corr_enable) {
155
const float correction_vec_mag = hdg_corr_weight * dock_pos_rel_vehicle_cm.projected(_desired_heading_NE).length();
156
target_cm = _dock_pos_rel_origin_cm - _desired_heading_NE * correction_vec_mag;
157
}
158
159
const Vector2p target_pos { target_cm.topostype() * 0.01 };
160
g2.pos_control.input_pos_target(target_pos, rover.G_Dt);
161
g2.pos_control.update(rover.G_Dt);
162
163
// get desired speed and turn rate from pos_control
164
float desired_speed = g2.pos_control.get_desired_speed();
165
float desired_turn_rate = g2.pos_control.get_desired_turn_rate_rads();
166
167
// slow down the vehicle as we approach the dock
168
desired_speed = apply_slowdown(desired_speed);
169
170
// run steering and throttle controllers
171
calc_steering_from_turn_rate(desired_turn_rate);
172
calc_throttle(desired_speed, true);
173
174
#if HAL_LOGGING_ENABLED
175
// @LoggerMessage: DOCK
176
// @Description: Dock mode target information
177
// @Field: TimeUS: Time since system startup
178
// @Field: DockX: Docking Station position, X-Axis
179
// @Field: DockY: Docking Station position, Y-Axis
180
// @Field: DockDist: Distance to docking station
181
// @Field: TPosX: Current Position Target, X-Axis
182
// @Field: TPosY: Current Position Target, Y-Axis
183
// @Field: DSpd: Desired speed
184
// @Field: DTrnRt: Desired Turn Rate
185
186
AP::logger().WriteStreaming(
187
"DOCK",
188
"TimeUS,DockX,DockY,DockDist,TPosX,TPosY,DSpd,DTrnRt",
189
"smmmmmnE",
190
"FBB0BB00",
191
"Qfffffff",
192
AP_HAL::micros64(),
193
_dock_pos_rel_origin_cm.x,
194
_dock_pos_rel_origin_cm.y,
195
_distance_to_destination,
196
target_cm.x,
197
target_cm.y,
198
desired_speed,
199
desired_turn_rate);
200
#endif
201
}
202
203
float ModeDock::apply_slowdown(float desired_speed)
204
{
205
const float dock_speed_slowdown_lmt = 0.5f;
206
207
// no slowdown for speed below dock_speed_slowdown_lmt
208
if (fabsf(desired_speed) < dock_speed_slowdown_lmt) {
209
return desired_speed;
210
}
211
212
Vector3f target_vec_rel_vehicle_NED;
213
if(!calc_dock_pos_rel_vehicle_NE(target_vec_rel_vehicle_NED.xy())) {
214
return desired_speed;
215
}
216
217
const Matrix3f &body_to_ned = AP::ahrs().get_rotation_body_to_ned();
218
Vector3f target_vec_body = body_to_ned.mul_transpose(target_vec_rel_vehicle_NED);
219
const float target_error_cm = fabsf(target_vec_body.y);
220
float error_ratio = target_error_cm / _acceptable_pos_error_cm;
221
error_ratio = constrain_float(error_ratio, 0.0f, 1.0f);
222
223
const float dock_slow_dist_max_m = 15.0f;
224
const float dock_slow_dist_min_m = 5.0f;
225
// approach slowdown is not applied when the vehicle is more than dock_slow_dist_max meters away
226
// within dock_slow_dist_max and dock_slow_dist_min the weight of the slowdown increases linearly
227
// once the vehicle reaches dock_slow_dist_min the slowdown weight becomes 1
228
float slowdown_weight = 1 - (target_vec_body.x * 0.01f - dock_slow_dist_min_m) / (dock_slow_dist_max_m - dock_slow_dist_min_m);
229
slowdown_weight = constrain_float(slowdown_weight, 0.0f, 1.0f);
230
231
desired_speed = MAX(dock_speed_slowdown_lmt, fabsf(desired_speed) * (1 - error_ratio * slowdown_weight));
232
233
// restrict speed to avoid going beyond stopping distance
234
desired_speed = MIN(desired_speed, safe_sqrt(2 * fabsf(_distance_to_destination - stopping_dist) * g2.pos_control.get_accel_max()));
235
236
// we worked on absolute value of speed before
237
// make it negative again if reversed
238
if (g2.pos_control.get_reversed()) {
239
desired_speed *= -1;
240
}
241
242
return desired_speed;
243
}
244
245
// calculate position of dock relative to the vehicle
246
// we need this method here because there can be a window during heading correction when we might lose the target
247
// during that window precland won't be able to give us this vector
248
// we can calculate it based on most recent value from precland because the dock is assumed stationary wrt ekf origin
249
bool ModeDock::calc_dock_pos_rel_vehicle_NE(Vector2f &dock_pos_rel_vehicle) const {
250
Vector2f current_pos_m;
251
if (!AP::ahrs().get_relative_position_NE_origin(current_pos_m)) {
252
return false;
253
}
254
255
dock_pos_rel_vehicle = _dock_pos_rel_origin_cm - current_pos_m * 100.0f;
256
return true;
257
}
258
#endif // MODE_DOCK_ENABLED
259
260