LP-498 updated copyright headers in modified files
[librepilot.git] / ground / gcs / src / plugins / opmap / opmapgadgetwidget.cpp
blob8db51bbdaa47669e3d21b3470cfbb26f52638819
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 poisition 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;
920 bool set;
921 double LLA[3];
923 // ***********************
924 // fetch the home location
926 if (obum->getHomeLocation(set, LLA) < 0) {
927 return; // error
929 setHome(internals::PointLatLng(LLA[0], LLA[1]), LLA[2]);
931 if (m_map) {
932 if (m_map->UAV->GetMapFollowType() != UAVMapFollowType::None) {
933 m_map->SetCurrentPosition(m_home_position.coord); // set the map position
936 // ***********************
939 void OPMapGadgetWidget::onTelemetryDisconnect()
941 m_telemetry_connected = false;
944 // Updates the Home position icon whenever the HomePosition object is updated
945 void OPMapGadgetWidget::homePositionUpdated(UAVObject *hp)
947 Q_UNUSED(hp);
948 if (!obum) {
949 return;
951 bool set;
952 double LLA[3];
953 if (obum->getHomeLocation(set, LLA) < 0) {
954 return; // error
956 setHome(internals::PointLatLng(LLA[0], LLA[1]), LLA[2]);
959 // *************************************************************************************
960 // public functions
963 Sets the home position on the map widget
965 void OPMapGadgetWidget::setHome(QPointF pos)
967 if (!m_widget || !m_map) {
968 return;
971 double latitude = pos.x();
972 double longitude = pos.y();
974 if (latitude > 90) {
975 latitude = 90;
976 } else if (latitude < -90) {
977 latitude = -90;
980 if (longitude != longitude) {
981 longitude = 0; // nan detection
982 } else if (longitude > 180) {
983 longitude = 180;
984 } else if (longitude < -180) {
985 longitude = -180;
988 setHome(internals::PointLatLng(latitude, longitude), 0);
992 Sets the home position on the map widget
994 void OPMapGadgetWidget::setHome(internals::PointLatLng pos_lat_lon, double altitude)
996 if (!m_widget || !m_map) {
997 return;
1000 if (pos_lat_lon.Lat() != pos_lat_lon.Lat() || pos_lat_lon.Lng() != pos_lat_lon.Lng()) {
1001 return;
1003 ; // nan prevention
1005 double latitude = pos_lat_lon.Lat();
1006 double longitude = pos_lat_lon.Lng();
1008 if (latitude != latitude) {
1009 latitude = 0; // nan detection
1010 } else if (latitude > 90) {
1011 latitude = 90;
1012 } else if (latitude < -90) {
1013 latitude = -90;
1016 if (longitude != longitude) {
1017 longitude = 0; // nan detection
1018 } else if (longitude > 180) {
1019 longitude = 180;
1020 } else if (longitude < -180) {
1021 longitude = -180;
1024 // *********
1026 m_home_position.coord = internals::PointLatLng(latitude, longitude);
1027 m_home_position.altitude = altitude;
1029 m_map->Home->SetCoord(m_home_position.coord);
1030 m_map->Home->SetAltitude(altitude);
1031 m_map->Home->RefreshPos();
1033 // move the magic waypoint to keep it within the safe area boundry
1034 keepMagicWaypointWithInSafeArea();
1039 Centers the map over the home position
1041 void OPMapGadgetWidget::goHome()
1043 if (!m_widget || !m_map) {
1044 return;
1047 followUAVpositionAct->setChecked(false);
1049 internals::PointLatLng home_pos = m_home_position.coord; // get the home location
1050 m_map->SetCurrentPosition(home_pos); // center the map onto the home location
1054 void OPMapGadgetWidget::zoomIn()
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::zoomOut()
1073 if (!m_widget || !m_map) {
1074 return;
1077 int zoom = m_map->ZoomTotal() - 1;
1079 if (zoom < m_min_zoom) {
1080 zoom = m_min_zoom;
1081 } else if (zoom > m_max_zoom) {
1082 zoom = m_max_zoom;
1085 m_map->SetZoom(zoom);
1088 void OPMapGadgetWidget::setMaxUpdateRate(int update_rate)
1090 if (!m_widget || !m_map) {
1091 return;
1094 int list_size = sizeof(max_update_rate_list) / sizeof(max_update_rate_list[0]);
1095 int min_rate = max_update_rate_list[0];
1096 int max_rate = max_update_rate_list[list_size - 1];
1098 if (update_rate < min_rate) {
1099 update_rate = min_rate;
1100 } else if (update_rate > max_rate) {
1101 update_rate = max_rate;
1104 m_maxUpdateRate = update_rate;
1106 if (m_updateTimer) {
1107 m_updateTimer->setInterval(m_maxUpdateRate);
1110 // if (m_statusUpdateTimer)
1111 // m_statusUpdateTimer->setInterval(m_maxUpdateRate);
1114 void OPMapGadgetWidget::setZoom(int zoom)
1116 if (!m_widget || !m_map) {
1117 return;
1120 if (zoom < m_min_zoom) {
1121 zoom = m_min_zoom;
1122 } else if (zoom > m_max_zoom) {
1123 zoom = m_max_zoom;
1126 internals::MouseWheelZoomType::Types zoom_type = m_map->GetMouseWheelZoomType();
1127 m_map->SetMouseWheelZoomType(internals::MouseWheelZoomType::ViewCenter);
1129 m_map->SetZoom(zoom);
1131 m_map->SetMouseWheelZoomType(zoom_type);
1133 void OPMapGadgetWidget::setOverlayOpacity(qreal value)
1135 if (!m_widget || !m_map) {
1136 return;
1138 m_map->setOverlayOpacity(value);
1139 overlayOpacityAct.at(value * 10)->setChecked(true);
1142 void OPMapGadgetWidget::setHomePosition(QPointF pos)
1144 if (!m_widget || !m_map) {
1145 return;
1148 double latitude = pos.y();
1149 double longitude = pos.x();
1151 if (latitude != latitude || longitude != longitude) {
1152 return; // nan prevention
1154 if (latitude > 90) {
1155 latitude = 90;
1156 } else if (latitude < -90) {
1157 latitude = -90;
1160 if (longitude > 180) {
1161 longitude = 180;
1162 } else if (longitude < -180) {
1163 longitude = -180;
1166 m_map->Home->SetCoord(internals::PointLatLng(latitude, longitude));
1169 void OPMapGadgetWidget::setPosition(QPointF pos)
1171 if (!m_widget || !m_map) {
1172 return;
1175 double latitude = pos.y();
1176 double longitude = pos.x();
1178 if (latitude != latitude || longitude != longitude) {
1179 return; // nan prevention
1181 if (latitude > 90) {
1182 latitude = 90;
1183 } else if (latitude < -90) {
1184 latitude = -90;
1187 if (longitude > 180) {
1188 longitude = 180;
1189 } else if (longitude < -180) {
1190 longitude = -180;
1193 m_map->SetCurrentPosition(internals::PointLatLng(latitude, longitude));
1196 void OPMapGadgetWidget::setMapProvider(QString provider)
1198 if (!m_widget || !m_map) {
1199 return;
1202 m_map->SetMapType(mapcontrol::Helper::MapTypeFromString(provider));
1205 void OPMapGadgetWidget::setAccessMode(QString accessMode)
1207 if (!m_widget || !m_map) {
1208 return;
1211 m_map->configuration->SetAccessMode(mapcontrol::Helper::AccessModeFromString(accessMode));
1214 void OPMapGadgetWidget::setUseOpenGL(bool useOpenGL)
1216 if (!m_widget || !m_map) {
1217 return;
1220 m_map->SetUseOpenGL(useOpenGL);
1223 void OPMapGadgetWidget::setShowTileGridLines(bool showTileGridLines)
1225 if (!m_widget || !m_map) {
1226 return;
1229 m_map->SetShowTileGridLines(showTileGridLines);
1232 void OPMapGadgetWidget::setUseMemoryCache(bool useMemoryCache)
1234 if (!m_widget || !m_map) {
1235 return;
1238 m_map->configuration->SetUseMemoryCache(useMemoryCache);
1241 void OPMapGadgetWidget::setCacheLocation(QString cacheLocation)
1243 if (!m_widget || !m_map) {
1244 return;
1247 cacheLocation = cacheLocation.simplified(); // remove any surrounding spaces
1249 if (cacheLocation.isEmpty()) {
1250 return;
1253 if (!cacheLocation.endsWith(QDir::separator())) {
1254 cacheLocation += QDir::separator();
1257 QDir dir;
1258 if (!dir.exists(cacheLocation)) {
1259 if (!dir.mkpath(cacheLocation)) {
1260 return;
1263 m_map->configuration->SetCacheLocation(cacheLocation);
1266 void OPMapGadgetWidget::setMapMode(opMapModeType mode)
1268 if (!m_widget || !m_map) {
1269 return;
1272 if (mode != Normal_MapMode && mode != MagicWaypoint_MapMode) {
1273 mode = Normal_MapMode; // fix error
1275 if (m_map_mode == mode) { // no change in map mode
1276 switch (mode) { // make sure the UI buttons are set correctly
1277 case Normal_MapMode:
1278 m_widget->toolButtonMagicWaypointMapMode->setChecked(false);
1279 m_widget->toolButtonNormalMapMode->setChecked(true);
1280 break;
1281 case MagicWaypoint_MapMode:
1282 m_widget->toolButtonNormalMapMode->setChecked(false);
1283 m_widget->toolButtonMagicWaypointMapMode->setChecked(true);
1284 break;
1286 return;
1289 switch (mode) {
1290 case Normal_MapMode:
1291 m_map_mode = Normal_MapMode;
1293 m_widget->toolButtonMagicWaypointMapMode->setChecked(false);
1294 m_widget->toolButtonNormalMapMode->setChecked(true);
1296 hideMagicWaypointControls();
1298 magicWayPoint->setVisible(false);
1299 m_map->WPSetVisibleAll(true);
1301 break;
1303 case MagicWaypoint_MapMode:
1304 m_map_mode = MagicWaypoint_MapMode;
1306 m_widget->toolButtonNormalMapMode->setChecked(false);
1307 m_widget->toolButtonMagicWaypointMapMode->setChecked(true);
1309 showMagicWaypointControls();
1311 // delete the normal waypoints from the map
1313 m_map->WPSetVisibleAll(false);
1314 magicWayPoint->setVisible(true);
1316 break;
1320 // *************************************************************************************
1321 // Context menu stuff
1323 void OPMapGadgetWidget::createActions()
1325 int list_size;
1327 if (!m_widget || !m_map) {
1328 return;
1331 // ***********************
1332 // create menu actions
1334 reloadAct = new QAction(tr("&Reload map"), this);
1335 reloadAct->setShortcut(tr("F5"));
1336 reloadAct->setStatusTip(tr("Reload the map tiles"));
1337 connect(reloadAct, SIGNAL(triggered()), this, SLOT(onReloadAct_triggered()));
1338 this->addAction(reloadAct);
1339 ripAct = new QAction(tr("&Rip map"), this);
1340 ripAct->setStatusTip(tr("Rip the map tiles"));
1341 connect(ripAct, SIGNAL(triggered()), this, SLOT(onRipAct_triggered()));
1343 copyMouseLatLonToClipAct = new QAction(tr("Mouse latitude and longitude"), this);
1344 copyMouseLatLonToClipAct->setStatusTip(tr("Copy the mouse latitude and longitude to the clipboard"));
1345 connect(copyMouseLatLonToClipAct, SIGNAL(triggered()), this, SLOT(onCopyMouseLatLonToClipAct_triggered()));
1347 copyMouseLatToClipAct = new QAction(tr("Mouse latitude"), this);
1348 copyMouseLatToClipAct->setStatusTip(tr("Copy the mouse latitude to the clipboard"));
1349 connect(copyMouseLatToClipAct, SIGNAL(triggered()), this, SLOT(onCopyMouseLatToClipAct_triggered()));
1351 copyMouseLonToClipAct = new QAction(tr("Mouse longitude"), this);
1352 copyMouseLonToClipAct->setStatusTip(tr("Copy the mouse longitude to the clipboard"));
1353 connect(copyMouseLonToClipAct, SIGNAL(triggered()), this, SLOT(onCopyMouseLonToClipAct_triggered()));
1355 showCompassAct = new QAction(tr("Show compass"), this);
1356 showCompassAct->setStatusTip(tr("Show/Hide the compass"));
1357 showCompassAct->setCheckable(true);
1358 showCompassAct->setChecked(true);
1359 connect(showCompassAct, SIGNAL(toggled(bool)), this, SLOT(onShowCompassAct_toggled(bool)));
1361 showDiagnostics = new QAction(tr("Show Diagnostics"), this);
1362 showDiagnostics->setStatusTip(tr("Show/Hide the diagnostics"));
1363 showDiagnostics->setCheckable(true);
1364 showDiagnostics->setChecked(false);
1365 connect(showDiagnostics, SIGNAL(toggled(bool)), this, SLOT(onShowDiagnostics_toggled(bool)));
1367 showNav = new QAction(tr("Show Nav"), this);
1368 showNav->setStatusTip(tr("Show/Hide pathfollower info"));
1369 showNav->setCheckable(true);
1370 showNav->setChecked(false);
1371 connect(showNav, SIGNAL(toggled(bool)), this, SLOT(onShowNav_toggled(bool)));
1373 showUAVInfo = new QAction(tr("Show UAV Info"), this);
1374 showUAVInfo->setStatusTip(tr("Show/Hide the UAV info"));
1375 showUAVInfo->setCheckable(true);
1376 showUAVInfo->setChecked(false);
1377 connect(showUAVInfo, SIGNAL(toggled(bool)), this, SLOT(onShowUAVInfo_toggled(bool)));
1379 showHomeAct = new QAction(tr("Show Home"), this);
1380 showHomeAct->setStatusTip(tr("Show/Hide the Home location"));
1381 showHomeAct->setCheckable(true);
1382 showHomeAct->setChecked(true);
1383 connect(showHomeAct, SIGNAL(toggled(bool)), this, SLOT(onShowHomeAct_toggled(bool)));
1385 showUAVAct = new QAction(tr("Show UAV"), this);
1386 showUAVAct->setStatusTip(tr("Show/Hide the UAV"));
1387 showUAVAct->setCheckable(true);
1388 showUAVAct->setChecked(true);
1389 connect(showUAVAct, SIGNAL(toggled(bool)), this, SLOT(onShowUAVAct_toggled(bool)));
1391 changeDefaultLocalAndZoom = new QAction(tr("Set default zoom and location"), this);
1392 changeDefaultLocalAndZoom->setStatusTip(tr("Changes the map default zoom and location to the current values"));
1393 connect(changeDefaultLocalAndZoom, SIGNAL(triggered()), this, SLOT(onChangeDefaultLocalAndZoom()));
1395 zoomInAct = new QAction(tr("Zoom &In"), this);
1396 zoomInAct->setShortcut(Qt::Key_PageUp);
1397 zoomInAct->setStatusTip(tr("Zoom the map in"));
1398 connect(zoomInAct, SIGNAL(triggered()), this, SLOT(onGoZoomInAct_triggered()));
1399 this->addAction(zoomInAct);
1401 zoomOutAct = new QAction(tr("Zoom &Out"), this);
1402 zoomOutAct->setShortcut(Qt::Key_PageDown);
1403 zoomOutAct->setStatusTip(tr("Zoom the map out"));
1404 connect(zoomOutAct, SIGNAL(triggered()), this, SLOT(onGoZoomOutAct_triggered()));
1405 this->addAction(zoomOutAct);
1407 goMouseClickAct = new QAction(tr("Go to where you right clicked the mouse"), this);
1408 goMouseClickAct->setStatusTip(tr("Center the map onto where you right clicked the mouse"));
1409 connect(goMouseClickAct, SIGNAL(triggered()), this, SLOT(onGoMouseClickAct_triggered()));
1411 setHomeAct = new QAction(tr("Set the home location"), this);
1412 setHomeAct->setStatusTip(tr("Set the home location to where you clicked"));
1413 #if !defined(allow_manual_home_location_move)
1414 setHomeAct->setEnabled(false);
1415 #endif
1416 connect(setHomeAct, SIGNAL(triggered()), this, SLOT(onSetHomeAct_triggered()));
1418 goHomeAct = new QAction(tr("Go to &Home location"), this);
1419 goHomeAct->setShortcut(tr("Ctrl+H"));
1420 goHomeAct->setStatusTip(tr("Center the map onto the home location"));
1421 connect(goHomeAct, SIGNAL(triggered()), this, SLOT(onGoHomeAct_triggered()));
1423 goUAVAct = new QAction(tr("Go to &UAV location"), this);
1424 goUAVAct->setShortcut(tr("Ctrl+U"));
1425 goUAVAct->setStatusTip(tr("Center the map onto the UAV location"));
1426 connect(goUAVAct, SIGNAL(triggered()), this, SLOT(onGoUAVAct_triggered()));
1428 followUAVpositionAct = new QAction(tr("Follow UAV position"), this);
1429 followUAVpositionAct->setShortcut(tr("Ctrl+F"));
1430 followUAVpositionAct->setStatusTip(tr("Keep the map centered onto the UAV"));
1431 followUAVpositionAct->setCheckable(true);
1432 followUAVpositionAct->setChecked(false);
1433 connect(followUAVpositionAct, SIGNAL(toggled(bool)), this, SLOT(onFollowUAVpositionAct_toggled(bool)));
1435 followUAVheadingAct = new QAction(tr("Follow UAV heading"), this);
1436 followUAVheadingAct->setShortcut(tr("Ctrl+F"));
1437 followUAVheadingAct->setStatusTip(tr("Keep the map rotation to the UAV heading"));
1438 followUAVheadingAct->setCheckable(true);
1439 followUAVheadingAct->setChecked(false);
1440 connect(followUAVheadingAct, SIGNAL(toggled(bool)), this, SLOT(onFollowUAVheadingAct_toggled(bool)));
1443 TODO: Waypoint support is disabled for v1.0
1446 #ifdef USE_PATHPLANNER
1447 wayPointEditorAct = new QAction(tr("&Waypoint editor"), this);
1448 wayPointEditorAct->setShortcut(tr("Ctrl+W"));
1449 wayPointEditorAct->setStatusTip(tr("Open the waypoint editor"));
1450 connect(wayPointEditorAct, SIGNAL(triggered()), this, SLOT(onOpenWayPointEditorAct_triggered()));
1452 addWayPointActFromContextMenu = new QAction(tr("&Add waypoint"), this);
1453 addWayPointActFromContextMenu->setShortcut(tr("Ctrl+A"));
1454 addWayPointActFromContextMenu->setStatusTip(tr("Add waypoint"));
1455 connect(addWayPointActFromContextMenu, SIGNAL(triggered()), this, SLOT(onAddWayPointAct_triggeredFromContextMenu()));
1457 addWayPointActFromThis = new QAction(tr("&Add waypoint"), this);
1458 addWayPointActFromThis->setShortcut(tr("Ctrl+A"));
1459 addWayPointActFromThis->setStatusTip(tr("Add waypoint"));
1460 connect(addWayPointActFromThis, SIGNAL(triggered()), this, SLOT(onAddWayPointAct_triggeredFromThis()));
1461 this->addAction(addWayPointActFromThis);
1463 editWayPointAct = new QAction(tr("&Edit waypoint"), this);
1464 editWayPointAct->setShortcut(tr("Ctrl+E"));
1465 editWayPointAct->setStatusTip(tr("Edit waypoint"));
1466 connect(editWayPointAct, SIGNAL(triggered()), this, SLOT(onEditWayPointAct_triggered()));
1468 lockWayPointAct = new QAction(tr("&Lock waypoint"), this);
1469 lockWayPointAct->setStatusTip(tr("Lock/Unlock a waypoint"));
1470 lockWayPointAct->setCheckable(true);
1471 lockWayPointAct->setChecked(false);
1472 connect(lockWayPointAct, SIGNAL(triggered()), this, SLOT(onLockWayPointAct_triggered()));
1474 deleteWayPointAct = new QAction(tr("&Delete waypoint"), this);
1475 deleteWayPointAct->setShortcut(tr("Ctrl+D"));
1476 deleteWayPointAct->setStatusTip(tr("Delete waypoint"));
1477 connect(deleteWayPointAct, SIGNAL(triggered()), this, SLOT(onDeleteWayPointAct_triggered()));
1479 clearWayPointsAct = new QAction(tr("&Clear waypoints"), this);
1480 clearWayPointsAct->setShortcut(tr("Ctrl+C"));
1481 clearWayPointsAct->setStatusTip(tr("Clear waypoints"));
1482 connect(clearWayPointsAct, SIGNAL(triggered()), this, SLOT(onClearWayPointsAct_triggered()));
1483 #endif // ifdef USE_PATHPLANNER
1484 overlayOpacityActGroup = new QActionGroup(this);
1485 connect(overlayOpacityActGroup, SIGNAL(triggered(QAction *)), this, SLOT(onOverlayOpacityActGroup_triggered(QAction *)));
1486 overlayOpacityAct.clear();
1487 for (int i = 0; i <= 10; i++) {
1488 QAction *overlayAct = new QAction(QString::number(i * 10), overlayOpacityActGroup);
1489 overlayAct->setCheckable(true);
1490 overlayAct->setData(i * 10);
1491 overlayOpacityAct.append(overlayAct);
1494 homeMagicWaypointAct = new QAction(tr("Home magic waypoint"), this);
1495 homeMagicWaypointAct->setStatusTip(tr("Move the magic waypoint to the home position"));
1496 connect(homeMagicWaypointAct, SIGNAL(triggered()), this, SLOT(onHomeMagicWaypointAct_triggered()));
1498 mapModeActGroup = new QActionGroup(this);
1499 connect(mapModeActGroup, SIGNAL(triggered(QAction *)), this, SLOT(onMapModeActGroup_triggered(QAction *)));
1500 mapModeAct.clear();
1502 QAction *map_mode_act;
1504 map_mode_act = new QAction(tr("Normal"), mapModeActGroup);
1505 map_mode_act->setCheckable(true);
1506 map_mode_act->setChecked(m_map_mode == Normal_MapMode);
1507 map_mode_act->setData((int)Normal_MapMode);
1508 mapModeAct.append(map_mode_act);
1510 map_mode_act = new QAction(tr("Magic Waypoint"), mapModeActGroup);
1511 map_mode_act->setCheckable(true);
1512 map_mode_act->setChecked(m_map_mode == MagicWaypoint_MapMode);
1513 map_mode_act->setData((int)MagicWaypoint_MapMode);
1514 mapModeAct.append(map_mode_act);
1517 zoomActGroup = new QActionGroup(this);
1518 connect(zoomActGroup, SIGNAL(triggered(QAction *)), this, SLOT(onZoomActGroup_triggered(QAction *)));
1519 zoomAct.clear();
1520 for (int i = m_min_zoom; i <= m_max_zoom; i++) {
1521 QAction *zoom_act = new QAction(QString::number(i), zoomActGroup);
1522 zoom_act->setCheckable(true);
1523 zoom_act->setData(i);
1524 zoomAct.append(zoom_act);
1527 maxUpdateRateActGroup = new QActionGroup(this);
1528 connect(maxUpdateRateActGroup, SIGNAL(triggered(QAction *)), this, SLOT(onMaxUpdateRateActGroup_triggered(QAction *)));
1529 maxUpdateRateAct.clear();
1530 list_size = sizeof(max_update_rate_list) / sizeof(max_update_rate_list[0]);
1531 for (int i = 0; i < list_size; i++) {
1532 QAction *maxUpdateRate_act;
1533 int j = max_update_rate_list[i];
1534 maxUpdateRate_act = new QAction(QString::number(j), maxUpdateRateActGroup);
1535 maxUpdateRate_act->setCheckable(true);
1536 maxUpdateRate_act->setData(j);
1537 maxUpdateRate_act->setChecked(j == m_maxUpdateRate);
1538 maxUpdateRateAct.append(maxUpdateRate_act);
1541 // *****
1542 // safe area
1544 showSafeAreaAct = new QAction(tr("Show Safe Area"), this);
1545 showSafeAreaAct->setStatusTip(tr("Show/Hide the Safe Area around the home location"));
1546 showSafeAreaAct->setCheckable(true);
1547 showSafeAreaAct->setChecked(m_map->Home->ShowSafeArea());
1548 connect(showSafeAreaAct, SIGNAL(toggled(bool)), this, SLOT(onShowSafeAreaAct_toggled(bool)));
1550 safeAreaActGroup = new QActionGroup(this);
1551 connect(safeAreaActGroup, SIGNAL(triggered(QAction *)), this, SLOT(onSafeAreaActGroup_triggered(QAction *)));
1552 safeAreaAct.clear();
1553 list_size = sizeof(safe_area_radius_list) / sizeof(safe_area_radius_list[0]);
1554 for (int i = 0; i < list_size; i++) {
1555 int safeArea = safe_area_radius_list[i];
1556 QAction *safeArea_act = new QAction(QString::number(safeArea) + "m", safeAreaActGroup);
1557 safeArea_act->setCheckable(true);
1558 safeArea_act->setChecked(safeArea == m_map->Home->SafeArea());
1559 safeArea_act->setData(safeArea);
1560 safeAreaAct.append(safeArea_act);
1563 // *****
1564 // UAV trail
1566 uavTrailTypeActGroup = new QActionGroup(this);
1567 connect(uavTrailTypeActGroup, SIGNAL(triggered(QAction *)), this, SLOT(onUAVTrailTypeActGroup_triggered(QAction *)));
1568 uavTrailTypeAct.clear();
1569 QStringList uav_trail_type_list = mapcontrol::Helper::UAVTrailTypes();
1570 for (int i = 0; i < uav_trail_type_list.count(); i++) {
1571 mapcontrol::UAVTrailType::Types uav_trail_type = mapcontrol::Helper::UAVTrailTypeFromString(uav_trail_type_list[i]);
1572 QAction *uavTrailType_act = new QAction(mapcontrol::Helper::StrFromUAVTrailType(uav_trail_type), uavTrailTypeActGroup);
1573 uavTrailType_act->setCheckable(true);
1574 uavTrailType_act->setChecked(uav_trail_type == m_map->UAV->GetTrailType());
1575 uavTrailType_act->setData(i);
1576 uavTrailTypeAct.append(uavTrailType_act);
1579 showTrailAct = new QAction(tr("Show Trail dots"), this);
1580 showTrailAct->setStatusTip(tr("Show/Hide the Trail dots"));
1581 showTrailAct->setCheckable(true);
1582 showTrailAct->setChecked(true);
1583 connect(showTrailAct, SIGNAL(toggled(bool)), this, SLOT(onShowTrailAct_toggled(bool)));
1585 showTrailLineAct = new QAction(tr("Show Trail lines"), this);
1586 showTrailLineAct->setStatusTip(tr("Show/Hide the Trail lines"));
1587 showTrailLineAct->setCheckable(true);
1588 showTrailLineAct->setChecked(true);
1589 connect(showTrailLineAct, SIGNAL(toggled(bool)), this, SLOT(onShowTrailLineAct_toggled(bool)));
1591 clearUAVtrailAct = new QAction(tr("Clear UAV trail"), this);
1592 clearUAVtrailAct->setStatusTip(tr("Clear the UAV trail"));
1593 connect(clearUAVtrailAct, SIGNAL(triggered()), this, SLOT(onClearUAVtrailAct_triggered()));
1595 uavTrailTimeActGroup = new QActionGroup(this);
1596 connect(uavTrailTimeActGroup, SIGNAL(triggered(QAction *)), this, SLOT(onUAVTrailTimeActGroup_triggered(QAction *)));
1597 uavTrailTimeAct.clear();
1598 list_size = sizeof(uav_trail_time_list) / sizeof(uav_trail_time_list[0]);
1599 for (int i = 0; i < list_size; i++) {
1600 int uav_trail_time = uav_trail_time_list[i];
1601 QAction *uavTrailTime_act = new QAction(QString::number(uav_trail_time) + " sec", uavTrailTimeActGroup);
1602 uavTrailTime_act->setCheckable(true);
1603 uavTrailTime_act->setChecked(uav_trail_time == m_map->UAV->TrailTime());
1604 uavTrailTime_act->setData(uav_trail_time);
1605 uavTrailTimeAct.append(uavTrailTime_act);
1608 uavTrailDistanceActGroup = new QActionGroup(this);
1609 connect(uavTrailDistanceActGroup, SIGNAL(triggered(QAction *)), this, SLOT(onUAVTrailDistanceActGroup_triggered(QAction *)));
1610 uavTrailDistanceAct.clear();
1611 list_size = sizeof(uav_trail_distance_list) / sizeof(uav_trail_distance_list[0]);
1612 for (int i = 0; i < list_size; i++) {
1613 int uav_trail_distance = uav_trail_distance_list[i];
1614 QAction *uavTrailDistance_act = new QAction(QString::number(uav_trail_distance) + " meters", uavTrailDistanceActGroup);
1615 uavTrailDistance_act->setCheckable(true);
1616 uavTrailDistance_act->setChecked(uav_trail_distance == m_map->UAV->TrailDistance());
1617 uavTrailDistance_act->setData(uav_trail_distance);
1618 uavTrailDistanceAct.append(uavTrailDistance_act);
1622 void OPMapGadgetWidget::onReloadAct_triggered()
1624 if (!m_widget || !m_map) {
1625 return;
1628 m_map->ReloadMap();
1631 void OPMapGadgetWidget::onRipAct_triggered()
1633 m_map->RipMap();
1636 void OPMapGadgetWidget::onCopyMouseLatLonToClipAct_triggered()
1638 QClipboard *clipboard = QApplication::clipboard();
1640 clipboard->setText(QString::number(m_context_menu_lat_lon.Lat(), 'f', 7) + ", " + QString::number(m_context_menu_lat_lon.Lng(), 'f', 7), QClipboard::Clipboard);
1643 void OPMapGadgetWidget::onCopyMouseLatToClipAct_triggered()
1645 QClipboard *clipboard = QApplication::clipboard();
1647 clipboard->setText(QString::number(m_context_menu_lat_lon.Lat(), 'f', 7), QClipboard::Clipboard);
1650 void OPMapGadgetWidget::onCopyMouseLonToClipAct_triggered()
1652 QClipboard *clipboard = QApplication::clipboard();
1654 clipboard->setText(QString::number(m_context_menu_lat_lon.Lng(), 'f', 7), QClipboard::Clipboard);
1658 void OPMapGadgetWidget::onShowCompassAct_toggled(bool show)
1660 if (!m_widget || !m_map) {
1661 return;
1664 m_map->SetShowCompass(show);
1667 void OPMapGadgetWidget::onShowDiagnostics_toggled(bool show)
1669 if (!m_widget || !m_map) {
1670 return;
1673 m_map->SetShowDiagnostics(show);
1676 void OPMapGadgetWidget::onShowNav_toggled(bool show)
1678 if (!m_widget || !m_map) {
1679 return;
1682 m_map->SetShowNav(show);
1685 void OPMapGadgetWidget::onShowUAVInfo_toggled(bool show)
1687 if (!m_widget || !m_map) {
1688 return;
1691 m_map->UAV->SetShowUAVInfo(show);
1694 void OPMapGadgetWidget::onShowHomeAct_toggled(bool show)
1696 if (!m_widget || !m_map) {
1697 return;
1700 m_map->Home->setVisible(show);
1703 void OPMapGadgetWidget::onShowUAVAct_toggled(bool show)
1705 if (!m_widget || !m_map) {
1706 return;
1709 m_map->UAV->setVisible(show);
1710 if (m_map->GPS) {
1711 m_map->GPS->setVisible(show);
1715 void OPMapGadgetWidget::onShowTrailAct_toggled(bool show)
1717 if (!m_widget || !m_map) {
1718 return;
1721 m_map->UAV->SetShowTrail(show);
1722 if (m_map->GPS) {
1723 m_map->GPS->SetShowTrail(show);
1727 void OPMapGadgetWidget::onShowTrailLineAct_toggled(bool show)
1729 if (!m_widget || !m_map) {
1730 return;
1733 m_map->UAV->SetShowTrailLine(show);
1734 if (m_map->GPS) {
1735 m_map->GPS->SetShowTrailLine(show);
1739 void OPMapGadgetWidget::onMapModeActGroup_triggered(QAction *action)
1741 if (!m_widget || !m_map || !action) {
1742 return;
1745 opMapModeType mode = (opMapModeType)action->data().toInt();
1747 setMapMode(mode);
1750 void OPMapGadgetWidget::onGoZoomInAct_triggered()
1752 zoomIn();
1755 void OPMapGadgetWidget::onGoZoomOutAct_triggered()
1757 zoomOut();
1760 void OPMapGadgetWidget::onZoomActGroup_triggered(QAction *action)
1762 if (!m_widget || !m_map || !action) {
1763 return;
1766 setZoom(action->data().toInt());
1769 void OPMapGadgetWidget::onMaxUpdateRateActGroup_triggered(QAction *action)
1771 if (!m_widget || !m_map || !action) {
1772 return;
1775 setMaxUpdateRate(action->data().toInt());
1778 void OPMapGadgetWidget::onChangeDefaultLocalAndZoom()
1780 emit defaultLocationAndZoomChanged(m_map->CurrentPosition().Lng(), m_map->CurrentPosition().Lat(), m_map->ZoomTotal());
1783 void OPMapGadgetWidget::onGoMouseClickAct_triggered()
1785 if (!m_widget || !m_map) {
1786 return;
1789 m_map->SetCurrentPosition(m_map->currentMousePosition()); // center the map onto the mouse position
1792 void OPMapGadgetWidget::onSetHomeAct_triggered()
1794 if (!m_widget || !m_map) {
1795 return;
1798 float altitude = 0;
1799 bool ok;
1801 // Get desired HomeLocation altitude from dialog box.
1802 // TODO: Populate box with altitude already in HomeLocation UAVO
1803 altitude = QInputDialog::getDouble(this, tr("Set home altitude"),
1804 tr("In [m], referenced to WGS84:"), altitude, -100, 100000, 2, &ok);
1806 setHome(m_context_menu_lat_lon, altitude);
1808 setHomeLocationObject(); // update the HomeLocation UAVObject
1811 void OPMapGadgetWidget::onGoHomeAct_triggered()
1813 if (!m_widget || !m_map) {
1814 return;
1817 goHome();
1820 void OPMapGadgetWidget::onGoUAVAct_triggered()
1822 if (!m_widget || !m_map) {
1823 return;
1826 double latitude;
1827 double longitude;
1828 double altitude;
1829 if (getUAVPosition(latitude, longitude, altitude)) { // get current UAV position
1830 internals::PointLatLng uav_pos = internals::PointLatLng(latitude, longitude); // current UAV position
1831 internals::PointLatLng map_pos = m_map->CurrentPosition(); // current MAP position
1832 if (map_pos != uav_pos) {
1833 m_map->SetCurrentPosition(uav_pos); // center the map onto the UAV
1838 void OPMapGadgetWidget::onFollowUAVpositionAct_toggled(bool checked)
1840 if (!m_widget || !m_map) {
1841 return;
1844 if (m_widget->toolButtonMapUAV->isChecked() != checked) {
1845 m_widget->toolButtonMapUAV->setChecked(checked);
1848 setMapFollowingMode();
1851 void OPMapGadgetWidget::onFollowUAVheadingAct_toggled(bool checked)
1853 if (!m_widget || !m_map) {
1854 return;
1857 if (m_widget->toolButtonMapUAVheading->isChecked() != checked) {
1858 m_widget->toolButtonMapUAVheading->setChecked(checked);
1861 setMapFollowingMode();
1864 void OPMapGadgetWidget::onUAVTrailTypeActGroup_triggered(QAction *action)
1866 if (!m_widget || !m_map || !action) {
1867 return;
1870 int trail_type_idx = action->data().toInt();
1872 QStringList uav_trail_type_list = mapcontrol::Helper::UAVTrailTypes();
1873 mapcontrol::UAVTrailType::Types uav_trail_type = mapcontrol::Helper::UAVTrailTypeFromString(uav_trail_type_list[trail_type_idx]);
1875 m_map->UAV->SetTrailType(uav_trail_type);
1878 void OPMapGadgetWidget::onClearUAVtrailAct_triggered()
1880 if (!m_widget || !m_map) {
1881 return;
1884 m_map->UAV->DeleteTrail();
1885 if (m_map->GPS) {
1886 m_map->GPS->DeleteTrail();
1890 void OPMapGadgetWidget::onUAVTrailTimeActGroup_triggered(QAction *action)
1892 if (!m_widget || !m_map || !action) {
1893 return;
1896 int trail_time = (double)action->data().toInt();
1898 m_map->UAV->SetTrailTime(trail_time);
1901 void OPMapGadgetWidget::onUAVTrailDistanceActGroup_triggered(QAction *action)
1903 if (!m_widget || !m_map || !action) {
1904 return;
1907 int trail_distance = action->data().toInt();
1909 m_map->UAV->SetTrailDistance(trail_distance);
1912 void OPMapGadgetWidget::onOpenWayPointEditorAct_triggered()
1914 // open dialog
1915 table->show();
1916 // bring dialog to the front in case it was already open and hidden away
1917 table->raise();
1920 void OPMapGadgetWidget::onAddWayPointAct_triggeredFromContextMenu()
1922 onAddWayPointAct_triggered(m_context_menu_lat_lon);
1924 void OPMapGadgetWidget::onAddWayPointAct_triggeredFromThis()
1926 onAddWayPointAct_triggered(lastLatLngMouse);
1929 void OPMapGadgetWidget::onAddWayPointAct_triggered(internals::PointLatLng coord)
1931 if (!m_widget || !m_map) {
1932 return;
1935 if (m_map_mode != Normal_MapMode) {
1936 return;
1939 mapProxy->createWayPoint(coord);
1944 * Called when the user asks to edit a waypoint from the map
1946 * TODO: should open an interface to edit waypoint properties, or
1947 * propagate the signal to a specific WP plugin (tbd).
1950 void OPMapGadgetWidget::onEditWayPointAct_triggered()
1952 if (!m_widget || !m_map) {
1953 return;
1956 if (m_map_mode != Normal_MapMode) {
1957 return;
1960 if (!m_mouse_waypoint) {
1961 return;
1964 waypoint_edit_dialog->editWaypoint(m_mouse_waypoint);
1965 m_mouse_waypoint = NULL;
1970 * TODO: unused for v1.0
1973 void OPMapGadgetWidget::onLockWayPointAct_triggered()
1975 if (!m_widget || !m_map || !m_mouse_waypoint) {
1976 return;
1979 if (m_map_mode != Normal_MapMode) {
1980 return;
1983 bool locked = (m_mouse_waypoint->flags() & QGraphicsItem::ItemIsMovable) == 0;
1984 m_mouse_waypoint->setFlag(QGraphicsItem::ItemIsMovable, locked);
1986 if (!locked) {
1987 m_mouse_waypoint->picture.load(QString::fromUtf8(":/opmap/images/waypoint_marker2.png"));
1988 } else {
1989 m_mouse_waypoint->picture.load(QString::fromUtf8(":/opmap/images/waypoint_marker1.png"));
1991 m_mouse_waypoint->update();
1993 m_mouse_waypoint = NULL;
1996 void OPMapGadgetWidget::onDeleteWayPointAct_triggered()
1998 if (!m_widget || !m_map) {
1999 return;
2002 if (m_map_mode != Normal_MapMode) {
2003 return;
2006 if (!m_mouse_waypoint) {
2007 return;
2010 mapProxy->deleteWayPoint(m_mouse_waypoint->Number());
2013 void OPMapGadgetWidget::onClearWayPointsAct_triggered()
2015 // First, ask to ensure this is what the user wants to do
2016 QMessageBox msgBox;
2018 msgBox.setText(tr("Are you sure you want to clear waypoints?"));
2019 msgBox.setInformativeText(tr("All associated data will be lost."));
2020 msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
2021 int ret = msgBox.exec();
2023 if (ret == QMessageBox::No) {
2024 return;
2027 if (!m_widget || !m_map) {
2028 return;
2031 if (m_map_mode != Normal_MapMode) {
2032 return;
2035 mapProxy->deleteAll();
2039 void OPMapGadgetWidget::onHomeMagicWaypointAct_triggered()
2041 // center the magic waypoint on the home position
2042 homeMagicWaypoint();
2045 void OPMapGadgetWidget::onShowSafeAreaAct_toggled(bool show)
2047 if (!m_widget || !m_map) {
2048 return;
2051 m_map->Home->SetShowSafeArea(show); // show the safe area
2052 m_map->Home->SetToggleRefresh(true);
2053 m_map->Home->RefreshPos();
2056 void OPMapGadgetWidget::onSafeAreaActGroup_triggered(QAction *action)
2058 if (!m_widget || !m_map || !action) {
2059 return;
2062 int radius = action->data().toInt();
2064 m_map->Home->SetSafeArea(radius); // set the radius (meters)
2065 m_map->Home->RefreshPos();
2067 // move the magic waypoint if need be to keep it within the safe area around the home position
2068 keepMagicWaypointWithInSafeArea();
2072 * move the magic waypoint to the home position
2074 void OPMapGadgetWidget::homeMagicWaypoint()
2076 if (!m_widget || !m_map) {
2077 return;
2080 if (m_map_mode != MagicWaypoint_MapMode) {
2081 return;
2084 magicWayPoint->SetCoord(m_home_position.coord);
2087 // *************************************************************************************
2088 // move the UAV to the magic waypoint position
2090 void OPMapGadgetWidget::moveToMagicWaypointPosition()
2092 if (!m_widget || !m_map) {
2093 return;
2096 if (m_map_mode != MagicWaypoint_MapMode) {
2097 return;
2101 // *************************************************************************************
2102 // show/hide the magic waypoint controls
2104 void OPMapGadgetWidget::hideMagicWaypointControls()
2106 m_widget->lineWaypoint->setVisible(false);
2107 m_widget->toolButtonHomeWaypoint->setVisible(false);
2108 m_widget->toolButtonMoveToWP->setVisible(false);
2111 void OPMapGadgetWidget::showMagicWaypointControls()
2113 m_widget->lineWaypoint->setVisible(true);
2114 m_widget->toolButtonHomeWaypoint->setVisible(true);
2116 #if defined(allow_manual_home_location_move)
2117 m_widget->toolButtonMoveToWP->setVisible(true);
2118 #else
2119 m_widget->toolButtonMoveToWP->setVisible(false);
2120 #endif
2123 // *************************************************************************************
2124 // move the magic waypoint to keep it within the safe area boundry
2126 void OPMapGadgetWidget::keepMagicWaypointWithInSafeArea()
2128 // calcute the bearing and distance from the home position to the magic waypoint
2129 double dist = distance(m_home_position.coord, magicWayPoint->Coord());
2130 double bear = bearing(m_home_position.coord, magicWayPoint->Coord());
2132 // get the maximum safe distance - in kilometers
2133 double boundry_dist = (double)m_map->Home->SafeArea() / 1000;
2135 if (dist > boundry_dist) {
2136 dist = boundry_dist;
2139 // move the magic waypoint;
2141 if (m_map_mode == MagicWaypoint_MapMode) { // move the on-screen waypoint
2142 if (magicWayPoint) {
2143 magicWayPoint->SetCoord(destPoint(m_home_position.coord, bear, dist));
2148 // *************************************************************************************
2149 // return the distance between two points .. in kilometers
2151 double OPMapGadgetWidget::distance(internals::PointLatLng from, internals::PointLatLng to)
2153 double lat1 = from.Lat() * deg_to_rad;
2154 double lon1 = from.Lng() * deg_to_rad;
2156 double lat2 = to.Lat() * deg_to_rad;
2157 double lon2 = to.Lng() * deg_to_rad;
2159 return acos(sin(lat1) * sin(lat2) + cos(lat1) * cos(lat2) * cos(lon2 - lon1)) * earth_mean_radius;
2161 // ***********************
2164 // *************************************************************************************
2165 // return the bearing from one point to another .. in degrees
2167 double OPMapGadgetWidget::bearing(internals::PointLatLng from, internals::PointLatLng to)
2169 double lat1 = from.Lat() * deg_to_rad;
2170 double lon1 = from.Lng() * deg_to_rad;
2172 double lat2 = to.Lat() * deg_to_rad;
2173 double lon2 = to.Lng() * deg_to_rad;
2175 // double delta_lat = lat2 - lat1;
2176 double delta_lon = lon2 - lon1;
2178 double y = sin(delta_lon) * cos(lat2);
2179 double x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(delta_lon);
2180 double bear = atan2(y, x) * rad_to_deg;
2182 bear += 360;
2183 while (bear < 0) {
2184 bear += 360;
2186 while (bear >= 360) {
2187 bear -= 360;
2190 return bear;
2193 // *************************************************************************************
2194 // return a destination lat/lon point given a source lat/lon point and the bearing and distance from the source point
2196 internals::PointLatLng OPMapGadgetWidget::destPoint(internals::PointLatLng source, double bear, double dist)
2198 double lat1 = source.Lat() * deg_to_rad;
2199 double lon1 = source.Lng() * deg_to_rad;
2201 bear *= deg_to_rad;
2203 double ad = dist / earth_mean_radius;
2205 double lat2 = asin(sin(lat1) * cos(ad) + cos(lat1) * sin(ad) * cos(bear));
2206 double lon2 = lon1 + atan2(sin(bear) * sin(ad) * cos(lat1), cos(ad) - sin(lat1) * sin(lat2));
2208 return internals::PointLatLng(lat2 * rad_to_deg, lon2 * rad_to_deg);
2211 // *************************************************************************************
2213 bool OPMapGadgetWidget::getUAVPosition(double &latitude, double &longitude, double &altitude)
2215 double NED[3];
2216 double LLA[3];
2217 double homeLLA[3];
2219 Q_ASSERT(obm != NULL);
2221 PositionState *positionState = PositionState::GetInstance(obm);
2222 Q_ASSERT(positionState != NULL);
2223 PositionState::DataFields positionStateData = positionState->getData();
2224 if (positionStateData.North == 0 && positionStateData.East == 0 && positionStateData.Down == 0) {
2225 GPSPositionSensor *gpsPositionObj = GPSPositionSensor::GetInstance(obm);
2226 Q_ASSERT(gpsPositionObj);
2228 GPSPositionSensor::DataFields gpsPositionData = gpsPositionObj->getData();
2229 latitude = gpsPositionData.Latitude / 1.0e7;
2230 longitude = gpsPositionData.Longitude / 1.0e7;
2231 altitude = gpsPositionData.Altitude;
2232 return true;
2234 HomeLocation *homeLocation = HomeLocation::GetInstance(obm);
2235 Q_ASSERT(homeLocation != NULL);
2236 HomeLocation::DataFields homeLocationData = homeLocation->getData();
2238 homeLLA[0] = homeLocationData.Latitude / 1.0e7;
2239 homeLLA[1] = homeLocationData.Longitude / 1.0e7;
2240 homeLLA[2] = homeLocationData.Altitude;
2242 NED[0] = positionStateData.North;
2243 NED[1] = positionStateData.East;
2244 NED[2] = positionStateData.Down;
2246 Utils::CoordinateConversions().NED2LLA_HomeLLA(homeLLA, NED, LLA);
2248 latitude = LLA[0];
2249 longitude = LLA[1];
2250 altitude = LLA[2];
2252 if (latitude != latitude) {
2253 latitude = 0; // nan detection
2254 } else if (latitude > 90) {
2255 latitude = 90;
2256 } else if (latitude < -90) {
2257 latitude = -90;
2260 if (longitude != longitude) {
2261 longitude = 0; // nan detection
2262 } else if (longitude > 180) {
2263 longitude = 180;
2264 } else if (longitude < -180) {
2265 longitude = -180;
2268 if (altitude != altitude) {
2269 altitude = 0; // nan detection
2271 return true;
2274 bool OPMapGadgetWidget::getNavPosition(double &latitude, double &longitude, double &altitude)
2276 double NED[3];
2277 double LLA[3];
2278 double homeLLA[3];
2280 Q_ASSERT(obm != NULL);
2282 PathDesired *pathDesired = PathDesired::GetInstance(obm);
2283 Q_ASSERT(pathDesired != NULL);
2284 PathDesired::DataFields pathDesiredData = pathDesired->getData();
2285 HomeLocation *homeLocation = HomeLocation::GetInstance(obm);
2286 Q_ASSERT(homeLocation != NULL);
2287 HomeLocation::DataFields homeLocationData = homeLocation->getData();
2289 homeLLA[0] = homeLocationData.Latitude / 1.0e7;
2290 homeLLA[1] = homeLocationData.Longitude / 1.0e7;
2291 homeLLA[2] = homeLocationData.Altitude;
2293 NED[0] = pathDesiredData.End[0];
2294 NED[1] = pathDesiredData.End[1];
2295 NED[2] = pathDesiredData.End[2];
2297 Utils::CoordinateConversions().NED2LLA_HomeLLA(homeLLA, NED, LLA);
2299 latitude = LLA[0];
2300 longitude = LLA[1];
2301 altitude = LLA[2];
2303 if (latitude != latitude) {
2304 latitude = 0; // nan detection
2305 } else if (latitude > 90) {
2306 latitude = 90;
2307 } else if (latitude < -90) {
2308 latitude = -90;
2311 if (longitude != longitude) {
2312 longitude = 0; // nan detection
2313 } else if (longitude > 180) {
2314 longitude = 180;
2315 } else if (longitude < -180) {
2316 longitude = -180;
2319 if (altitude != altitude) {
2320 altitude = 0; // nan detection
2322 return true;
2325 double OPMapGadgetWidget::getUAV_Yaw()
2327 if (!obm) {
2328 return 0;
2331 UAVObject *obj = dynamic_cast<UAVDataObject *>(obm->getObject(QString("AttitudeState")));
2332 double yaw = obj->getField(QString("Yaw"))->getDouble();
2334 if (yaw != yaw) {
2335 yaw = 0; // nan detection
2337 while (yaw < 0) {
2338 yaw += 360;
2340 while (yaw >= 360) {
2341 yaw -= 360;
2344 return yaw;
2347 bool OPMapGadgetWidget::getGPSPositionSensor(double &latitude, double &longitude, double &altitude)
2349 double LLA[3];
2351 if (!obum) {
2352 return false;
2355 if (obum->getGPSPositionSensor(LLA) < 0) {
2356 return false; // error
2358 latitude = LLA[0];
2359 longitude = LLA[1];
2360 altitude = LLA[2];
2362 return true;
2365 // *************************************************************************************
2367 void OPMapGadgetWidget::setMapFollowingMode()
2369 if (!m_widget || !m_map) {
2370 return;
2373 if (!followUAVpositionAct->isChecked()) {
2374 m_map->UAV->SetMapFollowType(UAVMapFollowType::None);
2375 m_map->SetRotate(0); // reset map rotation to 0deg
2376 } else if (!followUAVheadingAct->isChecked()) {
2377 m_map->UAV->SetMapFollowType(UAVMapFollowType::CenterMap);
2378 m_map->SetRotate(0); // reset map rotation to 0deg
2379 } else {
2380 m_map->UAV->SetMapFollowType(UAVMapFollowType::CenterMap); // the map library won't let you reset the uav rotation if it's already in rotate mode
2382 m_map->UAV->SetUAVHeading(0); // reset the UAV heading to 0deg
2383 m_map->UAV->SetMapFollowType(UAVMapFollowType::CenterAndRotateMap);
2387 // *************************************************************************************
2388 // update the HomeLocation UAV Object
2390 bool OPMapGadgetWidget::setHomeLocationObject()
2392 if (!obum) {
2393 return false;
2396 double LLA[3] = { m_home_position.coord.Lat(), m_home_position.coord.Lng(), m_home_position.altitude };
2397 return obum->setHomeLocation(LLA, true) >= 0;
2400 // *************************************************************************************
2402 void OPMapGadgetWidget::SetUavPic(QString UAVPic)
2404 m_map->SetUavPic(UAVPic);
2407 void OPMapGadgetWidget::on_tbFind_clicked()
2409 QPalette pal = m_widget->leFind->palette();
2411 QString status = m_map->SetCurrentPositionByKeywords(m_widget->leFind->text());
2413 if (status == "OK") {
2414 pal.setColor(m_widget->leFind->backgroundRole(), Qt::green);
2415 m_widget->leFind->setPalette(pal);
2416 m_map->SetZoom(12);
2417 } else if (status == "ZERO_RESULTS") {
2418 pal.setColor(m_widget->leFind->backgroundRole(), Qt::red);
2419 m_widget->leFind->setPalette(pal);
2420 qDebug() << "No results";
2421 } else if (status == "OVER_QUERY_LIMIT") {
2422 pal.setColor(m_widget->leFind->backgroundRole(), Qt::yellow);
2423 m_widget->leFind->setPalette(pal);
2424 qDebug() << "You are over quota on queries";
2425 } else if (status == "REQUEST_DENIED") {
2426 pal.setColor(m_widget->leFind->backgroundRole(), Qt::darkRed);
2427 m_widget->leFind->setPalette(pal);
2428 qDebug() << "Request was denied";
2429 } else if (status == "INVALID_REQUEST") {
2430 pal.setColor(m_widget->leFind->backgroundRole(), Qt::darkYellow);
2431 m_widget->leFind->setPalette(pal);
2432 qDebug() << "Invalid request, missing address, lat long or location";
2433 } else if (status == "UNKNOWN_ERROR") {
2434 pal.setColor(m_widget->leFind->backgroundRole(), Qt::darkYellow);
2435 m_widget->leFind->setPalette(pal);
2436 qDebug() << "Some sort of server error.";
2437 } else {
2438 pal.setColor(m_widget->leFind->backgroundRole(), Qt::gray);
2439 m_widget->leFind->setPalette(pal);
2440 qDebug() << "Some sort of code error!";
2444 void OPMapGadgetWidget::onHomeDoubleClick(HomeItem *)
2446 new homeEditor(m_map->Home, this);
2449 void OPMapGadgetWidget::onOverlayOpacityActGroup_triggered(QAction *action)
2451 if (!m_widget || !m_map || !action) {
2452 return;
2455 m_map->setOverlayOpacity(action->data().toReal() / 100);
2456 emit overlayOpacityChanged(action->data().toReal() / 100);
2459 void OPMapGadgetWidget::on_leFind_returnPressed()
2461 on_tbFind_clicked();
2464 void OPMapGadgetWidget::setDefaultWaypointAltitude(qreal default_altitude)
2466 m_defaultWaypointAltitude = default_altitude;
2467 if (model) {
2468 model->setDefaultWaypointAltitude(default_altitude);
2472 void OPMapGadgetWidget::setDefaultWaypointVelocity(qreal default_velocity)
2474 m_defaultWaypointVelocity = default_velocity;
2475 if (model) {
2476 model->setDefaultWaypointVelocity(default_velocity);