LP-572 Add buttons to the right: Save, clear trail, PathPlan editor, Home set
[librepilot.git] / ground / gcs / src / plugins / opmap / modeluavoproxy.cpp
bloba9a13528ac4fff1c5ddfb6dcf4d3f4441113aedc
1 /**
2 ******************************************************************************
4 * @file modeluavproxy.cpp
5 * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
6 * @addtogroup GCSPlugins GCS Plugins
7 * @{
8 * @addtogroup OPMapPlugin OpenPilot Map Plugin
9 * @{
10 * @brief The OpenPilot Map plugin
11 *****************************************************************************/
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 3 of the License, or
16 * (at your option) any later version.
18 * This program is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 * for more details.
23 * You should have received a copy of the GNU General Public License along
24 * with this program; if not, write to the Free Software Foundation, Inc.,
25 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 #include "modeluavoproxy.h"
28 #include "extensionsystem/pluginmanager.h"
29 #include "uavobjecthelper.h"
30 #include "uavobjectmanager.h"
32 #include <QProgressDialog>
33 #include <math.h>
35 ModelUavoProxy::ModelUavoProxy(QObject *parent, flightDataModel *model) : QObject(parent), myModel(model)
37 ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
39 Q_ASSERT(pm != NULL);
41 objMngr = pm->getObject<UAVObjectManager>();
42 Q_ASSERT(objMngr != NULL);
45 void ModelUavoProxy::sendPathPlan()
47 modelToObjects();
49 PathPlan *pathPlan = PathPlan::GetInstance(objMngr);
51 const int waypointCount = pathPlan->getWaypointCount();
52 const int actionCount = pathPlan->getPathActionCount();
54 QProgressDialog progress(tr("Sending the path plan to the board... "), "", 0, 1 + waypointCount + actionCount);
55 progress.setWindowModality(Qt::WindowModal);
56 progress.setCancelButton(NULL);
57 progress.show();
59 UAVObjectUpdaterHelper updateHelper;
61 // send PathPlan
62 bool success = (updateHelper.doObjectAndWait(pathPlan) == UAVObjectUpdaterHelper::SUCCESS);
63 progress.setValue(1);
65 if (success) {
66 // send Waypoint instances
67 qDebug() << "sending" << waypointCount << "waypoints";
68 for (int i = 0; i < waypointCount; ++i) {
69 Waypoint *waypoint = Waypoint::GetInstance(objMngr, i);
70 success = (updateHelper.doObjectAndWait(waypoint) == UAVObjectUpdaterHelper::SUCCESS);
71 if (!success) {
72 break;
74 progress.setValue(progress.value() + 1);
78 if (success) {
79 // send PathAction instances
80 qDebug() << "sending" << actionCount << "path actions";
81 for (int i = 0; i < actionCount; ++i) {
82 PathAction *action = PathAction::GetInstance(objMngr, i);
83 success = (updateHelper.doObjectAndWait(action) == UAVObjectUpdaterHelper::SUCCESS);
84 if (!success) {
85 break;
87 progress.setValue(progress.value() + 1);
91 qDebug() << "ModelUavoProxy::pathPlanSent - completed" << success;
92 if (!success) {
93 QMessageBox::critical(NULL, tr("Sending Path Plan Failed!"), tr("Failed to send the path plan to the board."));
96 progress.close();
99 void ModelUavoProxy::receivePathPlan()
101 QProgressDialog progress(tr("Receiving the path plan from the board... "), "", 0, 0);
103 progress.setWindowModality(Qt::WindowModal);
104 progress.setCancelButton(NULL);
105 progress.show();
107 UAVObjectRequestHelper requestHelper;
109 PathPlan *pathPlan = PathPlan::GetInstance(objMngr);
110 bool success = (requestHelper.doObjectAndWait(pathPlan) == UAVObjectUpdaterHelper::SUCCESS);
112 const int waypointCount = pathPlan->getWaypointCount();
113 const int actionCount = pathPlan->getPathActionCount();
115 progress.setMaximum(1 + waypointCount + actionCount);
116 progress.setValue(1);
118 if (success && (waypointCount > objMngr->getNumInstances(Waypoint::OBJID))) {
119 // allocate needed Waypoint instances
120 Waypoint *waypoint = new Waypoint;
121 waypoint->initialize(waypointCount - 1, waypoint->getMetaObject());
122 success = objMngr->registerObject(waypoint);
124 if (success) {
125 // request Waypoint instances
126 qDebug() << "requesting" << waypointCount << "waypoints";
127 for (int i = 0; i < waypointCount; ++i) {
128 Waypoint *waypoint = Waypoint::GetInstance(objMngr, i);
129 success = (requestHelper.doObjectAndWait(waypoint) == UAVObjectRequestHelper::SUCCESS);
130 if (!success) {
131 break;
133 progress.setValue(progress.value() + 1);
137 if (success && (actionCount > objMngr->getNumInstances(PathAction::OBJID))) {
138 // allocate needed PathAction instances
139 PathAction *action = new PathAction;
140 action->initialize(actionCount - 1, action->getMetaObject());
141 success = objMngr->registerObject(action);
143 if (success) {
144 // request PathAction isntances
145 qDebug() << "requesting" << actionCount << "path actions";
146 for (int i = 0; i < actionCount; ++i) {
147 PathAction *action = PathAction::GetInstance(objMngr, i);
148 success = (requestHelper.doObjectAndWait(action) == UAVObjectRequestHelper::SUCCESS);
149 if (!success) {
150 break;
152 progress.setValue(progress.value() + 1);
156 qDebug() << "ModelUavoProxy::pathPlanReceived - completed" << success;
157 if (success) {
158 objectsToModel();
159 } else {
160 QMessageBox::critical(NULL, tr("Receiving Path Plan Failed!"), tr("Failed to receive the path plan from the board."));
163 progress.close();
166 // update waypoint and path actions UAV objects
168 // waypoints are unique and each waypoint has an entry in the UAV waypoint list
170 // a path action can be referenced by multiple waypoints
171 // waypoints reference path action by their index in the UAV path action list
172 // the compression of path actions happens here.
173 // (compression consists in keeping only one instance of similar path actions)
175 // the UAV waypoint list and path action list are probably not empty, so we try to reuse existing instances
176 bool ModelUavoProxy::modelToObjects()
178 qDebug() << "ModelUAVProxy::modelToObjects";
180 // track number of path actions
181 int actionCount = 0;
183 // iterate over waypoints
184 int waypointCount = myModel->rowCount();
185 for (int i = 0; i < waypointCount; ++i) {
186 // Path Actions
188 // create action to use as a search criteria
189 // this object does not need to be deleted as it will either be added to the managed list or deleted later
190 PathAction *action = new PathAction;
192 // get model data
193 PathAction::DataFields actionData = action->getData();
194 modelToPathAction(i, actionData);
196 // see if that path action has already been added in this run
197 PathAction *foundAction = findPathAction(actionData, actionCount);
198 // TODO this test needs a consistency check as it is unsafe.
199 // if the find method is buggy and returns false positives then the flight plan sent to the uav is broken!
200 // the find method should do a "binary" compare instead of a field by field compare
201 // if a field is added everywhere and not in the compare method then you can start having false positives
202 if (!foundAction) {
203 // create or reuse an action instance
204 action = createPathAction(actionCount, action);
205 actionCount++;
207 // update UAVObject
208 action->setData(actionData);
209 } else {
210 action->deleteLater();
211 action = foundAction;
212 qDebug() << "ModelUAVProxy::modelToObjects - found action instance :" << action->getInstID();
215 // Waypoints
217 // create or reuse a waypoint instance
218 Waypoint *waypoint = createWaypoint(i, NULL);
219 Q_ASSERT(waypoint);
221 // get model data
222 Waypoint::DataFields waypointData = waypoint->getData();
223 modelToWaypoint(i, waypointData);
225 // connect waypoint to path action
226 waypointData.Action = action->getInstID();
228 // update UAVObject
229 waypoint->setData(waypointData);
232 // Put "safe" values in unused waypoint and path action objects
233 if (waypointCount < objMngr->getNumInstances(Waypoint::OBJID)) {
234 for (int i = waypointCount; i < objMngr->getNumInstances(Waypoint::OBJID); ++i) {
235 // TODO
238 if (actionCount < objMngr->getNumInstances(PathAction::OBJID)) {
239 for (int i = actionCount; i < objMngr->getNumInstances(PathAction::OBJID); ++i) {
240 // TODO
244 // Update PathPlan
245 PathPlan *pathPlan = PathPlan::GetInstance(objMngr);
246 PathPlan::DataFields pathPlanData = pathPlan->getData();
248 pathPlanData.WaypointCount = waypointCount;
249 pathPlanData.PathActionCount = actionCount;
250 pathPlanData.Crc = computePathPlanCrc(waypointCount, actionCount);
252 pathPlan->setData(pathPlanData);
254 return true;
257 Waypoint *ModelUavoProxy::createWaypoint(int index, Waypoint *newWaypoint)
259 Waypoint *waypoint = NULL;
260 int count = objMngr->getNumInstances(Waypoint::OBJID);
262 if (index < count) {
263 // reuse object
264 qDebug() << "ModelUAVProxy::createWaypoint - reused waypoint instance :" << index << "/" << count;
265 waypoint = Waypoint::GetInstance(objMngr, index);
266 if (newWaypoint) {
267 newWaypoint->deleteLater();
269 } else if (index < count + 1) {
270 // create "next" object
271 qDebug() << "ModelUAVProxy::createWaypoint - created waypoint instance :" << index;
272 // TODO is there a limit to the number of wp?
273 waypoint = newWaypoint ? newWaypoint : new Waypoint;
274 waypoint->initialize(index, waypoint->getMetaObject());
275 objMngr->registerObject(waypoint);
276 } else {
277 // we can only create the "next" object
278 // TODO fail in a clean way :(
280 return waypoint;
283 PathAction *ModelUavoProxy::createPathAction(int index, PathAction *newAction)
285 PathAction *action = NULL;
286 int count = objMngr->getNumInstances(PathAction::OBJID);
288 if (index < count) {
289 // reuse object
290 qDebug() << "ModelUAVProxy::createPathAction - reused action instance :" << index << "/" << count;
291 action = PathAction::GetInstance(objMngr, index);
292 if (newAction) {
293 newAction->deleteLater();
295 } else if (index < count + 1) {
296 // create "next" object
297 qDebug() << "ModelUAVProxy::createPathAction - created action instance :" << index;
298 // TODO is there a limit to the number of path actions?
299 action = newAction ? newAction : new PathAction;
300 action->initialize(index, action->getMetaObject());
301 objMngr->registerObject(action);
302 } else {
303 // we can only create the "next" object
304 // TODO fail in a clean way :(
306 return action;
309 PathAction *ModelUavoProxy::findPathAction(const PathAction::DataFields &actionData, int actionCount)
311 int instancesCount = objMngr->getNumInstances(PathAction::OBJID);
312 int count = actionCount <= instancesCount ? actionCount : instancesCount;
314 for (int i = 0; i < count; ++i) {
315 PathAction *action = PathAction::GetInstance(objMngr, i);
316 Q_ASSERT(action);
317 if (!action) {
318 continue;
320 PathAction::DataFields fields = action->getData();
321 if (fields.Command == actionData.Command
322 && fields.ConditionParameters[0] == actionData.ConditionParameters[0]
323 && fields.ConditionParameters[1] == actionData.ConditionParameters[1]
324 && fields.ConditionParameters[2] == actionData.ConditionParameters[2]
325 && fields.EndCondition == actionData.EndCondition
326 && fields.ErrorDestination == actionData.ErrorDestination
327 && fields.JumpDestination == actionData.JumpDestination && fields.Mode == actionData.Mode
328 && fields.ModeParameters[0] == actionData.ModeParameters[0]
329 && fields.ModeParameters[1] == actionData.ModeParameters[1]
330 && fields.ModeParameters[2] == actionData.ModeParameters[2]) {
331 return action;
334 return NULL;
337 bool ModelUavoProxy::objectsToModel()
339 // build model from uav objects
340 // the list of objects can end with "garbage" instances due to previous flightpath
341 // they need to be ignored
343 PathPlan *pathPlan = PathPlan::GetInstance(objMngr);
344 PathPlan::DataFields pathPlanData = pathPlan->getData();
346 int waypointCount = pathPlanData.WaypointCount;
347 int actionCount = pathPlanData.PathActionCount;
349 // consistency check
350 if (waypointCount > objMngr->getNumInstances(Waypoint::OBJID)) {
351 QMessageBox::critical(NULL, tr("Path Plan Download Failed"), tr("Path plan way point count error !"));
352 return false;
354 if (actionCount > objMngr->getNumInstances(PathAction::OBJID)) {
355 QMessageBox::critical(NULL, tr("Path Plan Download Failed"), tr("Path plan path action count error !"));
356 return false;
358 if (pathPlanData.Crc != computePathPlanCrc(waypointCount, actionCount)) {
359 QMessageBox::critical(NULL, tr("Path Plan Upload Failed"), tr("Path plan CRC error !"));
360 return false;
363 int rowCount = myModel->rowCount();
364 if (waypointCount < rowCount) {
365 myModel->removeRows(waypointCount, rowCount - waypointCount);
366 } else if (waypointCount > rowCount) {
367 myModel->insertRows(rowCount, waypointCount - rowCount);
370 for (int i = 0; i < waypointCount; ++i) {
371 Waypoint *waypoint = Waypoint::GetInstance(objMngr, i);
372 Q_ASSERT(waypoint);
373 if (!waypoint) {
374 continue;
377 Waypoint::DataFields waypointData = waypoint->getData();
378 waypointToModel(i, waypointData);
380 PathAction *action = PathAction::GetInstance(objMngr, waypoint->getAction());
381 Q_ASSERT(action);
382 if (!action) {
383 continue;
386 PathAction::DataFields actionData = action->getData();
387 pathActionToModel(i, actionData);
389 return true;
392 void ModelUavoProxy::modelToWaypoint(int i, Waypoint::DataFields &data)
394 double distance, bearing, altitude, velocity;
396 QModelIndex index = myModel->index(i, flightDataModel::DISRELATIVE);
398 distance = myModel->data(index).toDouble();
399 index = myModel->index(i, flightDataModel::BEARELATIVE);
400 bearing = myModel->data(index).toDouble();
401 index = myModel->index(i, flightDataModel::ALTITUDERELATIVE);
402 altitude = myModel->data(index).toFloat();
403 index = myModel->index(i, flightDataModel::VELOCITY);
404 velocity = myModel->data(index).toFloat();
406 data.Position[Waypoint::POSITION_NORTH] = distance * cos(bearing / 180 * M_PI);
407 data.Position[Waypoint::POSITION_EAST] = distance * sin(bearing / 180 * M_PI);
408 data.Position[Waypoint::POSITION_DOWN] = -altitude;
409 data.Velocity = velocity;
412 void ModelUavoProxy::waypointToModel(int i, Waypoint::DataFields &data)
414 double distance = sqrt(data.Position[Waypoint::POSITION_NORTH] * data.Position[Waypoint::POSITION_NORTH] +
415 data.Position[Waypoint::POSITION_EAST] * data.Position[Waypoint::POSITION_EAST]);
417 double bearing = atan2(data.Position[Waypoint::POSITION_EAST], data.Position[Waypoint::POSITION_NORTH]) * 180 / M_PI;
419 if (bearing != bearing) {
420 bearing = 0;
423 double altitude = -data.Position[Waypoint::POSITION_DOWN];
425 QModelIndex index = myModel->index(i, flightDataModel::VELOCITY);
426 myModel->setData(index, data.Velocity);
427 index = myModel->index(i, flightDataModel::DISRELATIVE);
428 myModel->setData(index, distance);
429 index = myModel->index(i, flightDataModel::BEARELATIVE);
430 myModel->setData(index, bearing);
431 index = myModel->index(i, flightDataModel::ALTITUDERELATIVE);
432 myModel->setData(index, altitude);
435 void ModelUavoProxy::modelToPathAction(int i, PathAction::DataFields &data)
437 QModelIndex index = myModel->index(i, flightDataModel::MODE);
439 data.Mode = myModel->data(index).toInt();
440 index = myModel->index(i, flightDataModel::MODE_PARAMS0);
441 data.ModeParameters[0] = myModel->data(index).toFloat();
442 index = myModel->index(i, flightDataModel::MODE_PARAMS1);
443 data.ModeParameters[1] = myModel->data(index).toFloat();
444 index = myModel->index(i, flightDataModel::MODE_PARAMS2);
445 data.ModeParameters[2] = myModel->data(index).toFloat();
446 index = myModel->index(i, flightDataModel::MODE_PARAMS3);
447 data.ModeParameters[3] = myModel->data(index).toFloat();
448 index = myModel->index(i, flightDataModel::CONDITION);
449 data.EndCondition = myModel->data(index).toInt();
450 index = myModel->index(i, flightDataModel::CONDITION_PARAMS0);
451 data.ConditionParameters[0] = myModel->data(index).toFloat();
452 index = myModel->index(i, flightDataModel::CONDITION_PARAMS1);
453 data.ConditionParameters[1] = myModel->data(index).toFloat();
454 index = myModel->index(i, flightDataModel::CONDITION_PARAMS2);
455 data.ConditionParameters[2] = myModel->data(index).toFloat();
456 index = myModel->index(i, flightDataModel::CONDITION_PARAMS3);
457 data.ConditionParameters[3] = myModel->data(index).toFloat();
458 index = myModel->index(i, flightDataModel::COMMAND);
459 data.Command = myModel->data(index).toInt();
460 index = myModel->index(i, flightDataModel::JUMPDESTINATION);
461 data.JumpDestination = myModel->data(index).toInt() - 1;
462 index = myModel->index(i, flightDataModel::ERRORDESTINATION);
463 data.ErrorDestination = myModel->data(index).toInt() - 1;
466 void ModelUavoProxy::pathActionToModel(int i, PathAction::DataFields &data)
468 QModelIndex index = myModel->index(i, flightDataModel::ISRELATIVE);
470 myModel->setData(index, true);
472 index = myModel->index(i, flightDataModel::COMMAND);
473 myModel->setData(index, data.Command);
475 index = myModel->index(i, flightDataModel::CONDITION_PARAMS0);
476 myModel->setData(index, data.ConditionParameters[0]);
477 index = myModel->index(i, flightDataModel::CONDITION_PARAMS1);
478 myModel->setData(index, data.ConditionParameters[1]);
479 index = myModel->index(i, flightDataModel::CONDITION_PARAMS2);
480 myModel->setData(index, data.ConditionParameters[2]);
481 index = myModel->index(i, flightDataModel::CONDITION_PARAMS3);
482 myModel->setData(index, data.ConditionParameters[3]);
484 index = myModel->index(i, flightDataModel::CONDITION);
485 myModel->setData(index, data.EndCondition);
487 index = myModel->index(i, flightDataModel::ERRORDESTINATION);
488 myModel->setData(index, data.ErrorDestination + 1);
490 index = myModel->index(i, flightDataModel::JUMPDESTINATION);
491 myModel->setData(index, data.JumpDestination + 1);
493 index = myModel->index(i, flightDataModel::MODE);
494 myModel->setData(index, data.Mode);
496 index = myModel->index(i, flightDataModel::MODE_PARAMS0);
497 myModel->setData(index, data.ModeParameters[0]);
498 index = myModel->index(i, flightDataModel::MODE_PARAMS1);
499 myModel->setData(index, data.ModeParameters[1]);
500 index = myModel->index(i, flightDataModel::MODE_PARAMS2);
501 myModel->setData(index, data.ModeParameters[2]);
502 index = myModel->index(i, flightDataModel::MODE_PARAMS3);
503 myModel->setData(index, data.ModeParameters[3]);
506 quint8 ModelUavoProxy::computePathPlanCrc(int waypointCount, int actionCount)
508 quint8 crc = 0;
510 for (int i = 0; i < waypointCount; ++i) {
511 Waypoint *waypoint = Waypoint::GetInstance(objMngr, i);
512 crc = waypoint->updateCRC(crc);
514 for (int i = 0; i < actionCount; ++i) {
515 PathAction *action = PathAction::GetInstance(objMngr, i);
516 crc = action->updateCRC(crc);
518 return crc;