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
9 * @addtogroup OPMapPlugin OpenPilot Map Plugin
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
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>
39 #include <QStringList>
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 // *************************************************************************************
91 OPMapGadgetWidget::OPMapGadgetWidget(QWidget
*parent
) : QWidget(parent
)
97 findPlaceCompleter
= NULL
;
99 m_mouse_waypoint
= 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();
121 obm
= pm
->getObject
<UAVObjectManager
>();
122 obum
= pm
->getObject
<UAVObjectUtilManager
>();
126 // get current location
129 double longitude
= 0;
133 getUAVPosition(latitude
, longitude
, altitude
);
135 internals::PointLatLng pos_lat_lon
= internals::PointLatLng(latitude
, longitude
);
138 // default home position
140 m_home_position
.coord
= pos_lat_lon
;
141 m_home_position
.altitude
= altitude
;
142 m_home_position
.locked
= false;
145 // create the widget that holds the user controls and the map
147 m_widget
= new Ui::OPMap_Widget();
148 m_widget
->setupUi(this);
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);
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
);
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
);
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();
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()));
240 magicWayPoint
= m_map
->magicWPCreate();
241 magicWayPoint
->setVisible(false);
243 m_map
->setOverlayOpacity(0.5);
246 // create various context menu (mouse right click menu) actions
251 // connect to the UAVObject updates we require to become a bit aware of our environment:
254 // Register for Home Location state changes
256 UAVDataObject
*obj
= dynamic_cast<UAVDataObject
*>(obm
->getObject(QString("HomeLocation")));
258 connect(obj
, SIGNAL(objectUpdated(UAVObject
*)), this, SLOT(homePositionUpdated(UAVObject
*)));
262 // Listen to telemetry connection events
263 TelemetryManager
*telMngr
= pm
->getObject
<TelemetryManager
>();
265 connect(telMngr
, SIGNAL(connected()), this, SLOT(onTelemetryConnect()));
266 connect(telMngr
, SIGNAL(disconnected()), this, SLOT(onTelemetryDisconnect()));
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();
288 OPMapGadgetWidget::~OPMapGadgetWidget()
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); // " "
301 if (!model
.isNull()) {
304 if (!table
.isNull()) {
307 if (!selectionModel
.isNull()) {
308 delete selectionModel
;
310 if (!mapProxy
.isNull()) {
313 if (!waypoint_edit_dialog
.isNull()) {
314 delete waypoint_edit_dialog
;
316 if (!UAVProxy
.isNull()) {
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
) {
350 if (event
->reason() != QContextMenuEvent::Mouse
) {
351 // not a mouse click event
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
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
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();
395 switch (m_map_mode
) {
397 mapMode
= tr(" (Normal)");
399 case MagicWaypoint_MapMode
:
400 mapMode
= tr(" (Magic Waypoint)");
403 mapMode
= tr(" (Unknown)");
406 for (int i
= 0; i
< mapModeAct
.count(); i
++) {
407 // set the menu to checked (or not)
408 QAction
*act
= mapModeAct
.at(i
);
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(©SubMenu
);
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
);
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
);
471 contextMenu
.addSection(tr("Home"));
473 contextMenu
.addAction(setHomeAct
);
474 contextMenu
.addAction(showHomeAct
);
475 contextMenu
.addAction(goHomeAct
);
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
);
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
);
514 #ifdef USE_PATHPLANNER
515 switch (m_map_mode
) {
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()) {
538 contextMenu
.addAction(clearWayPointsAct
);
542 case MagicWaypoint_MapMode
:
543 contextMenu
.addSection(tr("Waypoints"));
544 contextMenu
.addAction(homeMagicWaypointAct
);
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
);
559 contextMenu
.exec(event
->globalPos());
562 void OPMapGadgetWidget::closeEvent(QCloseEvent
*event
)
565 QWidget::closeEvent(event
);
568 // *************************************************************************************
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
) {
587 QMutexLocker
locker(&m_map_mutex
);
590 // get the current UAV details
592 // get current UAV position
593 if (!getUAVPosition(uav_latitude
, uav_longitude
, uav_altitude
)) {
597 // get current UAV heading
598 uav_yaw
= getUAV_Yaw();
600 uav_pos
= internals::PointLatLng(uav_latitude
, uav_longitude
);
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.
653 // display the UAV position
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
);
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
671 // set the GPS icon position on the map
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();
682 // update active waypoint position at same update rate
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
699 void OPMapGadgetWidget::updateMousePos()
701 if (!m_widget
|| !m_map
) {
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);
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";
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 // *************************************************************************************
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
) {
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
) {
769 } else if (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
) {
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
) {
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
) {
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
) {
833 m_widget
->progressBarMap
->setVisible(false);
836 void OPMapGadgetWidget::on_toolButtonZoomP_clicked()
838 QMutexLocker
locker(&m_map_mutex
);
843 void OPMapGadgetWidget::on_toolButtonZoomM_clicked()
845 QMutexLocker
locker(&m_map_mutex
);
850 void OPMapGadgetWidget::on_toolButtonMapHome_clicked()
852 QMutexLocker
locker(&m_map_mutex
);
857 void OPMapGadgetWidget::on_toolButtonMapUAV_clicked()
859 if (!m_widget
|| !m_map
) {
863 QMutexLocker
locker(&m_map_mutex
);
865 followUAVpositionAct
->toggle();
868 void OPMapGadgetWidget::on_toolButtonMapUAVheading_clicked()
870 if (!m_widget
|| !m_map
) {
874 followUAVheadingAct
->toggle();
877 void OPMapGadgetWidget::on_horizontalSliderZoom_sliderMoved(int position
)
879 if (!m_widget
|| !m_map
) {
883 QMutexLocker
locker(&m_map_mutex
);
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()
904 void OPMapGadgetWidget::on_toolButtonMoveToWP_clicked()
906 moveToMagicWaypointPosition();
909 // *************************************************************************************
912 void OPMapGadgetWidget::onTelemetryConnect()
914 m_telemetry_connected
= true;
923 // ***********************
924 // fetch the home location
926 if (obum
->getHomeLocation(set
, LLA
) < 0) {
929 setHome(internals::PointLatLng(LLA
[0], LLA
[1]), LLA
[2]);
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
)
953 if (obum
->getHomeLocation(set
, LLA
) < 0) {
956 setHome(internals::PointLatLng(LLA
[0], LLA
[1]), LLA
[2]);
959 // *************************************************************************************
963 Sets the home position on the map widget
965 void OPMapGadgetWidget::setHome(QPointF pos
)
967 if (!m_widget
|| !m_map
) {
971 double latitude
= pos
.x();
972 double longitude
= pos
.y();
976 } else if (latitude
< -90) {
980 if (longitude
!= longitude
) {
981 longitude
= 0; // nan detection
982 } else if (longitude
> 180) {
984 } else if (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
) {
1000 if (pos_lat_lon
.Lat() != pos_lat_lon
.Lat() || pos_lat_lon
.Lng() != pos_lat_lon
.Lng()) {
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) {
1012 } else if (latitude
< -90) {
1016 if (longitude
!= longitude
) {
1017 longitude
= 0; // nan detection
1018 } else if (longitude
> 180) {
1020 } else if (longitude
< -180) {
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
) {
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
) {
1060 int zoom
= m_map
->ZoomTotal() + 1;
1062 if (zoom
< m_min_zoom
) {
1064 } else if (zoom
> m_max_zoom
) {
1068 m_map
->SetZoom(zoom
);
1071 void OPMapGadgetWidget::zoomOut()
1073 if (!m_widget
|| !m_map
) {
1077 int zoom
= m_map
->ZoomTotal() - 1;
1079 if (zoom
< m_min_zoom
) {
1081 } else if (zoom
> m_max_zoom
) {
1085 m_map
->SetZoom(zoom
);
1088 void OPMapGadgetWidget::setMaxUpdateRate(int update_rate
)
1090 if (!m_widget
|| !m_map
) {
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
) {
1120 if (zoom
< m_min_zoom
) {
1122 } else if (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
) {
1138 m_map
->setOverlayOpacity(value
);
1139 overlayOpacityAct
.at(value
* 10)->setChecked(true);
1142 void OPMapGadgetWidget::setHomePosition(QPointF pos
)
1144 if (!m_widget
|| !m_map
) {
1148 double latitude
= pos
.y();
1149 double longitude
= pos
.x();
1151 if (latitude
!= latitude
|| longitude
!= longitude
) {
1152 return; // nan prevention
1154 if (latitude
> 90) {
1156 } else if (latitude
< -90) {
1160 if (longitude
> 180) {
1162 } else if (longitude
< -180) {
1166 m_map
->Home
->SetCoord(internals::PointLatLng(latitude
, longitude
));
1169 void OPMapGadgetWidget::setPosition(QPointF pos
)
1171 if (!m_widget
|| !m_map
) {
1175 double latitude
= pos
.y();
1176 double longitude
= pos
.x();
1178 if (latitude
!= latitude
|| longitude
!= longitude
) {
1179 return; // nan prevention
1181 if (latitude
> 90) {
1183 } else if (latitude
< -90) {
1187 if (longitude
> 180) {
1189 } else if (longitude
< -180) {
1193 m_map
->SetCurrentPosition(internals::PointLatLng(latitude
, longitude
));
1196 void OPMapGadgetWidget::setMapProvider(QString provider
)
1198 if (!m_widget
|| !m_map
) {
1202 m_map
->SetMapType(mapcontrol::Helper::MapTypeFromString(provider
));
1205 void OPMapGadgetWidget::setAccessMode(QString accessMode
)
1207 if (!m_widget
|| !m_map
) {
1211 m_map
->configuration
->SetAccessMode(mapcontrol::Helper::AccessModeFromString(accessMode
));
1214 void OPMapGadgetWidget::setUseOpenGL(bool useOpenGL
)
1216 if (!m_widget
|| !m_map
) {
1220 m_map
->SetUseOpenGL(useOpenGL
);
1223 void OPMapGadgetWidget::setShowTileGridLines(bool showTileGridLines
)
1225 if (!m_widget
|| !m_map
) {
1229 m_map
->SetShowTileGridLines(showTileGridLines
);
1232 void OPMapGadgetWidget::setUseMemoryCache(bool useMemoryCache
)
1234 if (!m_widget
|| !m_map
) {
1238 m_map
->configuration
->SetUseMemoryCache(useMemoryCache
);
1241 void OPMapGadgetWidget::setCacheLocation(QString cacheLocation
)
1243 if (!m_widget
|| !m_map
) {
1247 cacheLocation
= cacheLocation
.simplified(); // remove any surrounding spaces
1249 if (cacheLocation
.isEmpty()) {
1253 if (!cacheLocation
.endsWith(QDir::separator())) {
1254 cacheLocation
+= QDir::separator();
1258 if (!dir
.exists(cacheLocation
)) {
1259 if (!dir
.mkpath(cacheLocation
)) {
1263 m_map
->configuration
->SetCacheLocation(cacheLocation
);
1266 void OPMapGadgetWidget::setMapMode(opMapModeType mode
)
1268 if (!m_widget
|| !m_map
) {
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);
1281 case MagicWaypoint_MapMode
:
1282 m_widget
->toolButtonNormalMapMode
->setChecked(false);
1283 m_widget
->toolButtonMagicWaypointMapMode
->setChecked(true);
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);
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);
1320 // *************************************************************************************
1321 // Context menu stuff
1323 void OPMapGadgetWidget::createActions()
1327 if (!m_widget
|| !m_map
) {
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);
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
*)));
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
*)));
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
);
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
);
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
) {
1631 void OPMapGadgetWidget::onRipAct_triggered()
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
) {
1664 m_map
->SetShowCompass(show
);
1667 void OPMapGadgetWidget::onShowDiagnostics_toggled(bool show
)
1669 if (!m_widget
|| !m_map
) {
1673 m_map
->SetShowDiagnostics(show
);
1676 void OPMapGadgetWidget::onShowNav_toggled(bool show
)
1678 if (!m_widget
|| !m_map
) {
1682 m_map
->SetShowNav(show
);
1685 void OPMapGadgetWidget::onShowUAVInfo_toggled(bool show
)
1687 if (!m_widget
|| !m_map
) {
1691 m_map
->UAV
->SetShowUAVInfo(show
);
1694 void OPMapGadgetWidget::onShowHomeAct_toggled(bool show
)
1696 if (!m_widget
|| !m_map
) {
1700 m_map
->Home
->setVisible(show
);
1703 void OPMapGadgetWidget::onShowUAVAct_toggled(bool show
)
1705 if (!m_widget
|| !m_map
) {
1709 m_map
->UAV
->setVisible(show
);
1711 m_map
->GPS
->setVisible(show
);
1715 void OPMapGadgetWidget::onShowTrailAct_toggled(bool show
)
1717 if (!m_widget
|| !m_map
) {
1721 m_map
->UAV
->SetShowTrail(show
);
1723 m_map
->GPS
->SetShowTrail(show
);
1727 void OPMapGadgetWidget::onShowTrailLineAct_toggled(bool show
)
1729 if (!m_widget
|| !m_map
) {
1733 m_map
->UAV
->SetShowTrailLine(show
);
1735 m_map
->GPS
->SetShowTrailLine(show
);
1739 void OPMapGadgetWidget::onMapModeActGroup_triggered(QAction
*action
)
1741 if (!m_widget
|| !m_map
|| !action
) {
1745 opMapModeType mode
= (opMapModeType
)action
->data().toInt();
1750 void OPMapGadgetWidget::onGoZoomInAct_triggered()
1755 void OPMapGadgetWidget::onGoZoomOutAct_triggered()
1760 void OPMapGadgetWidget::onZoomActGroup_triggered(QAction
*action
)
1762 if (!m_widget
|| !m_map
|| !action
) {
1766 setZoom(action
->data().toInt());
1769 void OPMapGadgetWidget::onMaxUpdateRateActGroup_triggered(QAction
*action
)
1771 if (!m_widget
|| !m_map
|| !action
) {
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
) {
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
) {
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
) {
1820 void OPMapGadgetWidget::onGoUAVAct_triggered()
1822 if (!m_widget
|| !m_map
) {
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
) {
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
) {
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
) {
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
) {
1884 m_map
->UAV
->DeleteTrail();
1886 m_map
->GPS
->DeleteTrail();
1890 void OPMapGadgetWidget::onUAVTrailTimeActGroup_triggered(QAction
*action
)
1892 if (!m_widget
|| !m_map
|| !action
) {
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
) {
1907 int trail_distance
= action
->data().toInt();
1909 m_map
->UAV
->SetTrailDistance(trail_distance
);
1912 void OPMapGadgetWidget::onOpenWayPointEditorAct_triggered()
1916 // bring dialog to the front in case it was already open and hidden away
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
) {
1935 if (m_map_mode
!= Normal_MapMode
) {
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
) {
1956 if (m_map_mode
!= Normal_MapMode
) {
1960 if (!m_mouse_waypoint
) {
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
) {
1979 if (m_map_mode
!= Normal_MapMode
) {
1983 bool locked
= (m_mouse_waypoint
->flags() & QGraphicsItem::ItemIsMovable
) == 0;
1984 m_mouse_waypoint
->setFlag(QGraphicsItem::ItemIsMovable
, locked
);
1987 m_mouse_waypoint
->picture
.load(QString::fromUtf8(":/opmap/images/waypoint_marker2.png"));
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
) {
2002 if (m_map_mode
!= Normal_MapMode
) {
2006 if (!m_mouse_waypoint
) {
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
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
) {
2027 if (!m_widget
|| !m_map
) {
2031 if (m_map_mode
!= Normal_MapMode
) {
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
) {
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
) {
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
) {
2080 if (m_map_mode
!= MagicWaypoint_MapMode
) {
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
) {
2096 if (m_map_mode
!= MagicWaypoint_MapMode
) {
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);
2119 m_widget
->toolButtonMoveToWP
->setVisible(false);
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
;
2186 while (bear
>= 360) {
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
;
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
)
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
;
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
);
2252 if (latitude
!= latitude
) {
2253 latitude
= 0; // nan detection
2254 } else if (latitude
> 90) {
2256 } else if (latitude
< -90) {
2260 if (longitude
!= longitude
) {
2261 longitude
= 0; // nan detection
2262 } else if (longitude
> 180) {
2264 } else if (longitude
< -180) {
2268 if (altitude
!= altitude
) {
2269 altitude
= 0; // nan detection
2274 bool OPMapGadgetWidget::getNavPosition(double &latitude
, double &longitude
, double &altitude
)
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
);
2303 if (latitude
!= latitude
) {
2304 latitude
= 0; // nan detection
2305 } else if (latitude
> 90) {
2307 } else if (latitude
< -90) {
2311 if (longitude
!= longitude
) {
2312 longitude
= 0; // nan detection
2313 } else if (longitude
> 180) {
2315 } else if (longitude
< -180) {
2319 if (altitude
!= altitude
) {
2320 altitude
= 0; // nan detection
2325 double OPMapGadgetWidget::getUAV_Yaw()
2331 UAVObject
*obj
= dynamic_cast<UAVDataObject
*>(obm
->getObject(QString("AttitudeState")));
2332 double yaw
= obj
->getField(QString("Yaw"))->getDouble();
2335 yaw
= 0; // nan detection
2340 while (yaw
>= 360) {
2347 bool OPMapGadgetWidget::getGPSPositionSensor(double &latitude
, double &longitude
, double &altitude
)
2355 if (obum
->getGPSPositionSensor(LLA
) < 0) {
2356 return false; // error
2365 // *************************************************************************************
2367 void OPMapGadgetWidget::setMapFollowingMode()
2369 if (!m_widget
|| !m_map
) {
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
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()
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
);
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.";
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
) {
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
;
2468 model
->setDefaultWaypointAltitude(default_altitude
);
2472 void OPMapGadgetWidget::setDefaultWaypointVelocity(qreal default_velocity
)
2474 m_defaultWaypointVelocity
= default_velocity
;
2476 model
->setDefaultWaypointVelocity(default_velocity
);