LP-572 Apply HomeLocation only when OK button pressed (ignored on Cancel)
[librepilot.git] / ground / gcs / src / plugins / opmap / opmapgadgetwidget.cpp
blob5bfc300c3dd06ae390e75768c71245eed8bf2955
1 /**
2 ******************************************************************************
4 * @file opmapgadgetwidget.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
28 #define USE_PATHPLANNER
30 #include "opmapgadgetwidget.h"
31 #include "ui_opmap_widget.h"
33 #include <QtWidgets/QApplication>
34 #include <QHBoxLayout>
35 #include <QVBoxLayout>
36 #include <QInputDialog>
37 #include <QClipboard>
38 #include <QMenu>
39 #include <QStringList>
40 #include <QDir>
41 #include <QFile>
42 #include <QDateTime>
44 #include <math.h>
46 #include "utils/stylehelper.h"
47 #include "utils/homelocationutil.h"
48 #include "utils/worldmagmodel.h"
50 #include "uavtalk/telemetrymanager.h"
51 #include "uavobject.h"
53 #include "positionstate.h"
54 #include "pathdesired.h"
55 #include "homelocation.h"
56 #include "gpspositionsensor.h"
57 #include "gyrostate.h"
58 #include "attitudestate.h"
59 #include "positionstate.h"
60 #include "velocitystate.h"
61 #include "airspeedstate.h"
63 #define allow_manual_home_location_move
65 // *************************************************************************************
67 #define deg_to_rad ((double)M_PI / 180.0)
68 #define rad_to_deg (180.0 / (double)M_PI)
70 #define earth_mean_radius 6371 // kilometers
72 #define max_digital_zoom 3 // maximum allowed digital zoom level
74 const int safe_area_radius_list[] = { 5, 10, 20, 50, 100, 200, 500, 1000, 2000, 5000 }; // meters
76 const int uav_trail_time_list[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; // seconds
78 const int uav_trail_distance_list[] = { 1, 2, 5, 10, 20, 50, 100, 200, 500 }; // meters
80 const int max_update_rate_list[] = { 100, 200, 500, 1000, 2000, 5000 }; // milliseconds
82 // *************************************************************************************
85 // *************************************************************************************
86 // NOTE: go back to SVN REV 2137 and earlier to get back to experimental waypoint support.
87 // *************************************************************************************
90 // constructor
91 OPMapGadgetWidget::OPMapGadgetWidget(QWidget *parent) : QWidget(parent)
93 // **************
95 m_widget = NULL;
96 m_map = NULL;
97 findPlaceCompleter = NULL;
99 m_mouse_waypoint = NULL;
101 pm = NULL;
102 obm = NULL;
103 obum = NULL;
105 m_prev_tile_number = 0;
107 m_min_zoom = m_max_zoom = 0;
109 m_map_mode = Normal_MapMode;
111 m_maxUpdateRate = max_update_rate_list[4]; // 2 seconds //SHOULDN'T THIS BE LOADED FROM THE USER PREFERENCES?
113 m_telemetry_connected = false;
115 m_context_menu_lat_lon = m_mouse_lat_lon = internals::PointLatLng(0, 0);
117 setMouseTracking(true);
119 pm = ExtensionSystem::PluginManager::instance();
120 if (pm) {
121 obm = pm->getObject<UAVObjectManager>();
122 obum = pm->getObject<UAVObjectUtilManager>();
125 // **************
126 // get current location
128 double latitude = 0;
129 double longitude = 0;
130 double altitude = 0;
132 // current position
133 getUAVPosition(latitude, longitude, altitude);
135 internals::PointLatLng pos_lat_lon = internals::PointLatLng(latitude, longitude);
137 // **************
138 // default home position
140 m_home_position.coord = pos_lat_lon;
141 m_home_position.altitude = altitude;
142 m_home_position.locked = false;
144 // **************
145 // create the widget that holds the user controls and the map
147 m_widget = new Ui::OPMap_Widget();
148 m_widget->setupUi(this);
150 // **************
151 // create the central map widget
153 m_map = new mapcontrol::OPMapWidget(); // create the map object
155 m_map->setFrameStyle(QFrame::NoFrame); // no border frame
156 m_map->setBackgroundBrush(QBrush(Utils::StyleHelper::baseColor())); // tile background
158 m_map->configuration->DragButton = Qt::LeftButton; // use the left mouse button for map dragging
160 m_widget->horizontalSliderZoom->setMinimum(m_map->MinZoom()); //
161 m_widget->horizontalSliderZoom->setMaximum(m_map->MaxZoom() + max_digital_zoom); //
163 m_min_zoom = m_widget->horizontalSliderZoom->minimum(); // minimum zoom we can accept
164 m_max_zoom = m_widget->horizontalSliderZoom->maximum(); // maximum zoom we can accept
166 m_map->SetMouseWheelZoomType(internals::MouseWheelZoomType::MousePositionWithoutCenter); // set how the mouse wheel zoom functions
167 m_map->SetFollowMouse(true); // we want a contiuous mouse position reading
169 m_map->SetShowHome(true); // display the HOME position on the map
170 m_map->SetShowUAV(true); // display the UAV position on the map
171 m_map->SetShowNav(false); // initially don't display the NAV position on the map
173 m_map->Home->SetSafeArea(safe_area_radius_list[0]); // set radius (meters) //SHOULDN'T THE DEFAULT BE USER DEFINED?
174 m_map->Home->SetShowSafeArea(true); // show the safe area //SHOULDN'T THE DEFAULT BE USER DEFINED?
175 m_map->Home->SetToggleRefresh(true);
177 if (m_map->Home) {
178 connect(m_map->Home, SIGNAL(homedoubleclick(HomeItem *)), this, SLOT(onHomeDoubleClick(HomeItem *)));
180 m_map->UAV->SetTrailTime(uav_trail_time_list[0]); // seconds
181 m_map->UAV->SetTrailDistance(uav_trail_distance_list[1]); // meters
183 m_map->UAV->SetTrailType(UAVTrailType::ByTimeElapsed);
184 if (m_map->GPS) {
185 m_map->GPS->SetTrailTime(uav_trail_time_list[0]); // seconds
186 m_map->GPS->SetTrailDistance(uav_trail_distance_list[1]); // meters
188 m_map->GPS->SetTrailType(UAVTrailType::ByTimeElapsed);
190 // **************
192 setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
194 QVBoxLayout *layout = new QVBoxLayout;
195 layout->setSpacing(0);
196 layout->setContentsMargins(0, 0, 0, 0);
197 layout->addWidget(m_map);
198 m_widget->mapWidget->setLayout(layout);
200 m_widget->toolButtonMagicWaypointMapMode->setChecked(false);
201 m_widget->toolButtonNormalMapMode->setChecked(true);
202 hideMagicWaypointControls();
204 m_widget->labelUAVPos->setText("---");
205 m_widget->labelMapPos->setText("---");
206 m_widget->labelMousePos->setText("---");
207 m_widget->labelMapZoom->setText("---");
209 m_widget->progressBarMap->setMaximum(1);
211 connect(m_map, SIGNAL(zoomChanged(double, double, double)), this, SLOT(zoomChanged(double, double, double))); // map zoom change signals
212 connect(m_map, SIGNAL(OnCurrentPositionChanged(internals::PointLatLng)), this, SLOT(OnCurrentPositionChanged(internals::PointLatLng))); // map position change signals
213 connect(m_map, SIGNAL(OnTileLoadComplete()), this, SLOT(OnTileLoadComplete())); // tile loading stop signals
214 connect(m_map, SIGNAL(OnTileLoadStart()), this, SLOT(OnTileLoadStart())); // tile loading start signals
215 connect(m_map, SIGNAL(OnTilesStillToLoad(int)), this, SLOT(OnTilesStillToLoad(int))); // tile loading signals
216 connect(m_map, SIGNAL(OnWayPointDoubleClicked(WayPointItem *)), this, SLOT(wpDoubleClickEvent(WayPointItem *)));
217 m_map->SetCurrentPosition(m_home_position.coord); // set the map position
218 m_map->Home->SetCoord(m_home_position.coord); // set the HOME position
219 m_map->Nav->SetCoord(m_home_position.coord); // set the NAV position
220 m_map->UAV->SetUAVPos(m_home_position.coord, 0.0); // set the UAV position
221 m_map->UAV->update();
222 if (m_map->GPS) {
223 m_map->GPS->SetUAVPos(m_home_position.coord, 0.0); // set the GPS position
225 #ifdef USE_PATHPLANNER
226 model = new flightDataModel(this);
227 model->setDefaultWaypointAltitude(m_defaultWaypointAltitude);
228 model->setDefaultWaypointVelocity(m_defaultWaypointVelocity);
229 table = new pathPlanner();
230 selectionModel = new QItemSelectionModel(model);
231 mapProxy = new modelMapProxy(this, m_map, model, selectionModel);
232 table->setModel(model, selectionModel);
233 waypoint_edit_dialog = new opmap_edit_waypoint_dialog(this, model, selectionModel);
234 UAVProxy = new ModelUavoProxy(this, model);
235 // sending and receiving is asynchronous
236 // TODO : buttons should be disabled while a send or receive is in progress
237 connect(table, SIGNAL(sendPathPlanToUAV()), UAVProxy, SLOT(sendPathPlan()));
238 connect(table, SIGNAL(receivePathPlanFromUAV()), UAVProxy, SLOT(receivePathPlan()));
239 #endif
240 magicWayPoint = m_map->magicWPCreate();
241 magicWayPoint->setVisible(false);
243 m_map->setOverlayOpacity(0.5);
245 // **************
246 // create various context menu (mouse right click menu) actions
248 createActions();
250 // **************
251 // connect to the UAVObject updates we require to become a bit aware of our environment:
253 if (pm) {
254 // Register for Home Location state changes
255 if (obm) {
256 UAVDataObject *obj = dynamic_cast<UAVDataObject *>(obm->getObject(QString("HomeLocation")));
257 if (obj) {
258 connect(obj, SIGNAL(objectUpdated(UAVObject *)), this, SLOT(homePositionUpdated(UAVObject *)));
262 // Listen to telemetry connection events
263 TelemetryManager *telMngr = pm->getObject<TelemetryManager>();
264 if (telMngr) {
265 connect(telMngr, SIGNAL(connected()), this, SLOT(onTelemetryConnect()));
266 connect(telMngr, SIGNAL(disconnected()), this, SLOT(onTelemetryDisconnect()));
270 // **************
271 // create the desired timers
273 m_updateTimer = new QTimer();
274 m_updateTimer->setInterval(m_maxUpdateRate);
275 connect(m_updateTimer, SIGNAL(timeout()), this, SLOT(updatePosition()));
276 m_updateTimer->start();
278 m_statusUpdateTimer = new QTimer();
279 m_statusUpdateTimer->setInterval(200);
280 connect(m_statusUpdateTimer, SIGNAL(timeout()), this, SLOT(updateMousePos()));
281 m_statusUpdateTimer->start();
282 // **************
284 m_map->setFocus();
287 // destructor
288 OPMapGadgetWidget::~OPMapGadgetWidget()
290 if (m_map) {
291 disconnect(m_map, 0, 0, 0);
292 m_map->SetShowHome(false); // doing this appears to stop the map lib crashing on exit
293 m_map->SetShowUAV(false); // " "
294 m_map->SetShowNav(false); // " "
297 if (m_map) {
298 delete m_map;
299 m_map = NULL;
301 if (!model.isNull()) {
302 delete model;
304 if (!table.isNull()) {
305 delete table;
307 if (!selectionModel.isNull()) {
308 delete selectionModel;
310 if (!mapProxy.isNull()) {
311 delete mapProxy;
313 if (!waypoint_edit_dialog.isNull()) {
314 delete waypoint_edit_dialog;
316 if (!UAVProxy.isNull()) {
317 delete UAVProxy;
321 // *************************************************************************************
322 // widget signals .. the mouseMoveEvent does not get called - don't yet know why
324 void OPMapGadgetWidget::resizeEvent(QResizeEvent *event)
326 QWidget::resizeEvent(event);
329 void OPMapGadgetWidget::mouseMoveEvent(QMouseEvent *event)
331 if (m_widget && m_map) {}
333 if (event->buttons() & Qt::LeftButton) {}
334 QWidget::mouseMoveEvent(event);
336 void OPMapGadgetWidget::wpDoubleClickEvent(WayPointItem *wp)
338 m_mouse_waypoint = wp;
339 onEditWayPointAct_triggered();
342 void OPMapGadgetWidget::contextMenuEvent(QContextMenuEvent *event)
344 // the user has right clicked on the map - create the pop-up context menu and display it
346 if (!m_widget || !m_map) {
347 return;
350 if (event->reason() != QContextMenuEvent::Mouse) {
351 // not a mouse click event
352 return;
355 // current mouse position
356 QPoint p = m_map->mapFromGlobal(event->globalPos());
357 m_context_menu_lat_lon = m_map->GetFromLocalToLatLng(p);
359 if (!m_map->contentsRect().contains(p)) {
360 // the mouse click was not on the map
361 return;
364 // show the mouse position
365 QString mousePosString = QString::number(m_context_menu_lat_lon.Lat(), 'f', 7) + " " + QString::number(m_context_menu_lat_lon.Lng(), 'f', 7);
366 m_widget->labelMousePos->setText(mousePosString);
368 // find out if we have a waypoint under the mouse cursor
369 QGraphicsItem *item = m_map->itemAt(p);
370 m_mouse_waypoint = qgraphicsitem_cast<mapcontrol::WayPointItem *>(item);
372 // find out if the waypoint is locked (or not)
373 bool waypoint_locked = false;
374 if (m_mouse_waypoint) {
375 waypoint_locked = (m_mouse_waypoint->flags() & QGraphicsItem::ItemIsMovable) == 0;
378 // Dynamically create the popup menu
379 QMenu contextMenu;
381 contextMenu.addAction(reloadAct);
382 contextMenu.addSeparator();
383 contextMenu.addAction(ripAct);
384 contextMenu.addSeparator();
386 QMenu maxUpdateRateSubMenu(tr("&Max Update Rate ") + "(" + QString::number(m_maxUpdateRate) + " ms)", this);
387 for (int i = 0; i < maxUpdateRateAct.count(); i++) {
388 maxUpdateRateSubMenu.addAction(maxUpdateRateAct.at(i));
390 contextMenu.addMenu(&maxUpdateRateSubMenu);
392 contextMenu.addSeparator();
394 QString mapMode;
395 switch (m_map_mode) {
396 case Normal_MapMode:
397 mapMode = tr(" (Normal)");
398 break;
399 case MagicWaypoint_MapMode:
400 mapMode = tr(" (Magic Waypoint)");
401 break;
402 default:
403 mapMode = tr(" (Unknown)");
404 break;
406 for (int i = 0; i < mapModeAct.count(); i++) {
407 // set the menu to checked (or not)
408 QAction *act = mapModeAct.at(i);
409 if (!act) {
410 continue;
412 if (act->data().toInt() == (int)m_map_mode) {
413 act->setChecked(true);
416 QMenu mapModeSubMenu(tr("Map mode") + mapMode, this);
417 for (int i = 0; i < mapModeAct.count(); i++) {
418 mapModeSubMenu.addAction(mapModeAct.at(i));
420 contextMenu.addMenu(&mapModeSubMenu);
422 contextMenu.addSeparator();
424 QMenu copySubMenu(tr("Copy"), this);
425 copySubMenu.addAction(copyMouseLatLonToClipAct);
426 copySubMenu.addAction(copyMouseLatToClipAct);
427 copySubMenu.addAction(copyMouseLonToClipAct);
428 contextMenu.addMenu(&copySubMenu);
430 contextMenu.addSeparator();
431 contextMenu.addAction(changeDefaultLocalAndZoom);
432 contextMenu.addSeparator();
434 QMenu safeArea(tr("Safety Area definitions"));
435 // menu.addAction(showSafeAreaAct);
436 QMenu safeAreaSubMenu(tr("Safe Area Radius") + " (" + QString::number(m_map->Home->SafeArea()) + "m)", this);
437 for (int i = 0; i < safeAreaAct.count(); i++) {
438 safeAreaSubMenu.addAction(safeAreaAct.at(i));
440 safeArea.addMenu(&safeAreaSubMenu);
441 safeArea.addAction(showSafeAreaAct);
442 contextMenu.addMenu(&safeArea);
444 contextMenu.addSeparator();
446 contextMenu.addAction(showCompassAct);
448 contextMenu.addAction(showDiagnostics);
450 contextMenu.addAction(showNav);
452 contextMenu.addAction(showUAVInfo);
454 // Zoom section
455 contextMenu.addSection(tr("Zoom"));
457 contextMenu.addAction(zoomInAct);
458 contextMenu.addAction(zoomOutAct);
460 QMenu zoomSubMenu(tr("&Zoom ") + "(" + QString::number(m_map->ZoomTotal()) + ")", this);
461 for (int i = 0; i < zoomAct.count(); i++) {
462 zoomSubMenu.addAction(zoomAct.at(i));
464 contextMenu.addMenu(&zoomSubMenu);
466 contextMenu.addSeparator();
468 contextMenu.addAction(goMouseClickAct);
470 // Home section
471 contextMenu.addSection(tr("Home"));
473 contextMenu.addAction(setHomeAct);
474 contextMenu.addAction(showHomeAct);
475 contextMenu.addAction(goHomeAct);
477 // uav trails
478 QMenu uav_menu(tr("UAV"));
479 uav_menu.addSection(tr("UAV Trail"));
480 contextMenu.addMenu(&uav_menu);
481 QMenu uavTrailTypeSubMenu(tr("UAV trail type") + " (" + mapcontrol::Helper::StrFromUAVTrailType(m_map->UAV->GetTrailType()) + ")", this);
482 for (int i = 0; i < uavTrailTypeAct.count(); i++) {
483 uavTrailTypeSubMenu.addAction(uavTrailTypeAct.at(i));
485 uav_menu.addMenu(&uavTrailTypeSubMenu);
487 QMenu uavTrailTimeSubMenu(tr("UAV trail time") + " (" + QString::number(m_map->UAV->TrailTime()) + " sec)", this);
488 for (int i = 0; i < uavTrailTimeAct.count(); i++) {
489 uavTrailTimeSubMenu.addAction(uavTrailTimeAct.at(i));
491 uav_menu.addMenu(&uavTrailTimeSubMenu);
493 QMenu uavTrailDistanceSubMenu(tr("UAV trail distance") + " (" + QString::number(m_map->UAV->TrailDistance()) + " meters)", this);
494 for (int i = 0; i < uavTrailDistanceAct.count(); i++) {
495 uavTrailDistanceSubMenu.addAction(uavTrailDistanceAct.at(i));
497 uav_menu.addMenu(&uavTrailDistanceSubMenu);
499 uav_menu.addAction(showTrailAct);
501 uav_menu.addAction(showTrailLineAct);
503 uav_menu.addAction(clearUAVtrailAct);
505 // UAV section
506 uav_menu.addSection(tr("UAV"));
508 uav_menu.addAction(showUAVAct);
509 uav_menu.addAction(followUAVpositionAct);
510 uav_menu.addAction(followUAVheadingAct);
511 uav_menu.addAction(goUAVAct);
513 // waypoint section
514 #ifdef USE_PATHPLANNER
515 switch (m_map_mode) {
516 case Normal_MapMode:
517 // only show the waypoint stuff if not in 'magic waypoint' mode
519 contextMenu.addSection(tr("Waypoints"));
521 contextMenu.addAction(wayPointEditorAct);
522 contextMenu.addAction(addWayPointActFromContextMenu);
524 if (m_mouse_waypoint) {
525 // we have a waypoint under the mouse
526 contextMenu.addAction(editWayPointAct);
528 lockWayPointAct->setChecked(waypoint_locked);
529 contextMenu.addAction(lockWayPointAct);
531 if (!waypoint_locked) {
532 contextMenu.addAction(deleteWayPointAct);
536 if (m_map->WPPresent()) {
537 // we have waypoints
538 contextMenu.addAction(clearWayPointsAct);
540 break;
542 case MagicWaypoint_MapMode:
543 contextMenu.addSection(tr("Waypoints"));
544 contextMenu.addAction(homeMagicWaypointAct);
545 break;
547 #endif // ifdef USE_PATHPLANNER
549 QMenu overlaySubMenu(tr("&Overlay Opacity "), this);
550 for (int i = 0; i < overlayOpacityAct.count(); i++) {
551 overlaySubMenu.addAction(overlayOpacityAct.at(i));
553 contextMenu.addMenu(&overlaySubMenu);
555 // accept the event
556 event->accept();
558 // popup the menu
559 contextMenu.exec(event->globalPos());
562 void OPMapGadgetWidget::closeEvent(QCloseEvent *event)
564 table->close();
565 QWidget::closeEvent(event);
568 // *************************************************************************************
569 // timer signals
572 Updates the UAV position on the map. It is called at a user-defined frequency,
573 as set inside the map widget.
575 void OPMapGadgetWidget::updatePosition()
577 double uav_latitude, uav_longitude, uav_altitude, uav_yaw;
578 double gps_latitude, gps_longitude, gps_altitude, gps_heading;
580 internals::PointLatLng uav_pos;
581 internals::PointLatLng gps_pos;
583 if (!m_widget || !m_map) {
584 return;
587 QMutexLocker locker(&m_map_mutex);
589 // *************
590 // get the current UAV details
592 // get current UAV position
593 if (!getUAVPosition(uav_latitude, uav_longitude, uav_altitude)) {
594 return;
597 // get current UAV heading
598 uav_yaw = getUAV_Yaw();
600 uav_pos = internals::PointLatLng(uav_latitude, uav_longitude);
602 // *************
603 // get the current GPS position and heading
604 GPSPositionSensor *gpsPositionObj = GPSPositionSensor::GetInstance(obm);
605 Q_ASSERT(gpsPositionObj);
607 GPSPositionSensor::DataFields gpsPositionData = gpsPositionObj->getData();
609 gps_heading = gpsPositionData.Heading;
610 gps_latitude = gpsPositionData.Latitude;
611 gps_longitude = gpsPositionData.Longitude;
612 gps_altitude = gpsPositionData.Altitude;
614 gps_pos = internals::PointLatLng(gps_latitude * 1e-7, gps_longitude * 1e-7);
616 // **********************
617 // get the current position and heading estimates
618 AttitudeState *attitudeStateObj = AttitudeState::GetInstance(obm);
619 PositionState *positionStateObj = PositionState::GetInstance(obm);
620 VelocityState *velocityStateObj = VelocityState::GetInstance(obm);
621 AirspeedState *airspeedStateObj = AirspeedState::GetInstance(obm);
623 GyroState *gyroStateObj = GyroState::GetInstance(obm);
625 Q_ASSERT(attitudeStateObj);
626 Q_ASSERT(positionStateObj);
627 Q_ASSERT(velocityStateObj);
628 Q_ASSERT(airspeedStateObj);
629 Q_ASSERT(gyroStateObj);
631 AttitudeState::DataFields attitudeStateData = attitudeStateObj->getData();
632 PositionState::DataFields positionStateData = positionStateObj->getData();
633 VelocityState::DataFields velocityStateData = velocityStateObj->getData();
634 AirspeedState::DataFields airspeedStateData = airspeedStateObj->getData();
636 GyroState::DataFields gyroStateData = gyroStateObj->getData();
638 double NED[3] = { positionStateData.North, positionStateData.East, positionStateData.Down };
639 double vNED[3] = { velocityStateData.North, velocityStateData.East, velocityStateData.Down };
641 // Set the position and heading estimates in the painter module
642 m_map->UAV->SetNED(NED);
643 m_map->UAV->SetCAS(airspeedStateData.CalibratedAirspeed);
644 m_map->UAV->SetGroundspeed(vNED, m_maxUpdateRate);
646 // Convert angular velocities into a rotationg rate around the world-frame yaw axis. This is found by simply taking the dot product of the angular Euler-rate matrix with the angular rates.
647 float psiRate_dps = 0 * gyroStateData.z + sin(attitudeStateData.Roll * deg_to_rad) / cos(attitudeStateData.Pitch * deg_to_rad) * gyroStateData.y + cos(attitudeStateData.Roll * deg_to_rad) / cos(attitudeStateData.Pitch * deg_to_rad) * gyroStateData.z;
649 // Set the angular rate in the painter module
650 m_map->UAV->SetYawRate(psiRate_dps); // Not correct, but I'm being lazy right now.
652 // *************
653 // display the UAV position
655 QString str =
656 "lat: " + QString::number(uav_pos.Lat(), 'f', 7) +
657 " lon: " + QString::number(uav_pos.Lng(), 'f', 7) +
658 " " + QString::number(uav_yaw, 'f', 1) + "deg" +
659 " " + QString::number(uav_altitude, 'f', 1) + "m";
660 // " " + QString::number(uav_ground_speed_meters_per_second, 'f', 1) + "m/s";
661 m_widget->labelUAVPos->setText(str);
663 // *************
664 // set the UAV icon position on the map
666 m_map->UAV->SetUAVPos(uav_pos, uav_altitude); // set the maps UAV position
667 // qDebug()<<"UAVPOSITION"<<uav_pos.ToString();
668 m_map->UAV->SetUAVHeading(uav_yaw); // set the maps UAV heading
670 // *************
671 // set the GPS icon position on the map
672 if (m_map->GPS) {
673 m_map->GPS->SetUAVPos(gps_pos, gps_altitude); // set the maps GPS position
674 m_map->GPS->SetUAVHeading(gps_heading); // set the maps GPS heading
675 m_map->GPS->update();
677 m_map->UAV->updateTextOverlay();
678 m_map->UAV->update();
679 // *************
681 // *************
682 // update active waypoint position at same update rate
683 if (m_map->Nav) {
684 double latitude, longitude, altitude;
685 getNavPosition(latitude, longitude, altitude);
686 m_map->Nav->SetCoord(internals::PointLatLng(latitude, longitude)); // set the maps Nav position
687 m_map->Nav->SetAltitude(altitude);
688 m_map->Nav->RefreshPos();
689 m_map->Nav->update();
691 m_map->UAV->updateTextOverlay();
692 m_map->UAV->update();
696 Update plugin behaviour based on mouse position; Called every few ms by a
697 timer.
699 void OPMapGadgetWidget::updateMousePos()
701 if (!m_widget || !m_map) {
702 return;
705 QMutexLocker locker(&m_map_mutex);
707 QPoint p = m_map->mapFromGlobal(QCursor::pos());
708 internals::PointLatLng lat_lon = m_map->GetFromLocalToLatLng(p); // fetch the current lat/lon mouse position
709 lastLatLngMouse = lat_lon;
710 if (!m_map->contentsRect().contains(p)) {
711 return; // the mouse is not on the map
713 // internals::PointLatLng lat_lon = m_map->currentMousePosition(); // fetch the current lat/lon mouse position
715 QGraphicsItem *item = m_map->itemAt(p);
717 // find out if we are over the home position
718 mapcontrol::HomeItem *home = qgraphicsitem_cast<mapcontrol::HomeItem *>(item);
720 // find out if we have a waypoint under the mouse cursor
721 mapcontrol::WayPointItem *wp = qgraphicsitem_cast<mapcontrol::WayPointItem *>(item);
723 if (m_mouse_lat_lon == lat_lon) {
724 return; // the mouse has not moved
726 m_mouse_lat_lon = lat_lon; // yes it has!
728 internals::PointLatLng home_lat_lon = m_map->Home->Coord();
730 QString s = QString::number(m_mouse_lat_lon.Lat(), 'f', 7) + " " + QString::number(m_mouse_lat_lon.Lng(), 'f', 7);
731 if (wp) {
732 s += " wp[" + QString::number(wp->numberAdjusted()) + "]";
734 double dist = distance(home_lat_lon, wp->Coord());
735 double bear = bearing(home_lat_lon, wp->Coord());
736 s += " " + QString::number(dist * 1000, 'f', 1) + "m";
737 s += " " + QString::number(bear, 'f', 1) + "deg";
738 } else if (home) {
739 s += " home";
741 double dist = distance(home_lat_lon, m_mouse_lat_lon);
742 double bear = bearing(home_lat_lon, m_mouse_lat_lon);
743 s += " " + QString::number(dist * 1000, 'f', 1) + "m";
744 s += " " + QString::number(bear, 'f', 1) + "deg";
746 m_widget->labelMousePos->setText(s);
749 // *************************************************************************************
750 // map signals
754 Update the Plugin UI to reflect a change in zoom level
756 void OPMapGadgetWidget::zoomChanged(double zoomt, double zoom, double zoomd)
758 if (!m_widget || !m_map) {
759 return;
762 QString s = "tot:" + QString::number(zoomt, 'f', 1) + " rea:" + QString::number(zoom, 'f', 1) + " dig:" + QString::number(zoomd, 'f', 1);
763 m_widget->labelMapZoom->setText(s);
765 int i_zoom = (int)(zoomt + 0.5);
767 if (i_zoom < m_min_zoom) {
768 i_zoom = m_min_zoom;
769 } else if (i_zoom > m_max_zoom) {
770 i_zoom = m_max_zoom;
773 if (m_widget->horizontalSliderZoom->value() != i_zoom) {
774 m_widget->horizontalSliderZoom->setValue(i_zoom); // set the GUI zoom slider position
776 int index0_zoom = i_zoom - m_min_zoom; // zoom level starting at index level '0'
777 if (index0_zoom < zoomAct.count()) {
778 zoomAct.at(index0_zoom)->setChecked(true); // set the right-click context menu zoom level
782 void OPMapGadgetWidget::OnCurrentPositionChanged(internals::PointLatLng point)
784 if (!m_widget || !m_map) {
785 return;
788 QString coord_str = QString::number(point.Lat(), 'f', 7) + " " + QString::number(point.Lng(), 'f', 7) + " ";
789 m_widget->labelMapPos->setText(coord_str);
793 Update the progress bar while there are still tiles to load
795 void OPMapGadgetWidget::OnTilesStillToLoad(int number)
797 if (!m_widget || !m_map) {
798 return;
801 if (m_widget->progressBarMap->maximum() < number) {
802 m_widget->progressBarMap->setMaximum(number);
805 m_widget->progressBarMap->setValue(m_widget->progressBarMap->maximum() - number); // update the progress bar
807 m_prev_tile_number = number;
811 Show the progress bar as soon as the map lib starts downloading
813 void OPMapGadgetWidget::OnTileLoadStart()
815 if (!m_widget || !m_map) {
816 return;
818 m_widget->progressBarMap->setVisible(true);
822 Hide the progress bar once the map lib has finished downloading
824 TODO: somehow this gets called before tile load is actually complete?
827 void OPMapGadgetWidget::OnTileLoadComplete()
829 if (!m_widget || !m_map) {
830 return;
833 m_widget->progressBarMap->setVisible(false);
836 void OPMapGadgetWidget::on_toolButtonZoomP_clicked()
838 QMutexLocker locker(&m_map_mutex);
840 zoomIn();
843 void OPMapGadgetWidget::on_toolButtonZoomM_clicked()
845 QMutexLocker locker(&m_map_mutex);
847 zoomOut();
850 void OPMapGadgetWidget::on_toolButtonMapHome_clicked()
852 QMutexLocker locker(&m_map_mutex);
854 goHome();
857 void OPMapGadgetWidget::on_toolButtonMapUAV_clicked()
859 if (!m_widget || !m_map) {
860 return;
863 QMutexLocker locker(&m_map_mutex);
865 followUAVpositionAct->toggle();
868 void OPMapGadgetWidget::on_toolButtonMapUAVheading_clicked()
870 if (!m_widget || !m_map) {
871 return;
874 followUAVheadingAct->toggle();
877 void OPMapGadgetWidget::on_horizontalSliderZoom_sliderMoved(int position)
879 if (!m_widget || !m_map) {
880 return;
883 QMutexLocker locker(&m_map_mutex);
885 setZoom(position);
889 void OPMapGadgetWidget::on_toolButtonNormalMapMode_clicked()
891 setMapMode(Normal_MapMode);
894 void OPMapGadgetWidget::on_toolButtonMagicWaypointMapMode_clicked()
896 setMapMode(MagicWaypoint_MapMode);
899 void OPMapGadgetWidget::on_toolButtonHomeWaypoint_clicked()
901 homeMagicWaypoint();
904 void OPMapGadgetWidget::on_toolButtonMoveToWP_clicked()
906 moveToMagicWaypointPosition();
909 // *************************************************************************************
910 // public slots
912 void OPMapGadgetWidget::onTelemetryConnect()
914 m_telemetry_connected = true;
916 if (!obum) {
917 return;
919 applyHomeLocationOnMap();
922 void OPMapGadgetWidget::onTelemetryDisconnect()
924 m_telemetry_connected = false;
927 // Updates the Home position icon whenever the HomePosition object is updated
928 void OPMapGadgetWidget::homePositionUpdated(UAVObject *hp)
930 Q_UNUSED(hp);
931 if (!obum) {
932 return;
934 bool set;
935 double LLA[3];
936 if (obum->getHomeLocation(set, LLA) < 0) {
937 return; // error
939 setHome(internals::PointLatLng(LLA[0], LLA[1]), LLA[2]);
942 // *************************************************************************************
943 // public functions
946 Sets the home position on the map widget
948 void OPMapGadgetWidget::setHome(QPointF pos)
950 if (!m_widget || !m_map) {
951 return;
954 double latitude = pos.x();
955 double longitude = pos.y();
957 if (latitude > 90) {
958 latitude = 90;
959 } else if (latitude < -90) {
960 latitude = -90;
963 if (longitude != longitude) {
964 longitude = 0; // nan detection
965 } else if (longitude > 180) {
966 longitude = 180;
967 } else if (longitude < -180) {
968 longitude = -180;
971 setHome(internals::PointLatLng(latitude, longitude), 0);
975 Sets the home position on the map widget
977 void OPMapGadgetWidget::setHome(internals::PointLatLng pos_lat_lon, double altitude)
979 if (!m_widget || !m_map) {
980 return;
983 if (pos_lat_lon.Lat() != pos_lat_lon.Lat() || pos_lat_lon.Lng() != pos_lat_lon.Lng()) {
984 return;
986 ; // nan prevention
988 double latitude = pos_lat_lon.Lat();
989 double longitude = pos_lat_lon.Lng();
991 if (latitude != latitude) {
992 latitude = 0; // nan detection
993 } else if (latitude > 90) {
994 latitude = 90;
995 } else if (latitude < -90) {
996 latitude = -90;
999 if (longitude != longitude) {
1000 longitude = 0; // nan detection
1001 } else if (longitude > 180) {
1002 longitude = 180;
1003 } else if (longitude < -180) {
1004 longitude = -180;
1007 // *********
1009 m_home_position.coord = internals::PointLatLng(latitude, longitude);
1010 m_home_position.altitude = altitude;
1012 m_map->Home->SetCoord(m_home_position.coord);
1013 m_map->Home->SetAltitude(altitude);
1014 m_map->Home->RefreshPos();
1016 // move the magic waypoint to keep it within the safe area boundry
1017 keepMagicWaypointWithinSafeArea();
1022 Centers the map over the home position
1024 void OPMapGadgetWidget::goHome()
1026 if (!m_widget || !m_map) {
1027 return;
1030 followUAVpositionAct->setChecked(false);
1032 internals::PointLatLng home_pos = m_home_position.coord; // get the home location
1033 m_map->SetCurrentPosition(home_pos); // center the map onto the home location
1037 void OPMapGadgetWidget::zoomIn()
1039 if (!m_widget || !m_map) {
1040 return;
1043 int zoom = m_map->ZoomTotal() + 1;
1045 if (zoom < m_min_zoom) {
1046 zoom = m_min_zoom;
1047 } else if (zoom > m_max_zoom) {
1048 zoom = m_max_zoom;
1051 m_map->SetZoom(zoom);
1054 void OPMapGadgetWidget::zoomOut()
1056 if (!m_widget || !m_map) {
1057 return;
1060 int zoom = m_map->ZoomTotal() - 1;
1062 if (zoom < m_min_zoom) {
1063 zoom = m_min_zoom;
1064 } else if (zoom > m_max_zoom) {
1065 zoom = m_max_zoom;
1068 m_map->SetZoom(zoom);
1071 void OPMapGadgetWidget::setMaxUpdateRate(int update_rate)
1073 if (!m_widget || !m_map) {
1074 return;
1077 int list_size = sizeof(max_update_rate_list) / sizeof(max_update_rate_list[0]);
1078 int min_rate = max_update_rate_list[0];
1079 int max_rate = max_update_rate_list[list_size - 1];
1081 if (update_rate < min_rate) {
1082 update_rate = min_rate;
1083 } else if (update_rate > max_rate) {
1084 update_rate = max_rate;
1087 m_maxUpdateRate = update_rate;
1089 if (m_updateTimer) {
1090 m_updateTimer->setInterval(m_maxUpdateRate);
1093 // if (m_statusUpdateTimer)
1094 // m_statusUpdateTimer->setInterval(m_maxUpdateRate);
1097 void OPMapGadgetWidget::setZoom(int zoom)
1099 if (!m_widget || !m_map) {
1100 return;
1103 if (zoom < m_min_zoom) {
1104 zoom = m_min_zoom;
1105 } else if (zoom > m_max_zoom) {
1106 zoom = m_max_zoom;
1109 internals::MouseWheelZoomType::Types zoom_type = m_map->GetMouseWheelZoomType();
1110 m_map->SetMouseWheelZoomType(internals::MouseWheelZoomType::ViewCenter);
1112 m_map->SetZoom(zoom);
1114 m_map->SetMouseWheelZoomType(zoom_type);
1116 void OPMapGadgetWidget::setOverlayOpacity(qreal value)
1118 if (!m_widget || !m_map) {
1119 return;
1121 m_map->setOverlayOpacity(value);
1122 overlayOpacityAct.at(value * 10)->setChecked(true);
1125 void OPMapGadgetWidget::setHomePosition(QPointF pos)
1127 if (!m_widget || !m_map) {
1128 return;
1131 double latitude = pos.y();
1132 double longitude = pos.x();
1134 if (latitude != latitude || longitude != longitude) {
1135 return; // nan prevention
1137 if (latitude > 90) {
1138 latitude = 90;
1139 } else if (latitude < -90) {
1140 latitude = -90;
1143 if (longitude > 180) {
1144 longitude = 180;
1145 } else if (longitude < -180) {
1146 longitude = -180;
1149 m_map->Home->SetCoord(internals::PointLatLng(latitude, longitude));
1151 if (!m_telemetry_connected) {
1152 m_home_position.coord = internals::PointLatLng(latitude, longitude);
1156 void OPMapGadgetWidget::setPosition(QPointF pos)
1158 if (!m_widget || !m_map) {
1159 return;
1162 double latitude = pos.y();
1163 double longitude = pos.x();
1165 if (latitude != latitude || longitude != longitude) {
1166 return; // nan prevention
1168 if (latitude > 90) {
1169 latitude = 90;
1170 } else if (latitude < -90) {
1171 latitude = -90;
1174 if (longitude > 180) {
1175 longitude = 180;
1176 } else if (longitude < -180) {
1177 longitude = -180;
1180 m_map->SetCurrentPosition(internals::PointLatLng(latitude, longitude));
1183 void OPMapGadgetWidget::setMapProvider(QString provider)
1185 if (!m_widget || !m_map) {
1186 return;
1189 m_map->SetMapType(mapcontrol::Helper::MapTypeFromString(provider));
1192 void OPMapGadgetWidget::setAccessMode(QString accessMode)
1194 if (!m_widget || !m_map) {
1195 return;
1198 m_map->configuration->SetAccessMode(mapcontrol::Helper::AccessModeFromString(accessMode));
1201 void OPMapGadgetWidget::setUseOpenGL(bool useOpenGL)
1203 if (!m_widget || !m_map) {
1204 return;
1207 m_map->SetUseOpenGL(useOpenGL);
1210 void OPMapGadgetWidget::setShowTileGridLines(bool showTileGridLines)
1212 if (!m_widget || !m_map) {
1213 return;
1216 m_map->SetShowTileGridLines(showTileGridLines);
1219 void OPMapGadgetWidget::setUseMemoryCache(bool useMemoryCache)
1221 if (!m_widget || !m_map) {
1222 return;
1225 m_map->configuration->SetUseMemoryCache(useMemoryCache);
1228 void OPMapGadgetWidget::setCacheLocation(QString cacheLocation)
1230 if (!m_widget || !m_map) {
1231 return;
1234 cacheLocation = cacheLocation.simplified(); // remove any surrounding spaces
1236 if (cacheLocation.isEmpty()) {
1237 return;
1240 if (!cacheLocation.endsWith(QDir::separator())) {
1241 cacheLocation += QDir::separator();
1244 QDir dir;
1245 if (!dir.exists(cacheLocation)) {
1246 if (!dir.mkpath(cacheLocation)) {
1247 return;
1250 m_map->configuration->SetCacheLocation(cacheLocation);
1253 void OPMapGadgetWidget::setMapMode(opMapModeType mode)
1255 if (!m_widget || !m_map) {
1256 return;
1259 if (mode != Normal_MapMode && mode != MagicWaypoint_MapMode) {
1260 mode = Normal_MapMode; // fix error
1262 if (m_map_mode == mode) { // no change in map mode
1263 switch (mode) { // make sure the UI buttons are set correctly
1264 case Normal_MapMode:
1265 m_widget->toolButtonMagicWaypointMapMode->setChecked(false);
1266 m_widget->toolButtonNormalMapMode->setChecked(true);
1267 break;
1268 case MagicWaypoint_MapMode:
1269 m_widget->toolButtonNormalMapMode->setChecked(false);
1270 m_widget->toolButtonMagicWaypointMapMode->setChecked(true);
1271 break;
1273 return;
1276 switch (mode) {
1277 case Normal_MapMode:
1278 m_map_mode = Normal_MapMode;
1280 m_widget->toolButtonMagicWaypointMapMode->setChecked(false);
1281 m_widget->toolButtonNormalMapMode->setChecked(true);
1283 hideMagicWaypointControls();
1285 magicWayPoint->setVisible(false);
1286 m_map->WPSetVisibleAll(true);
1288 break;
1290 case MagicWaypoint_MapMode:
1291 m_map_mode = MagicWaypoint_MapMode;
1293 m_widget->toolButtonNormalMapMode->setChecked(false);
1294 m_widget->toolButtonMagicWaypointMapMode->setChecked(true);
1296 showMagicWaypointControls();
1298 // delete the normal waypoints from the map
1300 m_map->WPSetVisibleAll(false);
1301 magicWayPoint->setVisible(true);
1303 break;
1307 // *************************************************************************************
1308 // Context menu stuff
1310 void OPMapGadgetWidget::createActions()
1312 int list_size;
1314 if (!m_widget || !m_map) {
1315 return;
1318 // ***********************
1319 // create menu actions
1321 reloadAct = new QAction(tr("&Reload map"), this);
1322 reloadAct->setShortcut(tr("F5"));
1323 reloadAct->setStatusTip(tr("Reload the map tiles"));
1324 connect(reloadAct, SIGNAL(triggered()), this, SLOT(onReloadAct_triggered()));
1325 this->addAction(reloadAct);
1326 ripAct = new QAction(tr("&Rip map"), this);
1327 ripAct->setStatusTip(tr("Rip the map tiles"));
1328 connect(ripAct, SIGNAL(triggered()), this, SLOT(onRipAct_triggered()));
1330 copyMouseLatLonToClipAct = new QAction(tr("Mouse latitude and longitude"), this);
1331 copyMouseLatLonToClipAct->setStatusTip(tr("Copy the mouse latitude and longitude to the clipboard"));
1332 connect(copyMouseLatLonToClipAct, SIGNAL(triggered()), this, SLOT(onCopyMouseLatLonToClipAct_triggered()));
1334 copyMouseLatToClipAct = new QAction(tr("Mouse latitude"), this);
1335 copyMouseLatToClipAct->setStatusTip(tr("Copy the mouse latitude to the clipboard"));
1336 connect(copyMouseLatToClipAct, SIGNAL(triggered()), this, SLOT(onCopyMouseLatToClipAct_triggered()));
1338 copyMouseLonToClipAct = new QAction(tr("Mouse longitude"), this);
1339 copyMouseLonToClipAct->setStatusTip(tr("Copy the mouse longitude to the clipboard"));
1340 connect(copyMouseLonToClipAct, SIGNAL(triggered()), this, SLOT(onCopyMouseLonToClipAct_triggered()));
1342 showCompassAct = new QAction(tr("Show compass"), this);
1343 showCompassAct->setStatusTip(tr("Show/Hide the compass"));
1344 showCompassAct->setCheckable(true);
1345 showCompassAct->setChecked(true);
1346 connect(showCompassAct, SIGNAL(toggled(bool)), this, SLOT(onShowCompassAct_toggled(bool)));
1348 showDiagnostics = new QAction(tr("Show Diagnostics"), this);
1349 showDiagnostics->setStatusTip(tr("Show/Hide the diagnostics"));
1350 showDiagnostics->setCheckable(true);
1351 showDiagnostics->setChecked(false);
1352 connect(showDiagnostics, SIGNAL(toggled(bool)), this, SLOT(onShowDiagnostics_toggled(bool)));
1354 showNav = new QAction(tr("Show Nav"), this);
1355 showNav->setStatusTip(tr("Show/Hide pathfollower info"));
1356 showNav->setCheckable(true);
1357 showNav->setChecked(false);
1358 connect(showNav, SIGNAL(toggled(bool)), this, SLOT(onShowNav_toggled(bool)));
1360 showUAVInfo = new QAction(tr("Show UAV Info"), this);
1361 showUAVInfo->setStatusTip(tr("Show/Hide the UAV info"));
1362 showUAVInfo->setCheckable(true);
1363 showUAVInfo->setChecked(false);
1364 connect(showUAVInfo, SIGNAL(toggled(bool)), this, SLOT(onShowUAVInfo_toggled(bool)));
1366 showHomeAct = new QAction(tr("Show Home"), this);
1367 showHomeAct->setStatusTip(tr("Show/Hide the Home location"));
1368 showHomeAct->setCheckable(true);
1369 showHomeAct->setChecked(true);
1370 connect(showHomeAct, SIGNAL(toggled(bool)), this, SLOT(onShowHomeAct_toggled(bool)));
1372 showUAVAct = new QAction(tr("Show UAV"), this);
1373 showUAVAct->setStatusTip(tr("Show/Hide the UAV"));
1374 showUAVAct->setCheckable(true);
1375 showUAVAct->setChecked(true);
1376 connect(showUAVAct, SIGNAL(toggled(bool)), this, SLOT(onShowUAVAct_toggled(bool)));
1378 changeDefaultLocalAndZoom = new QAction(tr("Set default zoom and location"), this);
1379 changeDefaultLocalAndZoom->setStatusTip(tr("Changes the map default zoom and location to the current values"));
1380 connect(changeDefaultLocalAndZoom, SIGNAL(triggered()), this, SLOT(onChangeDefaultLocalAndZoom()));
1382 zoomInAct = new QAction(tr("Zoom &In"), this);
1383 zoomInAct->setShortcut(Qt::Key_PageUp);
1384 zoomInAct->setStatusTip(tr("Zoom the map in"));
1385 connect(zoomInAct, SIGNAL(triggered()), this, SLOT(onGoZoomInAct_triggered()));
1386 this->addAction(zoomInAct);
1388 zoomOutAct = new QAction(tr("Zoom &Out"), this);
1389 zoomOutAct->setShortcut(Qt::Key_PageDown);
1390 zoomOutAct->setStatusTip(tr("Zoom the map out"));
1391 connect(zoomOutAct, SIGNAL(triggered()), this, SLOT(onGoZoomOutAct_triggered()));
1392 this->addAction(zoomOutAct);
1394 goMouseClickAct = new QAction(tr("Go to where you right clicked the mouse"), this);
1395 goMouseClickAct->setStatusTip(tr("Center the map onto where you right clicked the mouse"));
1396 connect(goMouseClickAct, SIGNAL(triggered()), this, SLOT(onGoMouseClickAct_triggered()));
1398 setHomeAct = new QAction(tr("Set the home location"), this);
1399 setHomeAct->setStatusTip(tr("Set the home location to where you clicked"));
1400 #if !defined(allow_manual_home_location_move)
1401 setHomeAct->setEnabled(false);
1402 #endif
1403 connect(setHomeAct, SIGNAL(triggered()), this, SLOT(onSetHomeAct_triggered()));
1405 goHomeAct = new QAction(tr("Go to &Home location"), this);
1406 goHomeAct->setShortcut(tr("Ctrl+H"));
1407 goHomeAct->setStatusTip(tr("Center the map onto the home location"));
1408 connect(goHomeAct, SIGNAL(triggered()), this, SLOT(onGoHomeAct_triggered()));
1410 goUAVAct = new QAction(tr("Go to &UAV location"), this);
1411 goUAVAct->setShortcut(tr("Ctrl+U"));
1412 goUAVAct->setStatusTip(tr("Center the map onto the UAV location"));
1413 connect(goUAVAct, SIGNAL(triggered()), this, SLOT(onGoUAVAct_triggered()));
1415 followUAVpositionAct = new QAction(tr("Follow UAV position"), this);
1416 followUAVpositionAct->setShortcut(tr("Ctrl+F"));
1417 followUAVpositionAct->setStatusTip(tr("Keep the map centered onto the UAV"));
1418 followUAVpositionAct->setCheckable(true);
1419 followUAVpositionAct->setChecked(false);
1420 connect(followUAVpositionAct, SIGNAL(toggled(bool)), this, SLOT(onFollowUAVpositionAct_toggled(bool)));
1422 followUAVheadingAct = new QAction(tr("Follow UAV heading"), this);
1423 followUAVheadingAct->setShortcut(tr("Ctrl+F"));
1424 followUAVheadingAct->setStatusTip(tr("Keep the map rotation to the UAV heading"));
1425 followUAVheadingAct->setCheckable(true);
1426 followUAVheadingAct->setChecked(false);
1427 connect(followUAVheadingAct, SIGNAL(toggled(bool)), this, SLOT(onFollowUAVheadingAct_toggled(bool)));
1430 TODO: Waypoint support is disabled for v1.0
1433 #ifdef USE_PATHPLANNER
1434 wayPointEditorAct = new QAction(tr("&Waypoint editor"), this);
1435 wayPointEditorAct->setShortcut(tr("Ctrl+W"));
1436 wayPointEditorAct->setStatusTip(tr("Open the waypoint editor"));
1437 connect(wayPointEditorAct, SIGNAL(triggered()), this, SLOT(onOpenWayPointEditorAct_triggered()));
1439 addWayPointActFromContextMenu = new QAction(tr("&Add waypoint"), this);
1440 addWayPointActFromContextMenu->setShortcut(tr("Ctrl+A"));
1441 addWayPointActFromContextMenu->setStatusTip(tr("Add waypoint"));
1442 connect(addWayPointActFromContextMenu, SIGNAL(triggered()), this, SLOT(onAddWayPointAct_triggeredFromContextMenu()));
1444 addWayPointActFromThis = new QAction(tr("&Add waypoint"), this);
1445 addWayPointActFromThis->setShortcut(tr("Ctrl+A"));
1446 addWayPointActFromThis->setStatusTip(tr("Add waypoint"));
1447 connect(addWayPointActFromThis, SIGNAL(triggered()), this, SLOT(onAddWayPointAct_triggeredFromThis()));
1448 this->addAction(addWayPointActFromThis);
1450 editWayPointAct = new QAction(tr("&Edit waypoint"), this);
1451 editWayPointAct->setShortcut(tr("Ctrl+E"));
1452 editWayPointAct->setStatusTip(tr("Edit waypoint"));
1453 connect(editWayPointAct, SIGNAL(triggered()), this, SLOT(onEditWayPointAct_triggered()));
1455 lockWayPointAct = new QAction(tr("&Lock waypoint"), this);
1456 lockWayPointAct->setStatusTip(tr("Lock/Unlock a waypoint"));
1457 lockWayPointAct->setCheckable(true);
1458 lockWayPointAct->setChecked(false);
1459 connect(lockWayPointAct, SIGNAL(triggered()), this, SLOT(onLockWayPointAct_triggered()));
1461 deleteWayPointAct = new QAction(tr("&Delete waypoint"), this);
1462 deleteWayPointAct->setShortcut(tr("Ctrl+D"));
1463 deleteWayPointAct->setStatusTip(tr("Delete waypoint"));
1464 connect(deleteWayPointAct, SIGNAL(triggered()), this, SLOT(onDeleteWayPointAct_triggered()));
1466 clearWayPointsAct = new QAction(tr("&Clear waypoints"), this);
1467 clearWayPointsAct->setShortcut(tr("Ctrl+C"));
1468 clearWayPointsAct->setStatusTip(tr("Clear waypoints"));
1469 connect(clearWayPointsAct, SIGNAL(triggered()), this, SLOT(onClearWayPointsAct_triggered()));
1470 #endif // ifdef USE_PATHPLANNER
1471 overlayOpacityActGroup = new QActionGroup(this);
1472 connect(overlayOpacityActGroup, SIGNAL(triggered(QAction *)), this, SLOT(onOverlayOpacityActGroup_triggered(QAction *)));
1473 overlayOpacityAct.clear();
1474 for (int i = 0; i <= 10; i++) {
1475 QAction *overlayAct = new QAction(QString::number(i * 10), overlayOpacityActGroup);
1476 overlayAct->setCheckable(true);
1477 overlayAct->setData(i * 10);
1478 overlayOpacityAct.append(overlayAct);
1481 homeMagicWaypointAct = new QAction(tr("Home magic waypoint"), this);
1482 homeMagicWaypointAct->setStatusTip(tr("Move the magic waypoint to the home position"));
1483 connect(homeMagicWaypointAct, SIGNAL(triggered()), this, SLOT(onHomeMagicWaypointAct_triggered()));
1485 mapModeActGroup = new QActionGroup(this);
1486 connect(mapModeActGroup, SIGNAL(triggered(QAction *)), this, SLOT(onMapModeActGroup_triggered(QAction *)));
1487 mapModeAct.clear();
1489 QAction *map_mode_act;
1491 map_mode_act = new QAction(tr("Normal"), mapModeActGroup);
1492 map_mode_act->setCheckable(true);
1493 map_mode_act->setChecked(m_map_mode == Normal_MapMode);
1494 map_mode_act->setData((int)Normal_MapMode);
1495 mapModeAct.append(map_mode_act);
1497 map_mode_act = new QAction(tr("Magic Waypoint"), mapModeActGroup);
1498 map_mode_act->setCheckable(true);
1499 map_mode_act->setChecked(m_map_mode == MagicWaypoint_MapMode);
1500 map_mode_act->setData((int)MagicWaypoint_MapMode);
1501 mapModeAct.append(map_mode_act);
1504 zoomActGroup = new QActionGroup(this);
1505 connect(zoomActGroup, SIGNAL(triggered(QAction *)), this, SLOT(onZoomActGroup_triggered(QAction *)));
1506 zoomAct.clear();
1507 for (int i = m_min_zoom; i <= m_max_zoom; i++) {
1508 QAction *zoom_act = new QAction(QString::number(i), zoomActGroup);
1509 zoom_act->setCheckable(true);
1510 zoom_act->setData(i);
1511 zoomAct.append(zoom_act);
1514 maxUpdateRateActGroup = new QActionGroup(this);
1515 connect(maxUpdateRateActGroup, SIGNAL(triggered(QAction *)), this, SLOT(onMaxUpdateRateActGroup_triggered(QAction *)));
1516 maxUpdateRateAct.clear();
1517 list_size = sizeof(max_update_rate_list) / sizeof(max_update_rate_list[0]);
1518 for (int i = 0; i < list_size; i++) {
1519 QAction *maxUpdateRate_act;
1520 int j = max_update_rate_list[i];
1521 maxUpdateRate_act = new QAction(QString::number(j), maxUpdateRateActGroup);
1522 maxUpdateRate_act->setCheckable(true);
1523 maxUpdateRate_act->setData(j);
1524 maxUpdateRate_act->setChecked(j == m_maxUpdateRate);
1525 maxUpdateRateAct.append(maxUpdateRate_act);
1528 // *****
1529 // safe area
1531 showSafeAreaAct = new QAction(tr("Show Safe Area"), this);
1532 showSafeAreaAct->setStatusTip(tr("Show/Hide the Safe Area around the home location"));
1533 showSafeAreaAct->setCheckable(true);
1534 showSafeAreaAct->setChecked(m_map->Home->ShowSafeArea());
1535 connect(showSafeAreaAct, SIGNAL(toggled(bool)), this, SLOT(onShowSafeAreaAct_toggled(bool)));
1537 safeAreaActGroup = new QActionGroup(this);
1538 connect(safeAreaActGroup, SIGNAL(triggered(QAction *)), this, SLOT(onSafeAreaActGroup_triggered(QAction *)));
1539 safeAreaAct.clear();
1540 list_size = sizeof(safe_area_radius_list) / sizeof(safe_area_radius_list[0]);
1541 for (int i = 0; i < list_size; i++) {
1542 int safeArea = safe_area_radius_list[i];
1543 QAction *safeArea_act = new QAction(QString::number(safeArea) + "m", safeAreaActGroup);
1544 safeArea_act->setCheckable(true);
1545 safeArea_act->setChecked(safeArea == m_map->Home->SafeArea());
1546 safeArea_act->setData(safeArea);
1547 safeAreaAct.append(safeArea_act);
1550 // *****
1551 // UAV trail
1553 uavTrailTypeActGroup = new QActionGroup(this);
1554 connect(uavTrailTypeActGroup, SIGNAL(triggered(QAction *)), this, SLOT(onUAVTrailTypeActGroup_triggered(QAction *)));
1555 uavTrailTypeAct.clear();
1556 QStringList uav_trail_type_list = mapcontrol::Helper::UAVTrailTypes();
1557 for (int i = 0; i < uav_trail_type_list.count(); i++) {
1558 mapcontrol::UAVTrailType::Types uav_trail_type = mapcontrol::Helper::UAVTrailTypeFromString(uav_trail_type_list[i]);
1559 QAction *uavTrailType_act = new QAction(mapcontrol::Helper::StrFromUAVTrailType(uav_trail_type), uavTrailTypeActGroup);
1560 uavTrailType_act->setCheckable(true);
1561 uavTrailType_act->setChecked(uav_trail_type == m_map->UAV->GetTrailType());
1562 uavTrailType_act->setData(i);
1563 uavTrailTypeAct.append(uavTrailType_act);
1566 showTrailAct = new QAction(tr("Show Trail dots"), this);
1567 showTrailAct->setStatusTip(tr("Show/Hide the Trail dots"));
1568 showTrailAct->setCheckable(true);
1569 showTrailAct->setChecked(true);
1570 connect(showTrailAct, SIGNAL(toggled(bool)), this, SLOT(onShowTrailAct_toggled(bool)));
1572 showTrailLineAct = new QAction(tr("Show Trail lines"), this);
1573 showTrailLineAct->setStatusTip(tr("Show/Hide the Trail lines"));
1574 showTrailLineAct->setCheckable(true);
1575 showTrailLineAct->setChecked(true);
1576 connect(showTrailLineAct, SIGNAL(toggled(bool)), this, SLOT(onShowTrailLineAct_toggled(bool)));
1578 clearUAVtrailAct = new QAction(tr("Clear UAV trail"), this);
1579 clearUAVtrailAct->setStatusTip(tr("Clear the UAV trail"));
1580 connect(clearUAVtrailAct, SIGNAL(triggered()), this, SLOT(onClearUAVtrailAct_triggered()));
1582 uavTrailTimeActGroup = new QActionGroup(this);
1583 connect(uavTrailTimeActGroup, SIGNAL(triggered(QAction *)), this, SLOT(onUAVTrailTimeActGroup_triggered(QAction *)));
1584 uavTrailTimeAct.clear();
1585 list_size = sizeof(uav_trail_time_list) / sizeof(uav_trail_time_list[0]);
1586 for (int i = 0; i < list_size; i++) {
1587 int uav_trail_time = uav_trail_time_list[i];
1588 QAction *uavTrailTime_act = new QAction(QString::number(uav_trail_time) + " sec", uavTrailTimeActGroup);
1589 uavTrailTime_act->setCheckable(true);
1590 uavTrailTime_act->setChecked(uav_trail_time == m_map->UAV->TrailTime());
1591 uavTrailTime_act->setData(uav_trail_time);
1592 uavTrailTimeAct.append(uavTrailTime_act);
1595 uavTrailDistanceActGroup = new QActionGroup(this);
1596 connect(uavTrailDistanceActGroup, SIGNAL(triggered(QAction *)), this, SLOT(onUAVTrailDistanceActGroup_triggered(QAction *)));
1597 uavTrailDistanceAct.clear();
1598 list_size = sizeof(uav_trail_distance_list) / sizeof(uav_trail_distance_list[0]);
1599 for (int i = 0; i < list_size; i++) {
1600 int uav_trail_distance = uav_trail_distance_list[i];
1601 QAction *uavTrailDistance_act = new QAction(QString::number(uav_trail_distance) + " meters", uavTrailDistanceActGroup);
1602 uavTrailDistance_act->setCheckable(true);
1603 uavTrailDistance_act->setChecked(uav_trail_distance == m_map->UAV->TrailDistance());
1604 uavTrailDistance_act->setData(uav_trail_distance);
1605 uavTrailDistanceAct.append(uavTrailDistance_act);
1609 void OPMapGadgetWidget::onReloadAct_triggered()
1611 if (!m_widget || !m_map) {
1612 return;
1615 m_map->ReloadMap();
1618 void OPMapGadgetWidget::onRipAct_triggered()
1620 m_map->RipMap();
1623 void OPMapGadgetWidget::onCopyMouseLatLonToClipAct_triggered()
1625 QClipboard *clipboard = QApplication::clipboard();
1627 clipboard->setText(QString::number(m_context_menu_lat_lon.Lat(), 'f', 7) + ", " + QString::number(m_context_menu_lat_lon.Lng(), 'f', 7), QClipboard::Clipboard);
1630 void OPMapGadgetWidget::onCopyMouseLatToClipAct_triggered()
1632 QClipboard *clipboard = QApplication::clipboard();
1634 clipboard->setText(QString::number(m_context_menu_lat_lon.Lat(), 'f', 7), QClipboard::Clipboard);
1637 void OPMapGadgetWidget::onCopyMouseLonToClipAct_triggered()
1639 QClipboard *clipboard = QApplication::clipboard();
1641 clipboard->setText(QString::number(m_context_menu_lat_lon.Lng(), 'f', 7), QClipboard::Clipboard);
1645 void OPMapGadgetWidget::onShowCompassAct_toggled(bool show)
1647 if (!m_widget || !m_map) {
1648 return;
1651 m_map->SetShowCompass(show);
1654 void OPMapGadgetWidget::onShowDiagnostics_toggled(bool show)
1656 if (!m_widget || !m_map) {
1657 return;
1660 m_map->SetShowDiagnostics(show);
1663 void OPMapGadgetWidget::onShowNav_toggled(bool show)
1665 if (!m_widget || !m_map) {
1666 return;
1669 m_map->SetShowNav(show);
1672 void OPMapGadgetWidget::onShowUAVInfo_toggled(bool show)
1674 if (!m_widget || !m_map) {
1675 return;
1678 m_map->UAV->SetShowUAVInfo(show);
1681 void OPMapGadgetWidget::onShowHomeAct_toggled(bool show)
1683 if (!m_widget || !m_map) {
1684 return;
1687 m_map->Home->setVisible(show);
1690 void OPMapGadgetWidget::onShowUAVAct_toggled(bool show)
1692 if (!m_widget || !m_map) {
1693 return;
1696 m_map->UAV->setVisible(show);
1697 if (m_map->GPS) {
1698 m_map->GPS->setVisible(show);
1702 void OPMapGadgetWidget::onShowTrailAct_toggled(bool show)
1704 if (!m_widget || !m_map) {
1705 return;
1708 m_map->UAV->SetShowTrail(show);
1709 if (m_map->GPS) {
1710 m_map->GPS->SetShowTrail(show);
1714 void OPMapGadgetWidget::onShowTrailLineAct_toggled(bool show)
1716 if (!m_widget || !m_map) {
1717 return;
1720 m_map->UAV->SetShowTrailLine(show);
1721 if (m_map->GPS) {
1722 m_map->GPS->SetShowTrailLine(show);
1726 void OPMapGadgetWidget::onMapModeActGroup_triggered(QAction *action)
1728 if (!m_widget || !m_map || !action) {
1729 return;
1732 opMapModeType mode = (opMapModeType)action->data().toInt();
1734 setMapMode(mode);
1737 void OPMapGadgetWidget::onGoZoomInAct_triggered()
1739 zoomIn();
1742 void OPMapGadgetWidget::onGoZoomOutAct_triggered()
1744 zoomOut();
1747 void OPMapGadgetWidget::onZoomActGroup_triggered(QAction *action)
1749 if (!m_widget || !m_map || !action) {
1750 return;
1753 setZoom(action->data().toInt());
1756 void OPMapGadgetWidget::onMaxUpdateRateActGroup_triggered(QAction *action)
1758 if (!m_widget || !m_map || !action) {
1759 return;
1762 setMaxUpdateRate(action->data().toInt());
1765 void OPMapGadgetWidget::onChangeDefaultLocalAndZoom()
1767 emit defaultLocationAndZoomChanged(m_map->CurrentPosition().Lng(), m_map->CurrentPosition().Lat(), m_map->ZoomTotal());
1770 void OPMapGadgetWidget::onGoMouseClickAct_triggered()
1772 if (!m_widget || !m_map) {
1773 return;
1776 m_map->SetCurrentPosition(m_map->currentMousePosition()); // center the map onto the mouse position
1779 void OPMapGadgetWidget::onSetHomeAct_triggered()
1781 if (!m_widget || !m_map) {
1782 return;
1785 float altitude = 0;
1786 bool ok;
1788 // Get desired HomeLocation altitude from dialog box.
1789 // TODO: Populate box with altitude already in HomeLocation UAVO
1790 altitude = QInputDialog::getDouble(this, tr("Set home altitude"),
1791 tr("In [m], referenced to WGS84:"), altitude, -100, 100000, 2, &ok);
1793 if (ok) {
1794 setHome(m_context_menu_lat_lon, altitude);
1795 setHomeLocationObject(); // update the HomeLocation UAVObject
1799 void OPMapGadgetWidget::onGoHomeAct_triggered()
1801 if (!m_widget || !m_map) {
1802 return;
1805 goHome();
1808 void OPMapGadgetWidget::onGoUAVAct_triggered()
1810 if (!m_widget || !m_map) {
1811 return;
1814 double latitude;
1815 double longitude;
1816 double altitude;
1817 if (getUAVPosition(latitude, longitude, altitude)) { // get current UAV position
1818 internals::PointLatLng uav_pos = internals::PointLatLng(latitude, longitude); // current UAV position
1819 internals::PointLatLng map_pos = m_map->CurrentPosition(); // current MAP position
1820 if (map_pos != uav_pos) {
1821 m_map->SetCurrentPosition(uav_pos); // center the map onto the UAV
1826 void OPMapGadgetWidget::onFollowUAVpositionAct_toggled(bool checked)
1828 if (!m_widget || !m_map) {
1829 return;
1832 if (m_widget->toolButtonMapUAV->isChecked() != checked) {
1833 m_widget->toolButtonMapUAV->setChecked(checked);
1836 setMapFollowingMode();
1839 void OPMapGadgetWidget::onFollowUAVheadingAct_toggled(bool checked)
1841 if (!m_widget || !m_map) {
1842 return;
1845 if (m_widget->toolButtonMapUAVheading->isChecked() != checked) {
1846 m_widget->toolButtonMapUAVheading->setChecked(checked);
1849 setMapFollowingMode();
1852 void OPMapGadgetWidget::onUAVTrailTypeActGroup_triggered(QAction *action)
1854 if (!m_widget || !m_map || !action) {
1855 return;
1858 int trail_type_idx = action->data().toInt();
1860 QStringList uav_trail_type_list = mapcontrol::Helper::UAVTrailTypes();
1861 mapcontrol::UAVTrailType::Types uav_trail_type = mapcontrol::Helper::UAVTrailTypeFromString(uav_trail_type_list[trail_type_idx]);
1863 m_map->UAV->SetTrailType(uav_trail_type);
1866 void OPMapGadgetWidget::onClearUAVtrailAct_triggered()
1868 if (!m_widget || !m_map) {
1869 return;
1872 m_map->UAV->DeleteTrail();
1873 if (m_map->GPS) {
1874 m_map->GPS->DeleteTrail();
1878 void OPMapGadgetWidget::onUAVTrailTimeActGroup_triggered(QAction *action)
1880 if (!m_widget || !m_map || !action) {
1881 return;
1884 int trail_time = (double)action->data().toInt();
1886 m_map->UAV->SetTrailTime(trail_time);
1889 void OPMapGadgetWidget::onUAVTrailDistanceActGroup_triggered(QAction *action)
1891 if (!m_widget || !m_map || !action) {
1892 return;
1895 int trail_distance = action->data().toInt();
1897 m_map->UAV->SetTrailDistance(trail_distance);
1900 void OPMapGadgetWidget::onOpenWayPointEditorAct_triggered()
1902 // open dialog
1903 table->show();
1904 // bring dialog to the front in case it was already open and hidden away
1905 table->raise();
1908 void OPMapGadgetWidget::onAddWayPointAct_triggeredFromContextMenu()
1910 onAddWayPointAct_triggered(m_context_menu_lat_lon);
1912 void OPMapGadgetWidget::onAddWayPointAct_triggeredFromThis()
1914 onAddWayPointAct_triggered(lastLatLngMouse);
1917 void OPMapGadgetWidget::onAddWayPointAct_triggered(internals::PointLatLng coord)
1919 if (!m_widget || !m_map) {
1920 return;
1923 if (m_map_mode != Normal_MapMode) {
1924 return;
1927 mapProxy->createWayPoint(coord);
1932 * Called when the user asks to edit a waypoint from the map
1934 * TODO: should open an interface to edit waypoint properties, or
1935 * propagate the signal to a specific WP plugin (tbd).
1938 void OPMapGadgetWidget::onEditWayPointAct_triggered()
1940 if (!m_widget || !m_map) {
1941 return;
1944 if (m_map_mode != Normal_MapMode) {
1945 return;
1948 if (!m_mouse_waypoint) {
1949 return;
1952 waypoint_edit_dialog->editWaypoint(m_mouse_waypoint);
1953 m_mouse_waypoint = NULL;
1958 * TODO: unused for v1.0
1961 void OPMapGadgetWidget::onLockWayPointAct_triggered()
1963 if (!m_widget || !m_map || !m_mouse_waypoint) {
1964 return;
1967 if (m_map_mode != Normal_MapMode) {
1968 return;
1971 bool locked = (m_mouse_waypoint->flags() & QGraphicsItem::ItemIsMovable) == 0;
1972 m_mouse_waypoint->setFlag(QGraphicsItem::ItemIsMovable, locked);
1974 if (!locked) {
1975 m_mouse_waypoint->picture.load(":/markers/images/wp_marker_orange.png");
1976 } else {
1977 m_mouse_waypoint->picture.load(":/markers/images/wp_marker_red.png");
1979 m_mouse_waypoint->update();
1981 m_mouse_waypoint = NULL;
1984 void OPMapGadgetWidget::onDeleteWayPointAct_triggered()
1986 if (!m_widget || !m_map) {
1987 return;
1990 if (m_map_mode != Normal_MapMode) {
1991 return;
1994 if (!m_mouse_waypoint) {
1995 return;
1998 mapProxy->deleteWayPoint(m_mouse_waypoint->Number());
2001 void OPMapGadgetWidget::onClearWayPointsAct_triggered()
2003 // First, ask to ensure this is what the user wants to do
2004 QMessageBox msgBox;
2006 msgBox.setText(tr("Are you sure you want to clear waypoints?"));
2007 msgBox.setInformativeText(tr("All associated data will be lost."));
2008 msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
2009 int ret = msgBox.exec();
2011 if (ret == QMessageBox::No) {
2012 return;
2015 if (!m_widget || !m_map) {
2016 return;
2019 if (m_map_mode != Normal_MapMode) {
2020 return;
2023 mapProxy->deleteAll();
2027 void OPMapGadgetWidget::onHomeMagicWaypointAct_triggered()
2029 // center the magic waypoint on the home position
2030 homeMagicWaypoint();
2033 void OPMapGadgetWidget::onShowSafeAreaAct_toggled(bool show)
2035 if (!m_widget || !m_map) {
2036 return;
2039 m_map->Home->SetShowSafeArea(show); // show the safe area
2040 m_map->Home->SetToggleRefresh(true);
2041 m_map->Home->RefreshPos();
2044 void OPMapGadgetWidget::onSafeAreaActGroup_triggered(QAction *action)
2046 if (!m_widget || !m_map || !action) {
2047 return;
2050 int radius = action->data().toInt();
2052 m_map->Home->SetSafeArea(radius); // set the radius (meters)
2053 m_map->Home->RefreshPos();
2055 // move the magic waypoint if need be to keep it within the safe area around the home position
2056 keepMagicWaypointWithinSafeArea();
2060 * move the magic waypoint to the home position
2062 void OPMapGadgetWidget::homeMagicWaypoint()
2064 if (!m_widget || !m_map) {
2065 return;
2068 if (m_map_mode != MagicWaypoint_MapMode) {
2069 return;
2072 magicWayPoint->SetCoord(m_home_position.coord);
2075 // *************************************************************************************
2076 // move the UAV to the magic waypoint position
2078 void OPMapGadgetWidget::moveToMagicWaypointPosition()
2080 if (!m_widget || !m_map) {
2081 return;
2084 if (m_map_mode != MagicWaypoint_MapMode) {
2085 return;
2088 magicWayPoint->SetCoord(magicWayPoint->Coord());
2089 keepMagicWaypointWithinSafeArea();
2092 // *************************************************************************************
2093 // show/hide the magic waypoint controls
2095 void OPMapGadgetWidget::hideMagicWaypointControls()
2097 m_widget->lineWaypoint->setVisible(false);
2098 m_widget->toolButtonHomeWaypoint->setVisible(false);
2099 m_widget->toolButtonMoveToWP->setVisible(false);
2102 void OPMapGadgetWidget::showMagicWaypointControls()
2104 m_widget->lineWaypoint->setVisible(true);
2105 m_widget->toolButtonHomeWaypoint->setVisible(true);
2107 #if defined(allow_manual_home_location_move)
2108 m_widget->toolButtonMoveToWP->setVisible(true);
2109 #else
2110 m_widget->toolButtonMoveToWP->setVisible(false);
2111 #endif
2114 // *************************************************************************************
2115 // move the magic waypoint to keep it within the safe area boundry
2117 void OPMapGadgetWidget::keepMagicWaypointWithinSafeArea()
2119 bool moveMagicWP = false;
2120 // calcute the bearing and distance from the home position to the magic waypoint
2121 double dist = distance(m_home_position.coord, magicWayPoint->Coord());
2122 double bear = bearing(m_home_position.coord, magicWayPoint->Coord());
2124 // get the maximum safe distance - in kilometers
2125 double boundry_dist = (double)m_map->Home->SafeArea() / 1000;
2127 if (dist > boundry_dist) {
2128 dist = boundry_dist;
2129 moveMagicWP = true;
2132 // move the magic waypoint;
2133 if ((m_map_mode == MagicWaypoint_MapMode) && moveMagicWP) { // if needed, move the on-screen waypoint to the safe area
2134 if (magicWayPoint) {
2135 magicWayPoint->SetCoord(destPoint(m_home_position.coord, bear, dist));
2140 // *************************************************************************************
2141 // return the distance between two points .. in kilometers
2143 double OPMapGadgetWidget::distance(internals::PointLatLng from, internals::PointLatLng to)
2145 double lat1 = from.Lat() * deg_to_rad;
2146 double lon1 = from.Lng() * deg_to_rad;
2148 double lat2 = to.Lat() * deg_to_rad;
2149 double lon2 = to.Lng() * deg_to_rad;
2151 return acos(sin(lat1) * sin(lat2) + cos(lat1) * cos(lat2) * cos(lon2 - lon1)) * earth_mean_radius;
2153 // ***********************
2156 // *************************************************************************************
2157 // return the bearing from one point to another .. in degrees
2159 double OPMapGadgetWidget::bearing(internals::PointLatLng from, internals::PointLatLng to)
2161 double lat1 = from.Lat() * deg_to_rad;
2162 double lon1 = from.Lng() * deg_to_rad;
2164 double lat2 = to.Lat() * deg_to_rad;
2165 double lon2 = to.Lng() * deg_to_rad;
2167 // double delta_lat = lat2 - lat1;
2168 double delta_lon = lon2 - lon1;
2170 double y = sin(delta_lon) * cos(lat2);
2171 double x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(delta_lon);
2172 double bear = atan2(y, x) * rad_to_deg;
2174 bear += 360;
2175 while (bear < 0) {
2176 bear += 360;
2178 while (bear >= 360) {
2179 bear -= 360;
2182 return bear;
2185 // *************************************************************************************
2186 // return a destination lat/lon point given a source lat/lon point and the bearing and distance from the source point
2188 internals::PointLatLng OPMapGadgetWidget::destPoint(internals::PointLatLng source, double bear, double dist)
2190 double lat1 = source.Lat() * deg_to_rad;
2191 double lon1 = source.Lng() * deg_to_rad;
2193 bear *= deg_to_rad;
2195 double ad = dist / earth_mean_radius;
2197 double lat2 = asin(sin(lat1) * cos(ad) + cos(lat1) * sin(ad) * cos(bear));
2198 double lon2 = lon1 + atan2(sin(bear) * sin(ad) * cos(lat1), cos(ad) - sin(lat1) * sin(lat2));
2200 return internals::PointLatLng(lat2 * rad_to_deg, lon2 * rad_to_deg);
2203 // *************************************************************************************
2205 bool OPMapGadgetWidget::getUAVPosition(double &latitude, double &longitude, double &altitude)
2207 double NED[3];
2208 double LLA[3];
2209 double homeLLA[3];
2211 Q_ASSERT(obm != NULL);
2213 PositionState *positionState = PositionState::GetInstance(obm);
2214 Q_ASSERT(positionState != NULL);
2215 PositionState::DataFields positionStateData = positionState->getData();
2216 if (positionStateData.North == 0 && positionStateData.East == 0 && positionStateData.Down == 0) {
2217 GPSPositionSensor *gpsPositionObj = GPSPositionSensor::GetInstance(obm);
2218 Q_ASSERT(gpsPositionObj);
2220 GPSPositionSensor::DataFields gpsPositionData = gpsPositionObj->getData();
2221 latitude = gpsPositionData.Latitude / 1.0e7;
2222 longitude = gpsPositionData.Longitude / 1.0e7;
2223 altitude = gpsPositionData.Altitude;
2224 return true;
2226 HomeLocation *homeLocation = HomeLocation::GetInstance(obm);
2227 Q_ASSERT(homeLocation != NULL);
2228 HomeLocation::DataFields homeLocationData = homeLocation->getData();
2230 homeLLA[0] = homeLocationData.Latitude / 1.0e7;
2231 homeLLA[1] = homeLocationData.Longitude / 1.0e7;
2232 homeLLA[2] = homeLocationData.Altitude;
2234 NED[0] = positionStateData.North;
2235 NED[1] = positionStateData.East;
2236 NED[2] = positionStateData.Down;
2238 Utils::CoordinateConversions().NED2LLA_HomeLLA(homeLLA, NED, LLA);
2240 latitude = LLA[0];
2241 longitude = LLA[1];
2242 altitude = LLA[2];
2244 if (latitude != latitude) {
2245 latitude = 0; // nan detection
2246 } else if (latitude > 90) {
2247 latitude = 90;
2248 } else if (latitude < -90) {
2249 latitude = -90;
2252 if (longitude != longitude) {
2253 longitude = 0; // nan detection
2254 } else if (longitude > 180) {
2255 longitude = 180;
2256 } else if (longitude < -180) {
2257 longitude = -180;
2260 if (altitude != altitude) {
2261 altitude = 0; // nan detection
2263 return true;
2266 bool OPMapGadgetWidget::getNavPosition(double &latitude, double &longitude, double &altitude)
2268 double NED[3];
2269 double LLA[3];
2270 double homeLLA[3];
2272 Q_ASSERT(obm != NULL);
2274 PathDesired *pathDesired = PathDesired::GetInstance(obm);
2275 Q_ASSERT(pathDesired != NULL);
2276 PathDesired::DataFields pathDesiredData = pathDesired->getData();
2277 HomeLocation *homeLocation = HomeLocation::GetInstance(obm);
2278 Q_ASSERT(homeLocation != NULL);
2279 HomeLocation::DataFields homeLocationData = homeLocation->getData();
2281 homeLLA[0] = homeLocationData.Latitude / 1.0e7;
2282 homeLLA[1] = homeLocationData.Longitude / 1.0e7;
2283 homeLLA[2] = homeLocationData.Altitude;
2285 NED[0] = pathDesiredData.End[0];
2286 NED[1] = pathDesiredData.End[1];
2287 NED[2] = pathDesiredData.End[2];
2289 Utils::CoordinateConversions().NED2LLA_HomeLLA(homeLLA, NED, LLA);
2291 latitude = LLA[0];
2292 longitude = LLA[1];
2293 altitude = LLA[2];
2295 if (latitude != latitude) {
2296 latitude = 0; // nan detection
2297 } else if (latitude > 90) {
2298 latitude = 90;
2299 } else if (latitude < -90) {
2300 latitude = -90;
2303 if (longitude != longitude) {
2304 longitude = 0; // nan detection
2305 } else if (longitude > 180) {
2306 longitude = 180;
2307 } else if (longitude < -180) {
2308 longitude = -180;
2311 if (altitude != altitude) {
2312 altitude = 0; // nan detection
2314 return true;
2317 double OPMapGadgetWidget::getUAV_Yaw()
2319 if (!obm) {
2320 return 0;
2323 UAVObject *obj = dynamic_cast<UAVDataObject *>(obm->getObject(QString("AttitudeState")));
2324 double yaw = obj->getField(QString("Yaw"))->getDouble();
2326 if (yaw != yaw) {
2327 yaw = 0; // nan detection
2329 while (yaw < 0) {
2330 yaw += 360;
2332 while (yaw >= 360) {
2333 yaw -= 360;
2336 return yaw;
2339 bool OPMapGadgetWidget::getGPSPositionSensor(double &latitude, double &longitude, double &altitude)
2341 double LLA[3];
2343 if (!obum) {
2344 return false;
2347 if (obum->getGPSPositionSensor(LLA) < 0) {
2348 return false; // error
2350 latitude = LLA[0];
2351 longitude = LLA[1];
2352 altitude = LLA[2];
2354 return true;
2357 bool OPMapGadgetWidget::applyHomeLocationOnMap()
2359 bool set;
2360 double LLA[3];
2362 if (!obum) {
2363 return false;
2366 // fetch the home location
2367 if (obum->getHomeLocation(set, LLA) < 0) {
2368 return false; // error
2371 if (m_telemetry_connected) {
2372 setHome(internals::PointLatLng(LLA[0], LLA[1]), LLA[2]);
2373 if (m_map) {
2374 if (m_map->UAV->GetMapFollowType() != UAVMapFollowType::None) {
2375 m_map->SetCurrentPosition(m_home_position.coord); // set the map position
2378 return true;
2380 return false;
2383 // *************************************************************************************
2385 void OPMapGadgetWidget::setMapFollowingMode()
2387 if (!m_widget || !m_map) {
2388 return;
2391 if (!followUAVpositionAct->isChecked()) {
2392 m_map->UAV->SetMapFollowType(UAVMapFollowType::None);
2393 m_map->SetRotate(0); // reset map rotation to 0deg
2394 } else if (!followUAVheadingAct->isChecked()) {
2395 m_map->UAV->SetMapFollowType(UAVMapFollowType::CenterMap);
2396 m_map->SetRotate(0); // reset map rotation to 0deg
2397 } else {
2398 m_map->UAV->SetMapFollowType(UAVMapFollowType::CenterMap); // the map library won't let you reset the uav rotation if it's already in rotate mode
2400 m_map->UAV->SetUAVHeading(0); // reset the UAV heading to 0deg
2401 m_map->UAV->SetMapFollowType(UAVMapFollowType::CenterAndRotateMap);
2405 // *************************************************************************************
2406 // update the HomeLocation UAV Object
2408 bool OPMapGadgetWidget::setHomeLocationObject()
2410 if (!obum) {
2411 return false;
2414 double LLA[3] = { m_home_position.coord.Lat(), m_home_position.coord.Lng(), m_home_position.altitude };
2415 return obum->setHomeLocation(LLA, true) >= 0;
2418 // *************************************************************************************
2420 void OPMapGadgetWidget::SetUavPic(QString UAVPic)
2422 m_map->SetUavPic(UAVPic);
2425 void OPMapGadgetWidget::on_tbFind_clicked()
2427 QPalette pal = m_widget->leFind->palette();
2429 QString status = m_map->SetCurrentPositionByKeywords(m_widget->leFind->text());
2431 if (status == "OK") {
2432 pal.setColor(m_widget->leFind->backgroundRole(), Qt::green);
2433 m_widget->leFind->setPalette(pal);
2434 m_map->SetZoom(12);
2435 } else if (status == "ZERO_RESULTS") {
2436 pal.setColor(m_widget->leFind->backgroundRole(), Qt::red);
2437 m_widget->leFind->setPalette(pal);
2438 qDebug() << "No results";
2439 } else if (status == "OVER_QUERY_LIMIT") {
2440 pal.setColor(m_widget->leFind->backgroundRole(), Qt::yellow);
2441 m_widget->leFind->setPalette(pal);
2442 qDebug() << "You are over quota on queries";
2443 } else if (status == "REQUEST_DENIED") {
2444 pal.setColor(m_widget->leFind->backgroundRole(), Qt::darkRed);
2445 m_widget->leFind->setPalette(pal);
2446 qDebug() << "Request was denied";
2447 } else if (status == "INVALID_REQUEST") {
2448 pal.setColor(m_widget->leFind->backgroundRole(), Qt::darkYellow);
2449 m_widget->leFind->setPalette(pal);
2450 qDebug() << "Invalid request, missing address, lat long or location";
2451 } else if (status == "UNKNOWN_ERROR") {
2452 pal.setColor(m_widget->leFind->backgroundRole(), Qt::darkYellow);
2453 m_widget->leFind->setPalette(pal);
2454 qDebug() << "Some sort of server error.";
2455 } else {
2456 pal.setColor(m_widget->leFind->backgroundRole(), Qt::gray);
2457 m_widget->leFind->setPalette(pal);
2458 qDebug() << "Some sort of code error!";
2462 void OPMapGadgetWidget::onHomeDoubleClick(HomeItem *)
2464 new homeEditor(m_map->Home, this);
2467 void OPMapGadgetWidget::onOverlayOpacityActGroup_triggered(QAction *action)
2469 if (!m_widget || !m_map || !action) {
2470 return;
2473 m_map->setOverlayOpacity(action->data().toReal() / 100);
2474 emit overlayOpacityChanged(action->data().toReal() / 100);
2477 void OPMapGadgetWidget::on_leFind_returnPressed()
2479 on_tbFind_clicked();
2482 void OPMapGadgetWidget::setDefaultWaypointAltitude(qreal default_altitude)
2484 m_defaultWaypointAltitude = default_altitude;
2485 if (model) {
2486 model->setDefaultWaypointAltitude(default_altitude);
2490 void OPMapGadgetWidget::setDefaultWaypointVelocity(qreal default_velocity)
2492 m_defaultWaypointVelocity = default_velocity;
2493 if (model) {
2494 model->setDefaultWaypointVelocity(default_velocity);