LP-601 Use normal altitude sign above home for AboveAltitude condition parameter
[librepilot.git] / ground / gcs / src / plugins / opmap / opmap_edit_waypoint_dialog.cpp
blobdbbed9ba5cc0f48721862aa33bdaddea10ef3583
1 /**
2 ******************************************************************************
4 * @file opmap_edit_waypoint_dialog.cpp
5 * @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2017.
6 * The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
7 * @addtogroup GCSPlugins GCS Plugins
8 * @{
9 * @addtogroup OPMapPlugin OpenPilot Map Plugin
10 * @{
11 * @brief The OpenPilot Map plugin
12 *****************************************************************************/
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 3 of the License, or
17 * (at your option) any later version.
19 * This program is distributed in the hope that it will be useful, but
20 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
21 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 * for more details.
24 * You should have received a copy of the GNU General Public License along
25 * with this program; if not, write to the Free Software Foundation, Inc.,
26 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 #include "opmap_edit_waypoint_dialog.h"
30 #include "ui_opmap_edit_waypoint_dialog.h"
31 #include "opmapcontrol/opmapcontrol.h"
32 #include "widgetdelegates.h"
33 // *********************************************************************
35 // constructor
36 opmap_edit_waypoint_dialog::opmap_edit_waypoint_dialog(QWidget *parent, QAbstractItemModel *model, QItemSelectionModel *selection) :
37 QWidget(parent, Qt::Window), model(model), itemSelection(selection),
38 ui(new Ui::opmap_edit_waypoint_dialog)
40 ui->setupUi(this);
41 ui->pushButtonPrevious->setEnabled(false);
42 ui->pushButtonNext->setEnabled(false);
43 connect(ui->checkBoxLocked, SIGNAL(toggled(bool)), this, SLOT(enableEditWidgets(bool)));
44 connect(ui->cbMode, SIGNAL(currentIndexChanged(int)), this, SLOT(setupModeWidgets()));
45 connect(ui->cbCondition, SIGNAL(currentIndexChanged(int)), this, SLOT(setupConditionWidgets()));
46 connect(ui->pushButtonCancel, SIGNAL(clicked()), this, SLOT(pushButtonCancel_clicked()));
47 MapDataDelegate::loadComboBox(ui->cbMode, flightDataModel::MODE);
48 MapDataDelegate::loadComboBox(ui->cbCondition, flightDataModel::CONDITION);
49 MapDataDelegate::loadComboBox(ui->cbCommand, flightDataModel::COMMAND);
50 mapper = new QDataWidgetMapper(this);
52 mapper->setItemDelegate(new MapDataDelegate(this));
53 connect(mapper, SIGNAL(currentIndexChanged(int)), this, SLOT(currentIndexChanged(int)));
54 mapper->setModel(model);
55 mapper->setSubmitPolicy(QDataWidgetMapper::AutoSubmit);
56 mapper->addMapping(ui->checkBoxLocked, flightDataModel::LOCKED);
57 mapper->addMapping(ui->doubleSpinBoxLatitude, flightDataModel::LATPOSITION);
58 mapper->addMapping(ui->doubleSpinBoxLongitude, flightDataModel::LNGPOSITION);
59 mapper->addMapping(ui->doubleSpinBoxAltitude, flightDataModel::ALTITUDE);
60 mapper->addMapping(ui->lineEditDescription, flightDataModel::WPDESCRIPTION);
61 mapper->addMapping(ui->checkBoxRelative, flightDataModel::ISRELATIVE);
62 mapper->addMapping(ui->doubleSpinBoxBearing, flightDataModel::BEARELATIVE);
63 mapper->addMapping(ui->doubleSpinBoxVelocity, flightDataModel::VELOCITY);
64 mapper->addMapping(ui->doubleSpinBoxDistance, flightDataModel::DISRELATIVE);
65 mapper->addMapping(ui->doubleSpinBoxRelativeAltitude, flightDataModel::ALTITUDERELATIVE);
66 mapper->addMapping(ui->cbMode, flightDataModel::MODE);
67 mapper->addMapping(ui->dsb_modeParam1, flightDataModel::MODE_PARAMS0);
68 mapper->addMapping(ui->dsb_modeParam2, flightDataModel::MODE_PARAMS1);
69 mapper->addMapping(ui->dsb_modeParam3, flightDataModel::MODE_PARAMS2);
70 mapper->addMapping(ui->dsb_modeParam4, flightDataModel::MODE_PARAMS3);
72 mapper->addMapping(ui->cbCondition, flightDataModel::CONDITION);
73 mapper->addMapping(ui->dsb_condParam1, flightDataModel::CONDITION_PARAMS0);
74 mapper->addMapping(ui->dsb_condParam2, flightDataModel::CONDITION_PARAMS1);
75 mapper->addMapping(ui->dsb_condParam3, flightDataModel::CONDITION_PARAMS2);
76 mapper->addMapping(ui->dsb_condParam4, flightDataModel::CONDITION_PARAMS0);
78 mapper->addMapping(ui->cbCommand, flightDataModel::COMMAND);
79 mapper->addMapping(ui->sbJump, flightDataModel::JUMPDESTINATION);
80 mapper->addMapping(ui->sbError, flightDataModel::ERRORDESTINATION);
81 connect(itemSelection, SIGNAL(currentRowChanged(QModelIndex, QModelIndex)), this, SLOT(currentRowChanged(QModelIndex, QModelIndex)));
83 ui->descriptionCommandLabel->setText(tr("<p>The Command specifies the transition to the next state (aka waypoint), as well as when it "
84 "is to be executed. This command will always switch to another waypoint instantly, but which waypoint depends on the Condition.</p>"
85 "<p>The JumpDestination is the waypoint to jump to in unconditional or conditional jumps.</p>"));
87 ui->descriptionErrorDestinationLabel->setText(tr("<p>The ErrorDestination is special; it allows exception handling based on the PathFollower. "
88 "If the PathFollower indicates that it is unable to execute Mode, it indicates this error in the PathStatus UAVObject. "
89 "If that happens, then the sequence of waypoints is interrupted and the waypoint in ErrorDestination becomes the Active Waypoint. "
90 "A thinkable use case for this functionality would be to steer towards a safe emergency landing site if the engine fails.</p>"));
93 void opmap_edit_waypoint_dialog::currentIndexChanged(int index)
95 ui->lbNumber->setText(QString::number(index + 1));
96 ui->wpNumberSpinBox->setValue(index + 1);
98 bool isMin = (index == 0);
99 bool isMax = ((index + 1) == mapper->model()->rowCount());
100 ui->pushButtonPrevious->setEnabled(!isMin);
101 ui->pushButtonNext->setEnabled(!isMax);
103 QModelIndex idx = mapper->model()->index(index, 0);
104 if (index == itemSelection->currentIndex().row()) {
105 return;
107 itemSelection->clear();
108 itemSelection->setCurrentIndex(idx, QItemSelectionModel::Select | QItemSelectionModel::Rows);
111 opmap_edit_waypoint_dialog::~opmap_edit_waypoint_dialog()
113 delete ui;
116 void opmap_edit_waypoint_dialog::setupModeWidgets()
118 MapDataDelegate::ModeOptions mode = (MapDataDelegate::ModeOptions)ui->cbMode->itemData(ui->cbMode->currentIndex()).toInt();
120 ui->modeParam1->setText("");
121 ui->modeParam2->setText("");
122 ui->modeParam3->setText("");
123 ui->modeParam4->setText("");
124 ui->modeParam1->setEnabled(false);
125 ui->modeParam2->setEnabled(false);
126 ui->modeParam3->setEnabled(false);
127 ui->modeParam4->setEnabled(false);
128 ui->dsb_modeParam1->setEnabled(false);
129 ui->dsb_modeParam2->setEnabled(false);
130 ui->dsb_modeParam3->setEnabled(false);
131 ui->dsb_modeParam4->setEnabled(false);
133 switch (mode) {
134 case MapDataDelegate::MODE_GOTOENDPOINT:
135 ui->descriptionModeLabel->setText(tr("<p>The Autopilot will try to hold position at a fixed end-coordinate. "
136 "If elsewhere, the craft will steer towards the coordinate but not "
137 "necessarily in a straight line as drift will not be compensated.</p>"));
138 break;
139 case MapDataDelegate::MODE_FOLLOWVECTOR:
140 ui->descriptionModeLabel->setText(tr("<p>The Autopilot will attempt to stay on a defined trajectory from the previous waypoint "
141 "to the current one. Any deviation from this path, for example by wind, will be corrected. "
142 "This is the best and obvious choice for direct straight-line (rhumb line) navigation in any vehicle.</p>"));
143 break;
144 case MapDataDelegate::MODE_CIRCLERIGHT:
145 ui->descriptionModeLabel->setText(tr("<p>The Autopilot will attempt to fly a circular trajectory around a waypoint. "
146 "The curve radius is defined by the distance from the previous waypoint, therefore setting the coordinate "
147 "of the waypoint perpendicular to the previous flight path leg (and on the side the vehicle is supposed to turn toward!) "
148 "will lead to the smoothest possible transition.</p><p>Staying in FlyCircle for a prolonged time will lead to a circular "
149 "loiter trajectory around a waypoint, but this mode can be used in combination with the PointingTowardsNext-EndCondition "
150 "to stay on the curved trajectory until the vehicle is moving towards the next waypoint, which allows for very controlled "
151 "turns in flight paths.</p>"));
152 break;
153 case MapDataDelegate::MODE_CIRCLELEFT:
154 ui->descriptionModeLabel->setText(tr("<p>The Autopilot will attempt to fly a circular trajectory around a waypoint. "
155 "The curve radius is defined by the distance from the previous waypoint, therefore setting the coordinate "
156 "of the waypoint perpendicular to the previous flight path leg (and on the side the vehicle is supposed to turn toward!) "
157 "will lead to the smoothest possible transition.</p><p>Staying in FlyCircle for a prolonged time will lead to a circular "
158 "loiter trajectory around a waypoint, but this mode can be used in combination with the PointingTowardsNext-EndCondition "
159 "to stay on the curved trajectory until the vehicle is moving towards the next waypoint, which allows for very controlled "
160 "turns in flight paths.</p>"));
161 break;
162 case MapDataDelegate::MODE_DISARMALARM:
163 ui->descriptionModeLabel->setText(tr("<p>The Autopilot is instructed to force a CRITICAL PathFollower alarm. A PathFollower alarm of type CRITICAL "
164 "is supposed to automatically set the vehicle to DISARMED and thus disable the engines, cut fuel supply, ...</p><p>"
165 "The PathFollower can do this during any mode in case of emergency, but through this mode the PathPlanner "
166 "can force this behavior, for example after a landing.</p>"));
167 break;
168 case MapDataDelegate::MODE_AUTOTAKEOFF:
169 // FixedWing do not use parameters, vertical velocity can be set for multirotors as param0
170 ui->modeParam1->setText("Speed (m/s):");
171 ui->modeParam1->setEnabled(true);
172 ui->dsb_modeParam1->setEnabled(true);
173 ui->descriptionModeLabel->setText(tr("<p>The Autopilot will engage a hardcoded, fully automated takeoff sequence. "
174 "Using a fixed attitude, heading towards the destination waypoint for a fixed wing or "
175 "a vertical climb for a multirotor.</p>"
176 "<p>Vertical speed in meters/second, for multirotors. (Will be around 0.6m/s)</p>"));
177 break;
178 case MapDataDelegate::MODE_LAND:
179 // FixedWing do not use parameters, vertical velocity can be set for multirotors as param0 (0.1/0.6m/s range)
180 ui->modeParam1->setText("Speed (m/s):");
181 ui->modeParam1->setEnabled(true);
182 ui->dsb_modeParam1->setEnabled(true);
183 ui->descriptionModeLabel->setText(tr("<p>The Autopilot will engage a hardcoded, fully automated landing sequence. "
184 "Using a fixed attitude, heading towards the destination waypoint for a fixed wing or "
185 "a vertical descent for a multirotor.</p>"
186 "<p>Vertical speed in meters/second, for multirotors. (Will be around 0.6m/s)</p>"));
187 break;
188 case MapDataDelegate::MODE_BRAKE:
189 ui->descriptionModeLabel->setText(tr("<p>This mode is used internally by assisted flight modes with multirotors to slow down the velocity.</p>"));
190 break;
191 case MapDataDelegate::MODE_VELOCITY:
192 ui->descriptionModeLabel->setText(tr("<p>This mode is used internally by assisted flight modes with multirotors to maintain a velocity in 3D space.</p>"));
193 break;
194 case MapDataDelegate::MODE_FIXEDATTITUDE:
195 ui->modeParam1->setText("Roll:");
196 ui->modeParam2->setText("Pitch:");
197 ui->modeParam3->setText("Yaw:");
198 ui->modeParam4->setText("Thrust:");
199 ui->modeParam1->setEnabled(true);
200 ui->modeParam2->setEnabled(true);
201 ui->modeParam3->setEnabled(true);
202 ui->modeParam4->setEnabled(true);
203 ui->dsb_modeParam1->setEnabled(true);
204 ui->dsb_modeParam2->setEnabled(true);
205 ui->dsb_modeParam3->setEnabled(true);
206 ui->dsb_modeParam4->setEnabled(true);
207 ui->descriptionModeLabel->setText(tr("<p>The Autopilot will play dumb and simply instruct the Stabilization Module to assume a certain Roll, Pitch angle "
208 "and optionally a Yaw rotation rate and Thrust setting. This allows for very simple auto-takeoff and "
209 "auto-landing maneuvers.</p>"
210 "<p>Roll(+-180°) and Pitch (+-90°) angles in degrees</p>"
211 "<p>Yaw rate in deg/s</p>"
212 "<p>Thrust from 0 to 1</p>"));
213 break;
214 case MapDataDelegate::MODE_SETACCESSORY:
215 ui->modeParam1->setText("Acc.channel:");
216 ui->modeParam2->setText("Value:");
217 ui->modeParam1->setEnabled(true);
218 ui->modeParam2->setEnabled(true);
219 ui->dsb_modeParam1->setEnabled(true);
220 ui->dsb_modeParam2->setEnabled(true);
221 ui->descriptionModeLabel->setText(tr("<p>Not yet implemented.</p>"));
222 // ui->descriptionModeLabel->setText(tr("<p>In this mode, the PathFollower is supposed to inject a specific value (-1|0|+1 range) into an AccessoryDesired channel. "
223 // "This would allow one to control arbitrary auxilliary components from the PathPlanner like flaps and landing gear.</p>"));
224 break;
225 default:
226 ui->descriptionModeLabel->setText("");
227 break;
231 void opmap_edit_waypoint_dialog::setupConditionWidgets()
233 MapDataDelegate::EndConditionOptions mode = (MapDataDelegate::EndConditionOptions)ui->cbCondition->itemData(ui->cbCondition->currentIndex()).toInt();
235 ui->condParam1->setText("");
236 ui->condParam2->setText("");
237 ui->condParam3->setText("");
238 ui->condParam4->setText("");
239 ui->condParam1->setEnabled(false);
240 ui->condParam2->setEnabled(false);
241 ui->condParam3->setEnabled(false);
242 ui->condParam4->setEnabled(false);
243 ui->dsb_condParam1->setEnabled(false);
244 ui->dsb_condParam2->setEnabled(false);
245 ui->dsb_condParam3->setEnabled(false);
246 ui->dsb_condParam4->setEnabled(false);
248 switch (mode) {
249 case MapDataDelegate::ENDCONDITION_NONE:
250 ui->descriptionConditionLabel->setText(tr("<p>This condition is always false. A WaypointAction with EndCondition to None will stay in "
251 "its mode until forever, or until an Error in the PathFollower triggers the ErrorJump. (For example out of fuel!)</p>"));
252 break;
253 case MapDataDelegate::ENDCONDITION_IMMEDIATE:
254 ui->descriptionConditionLabel->setText(tr("<p>Opposite to the None condition, the immediate condition is always true.</p>"));
255 break;
256 case MapDataDelegate::ENDCONDITION_PYTHONSCRIPT:
257 ui->descriptionConditionLabel->setText(tr("<p>Not yet implemented.</p>"));
258 break;
259 case MapDataDelegate::ENDCONDITION_TIMEOUT:
260 ui->condParam1->setEnabled(true);
261 ui->dsb_condParam1->setEnabled(true);
262 ui->condParam1->setText("Timeout (s)");
263 ui->descriptionConditionLabel->setText(tr("<p>The Timeout condition measures time this waypoint is active (in seconds).</p>"));
264 break;
265 case MapDataDelegate::ENDCONDITION_DISTANCETOTARGET:
266 ui->condParam1->setEnabled(true);
267 ui->condParam2->setEnabled(true);
268 ui->dsb_condParam1->setEnabled(true);
269 ui->dsb_condParam2->setEnabled(true);
270 ui->condParam1->setText("Distance (m):");
271 ui->condParam2->setText("Flag:");
272 ui->descriptionConditionLabel->setText(tr("<p>The DistanceToTarget condition measures the distance to a waypoint, returns true if closer.</p>"
273 "<p>Flag: <b>0</b>= 2D distance, <b>1</b>= 3D distance</p>"));
274 break;
275 case MapDataDelegate::ENDCONDITION_LEGREMAINING:
276 ui->condParam1->setEnabled(true);
277 ui->dsb_condParam1->setEnabled(true);
278 ui->condParam1->setText("Relative Distance:");
279 ui->descriptionConditionLabel->setText(tr("<p>The LegRemaining condition measures how far the pathfollower got on a linear path segment, returns true "
280 "if closer to destination(path more complete).</p>"
281 "<p><b>0</b>=complete, <b>1</b>=just starting</p>"));
282 break;
283 case MapDataDelegate::ENDCONDITION_BELOWERROR:
284 ui->condParam1->setEnabled(true);
285 ui->dsb_condParam1->setEnabled(true);
286 ui->condParam1->setText("Error margin (m):");
287 ui->descriptionConditionLabel->setText(tr("<p>The BelowError condition measures the error on a path segment, returns true if error is below margin in meters.</p>"));
288 break;
289 case MapDataDelegate::ENDCONDITION_ABOVEALTITUDE:
290 ui->condParam1->setEnabled(true);
291 ui->dsb_condParam1->setEnabled(true);
292 ui->condParam1->setText("Altitude (m):");
293 ui->descriptionConditionLabel->setText(tr("<p>The AboveAltitude condition measures the flight altitude relative to home position, returns true if above critical altitude.</p>"));
294 break;
295 case MapDataDelegate::ENDCONDITION_ABOVESPEED:
296 ui->condParam1->setEnabled(true);
297 ui->condParam2->setEnabled(true);
298 ui->dsb_condParam1->setEnabled(true);
299 ui->dsb_condParam2->setEnabled(true);
300 ui->condParam1->setText("Speed (m/s):");
301 ui->condParam2->setText("Flag:");
302 ui->descriptionConditionLabel->setText(tr("<p>The AboveSpeed measures the movement speed(3D), returns true if above critical speed</p>"
303 "<p>Speed in meters / second</p>"
304 "<p>Flag: <b>0</b>= groundspeed <b>1</b>= airspeed</p>"));
305 break;
306 case MapDataDelegate::ENDCONDITION_POINTINGTOWARDSNEXT:
307 ui->condParam1->setEnabled(true);
308 ui->dsb_condParam1->setEnabled(true);
309 ui->condParam1->setText("Degrees:");
310 ui->descriptionConditionLabel->setText(tr("<p>The PointingTowardsNext condition measures the horizontal movement vector direction relative "
311 "to the next waypoint regardless whether this waypoint will ever be active "
312 "(Command could jump to a different waypoint on true).</p><p>This is useful for curve segments where "
313 "the craft should stop circling when facing a certain way(usually the next waypoint), "
314 "returns true if within a certain angular margin in degrees.</p>"));
315 break;
316 default:
317 ui->descriptionConditionLabel->setText("");
318 break;
322 void opmap_edit_waypoint_dialog::editWaypoint(mapcontrol::WayPointItem *waypoint_item)
324 if (!waypoint_item) {
325 return;
327 if (!isVisible()) {
328 show();
330 if (isMinimized()) {
331 showNormal();
333 if (!isActiveWindow()) {
334 activateWindow();
336 raise();
337 setFocus(Qt::OtherFocusReason);
338 mapper->setCurrentIndex(waypoint_item->Number());
341 void opmap_edit_waypoint_dialog::on_pushButtonOK_clicked()
343 mapper->submit();
344 close();
347 void opmap_edit_waypoint_dialog::pushButtonCancel_clicked()
349 mapper->revert();
350 close();
353 void opmap_edit_waypoint_dialog::on_pushButtonPrevious_clicked()
355 mapper->toPrevious();
358 void opmap_edit_waypoint_dialog::on_pushButtonNext_clicked()
360 mapper->toNext();
363 void opmap_edit_waypoint_dialog::on_pushButtonApply_clicked()
365 mapper->submit();
368 void opmap_edit_waypoint_dialog::enableEditWidgets(bool value)
370 QWidget *w;
372 foreach(QWidget * obj, this->findChildren<QWidget *>()) {
373 w = qobject_cast<QComboBox *>(obj);
374 if (w) {
375 w->setEnabled(!value);
377 w = qobject_cast<QLineEdit *>(obj);
378 if (w) {
379 w->setEnabled(!value);
381 w = qobject_cast<QDoubleSpinBox *>(obj);
382 if (w) {
383 w->setEnabled(!value);
385 w = qobject_cast<QCheckBox *>(obj);
386 if (w && w != ui->checkBoxLocked) {
387 w->setEnabled(!value);
389 w = qobject_cast<QSpinBox *>(obj);
390 if (w) {
391 w->setEnabled(!value);
396 void opmap_edit_waypoint_dialog::currentRowChanged(QModelIndex current, QModelIndex previous)
398 Q_UNUSED(previous);
400 mapper->setCurrentIndex(current.row());