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 position change signals
213 connect(m_map
, SIGNAL(OnTileLoadComplete()), this, SLOT(OnTileLoadComplete())); // tile loading stop signals
214 connect(m_map
, SIGNAL(OnTileLoadStart()), this, SLOT(OnTileLoadStart())); // tile loading start signals
215 connect(m_map
, SIGNAL(OnTilesStillToLoad(int)), this, SLOT(OnTilesStillToLoad(int))); // tile loading signals
216 connect(m_map
, SIGNAL(OnWayPointDoubleClicked(WayPointItem
*)), this, SLOT(wpDoubleClickEvent(WayPointItem
*)));
217 m_map
->SetCurrentPosition(m_home_position
.coord
); // set the map position
218 m_map
->Home
->SetCoord(m_home_position
.coord
); // set the HOME position
219 m_map
->Nav
->SetCoord(m_home_position
.coord
); // set the NAV position
220 m_map
->UAV
->SetUAVPos(m_home_position
.coord
, 0.0); // set the UAV position
221 m_map
->UAV
->update();
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;
919 applyHomeLocationOnMap();
922 void OPMapGadgetWidget::onTelemetryDisconnect()
924 m_telemetry_connected
= false;
927 // Updates the Home position icon whenever the HomePosition object is updated
928 void OPMapGadgetWidget::homePositionUpdated(UAVObject
*hp
)
936 if (obum
->getHomeLocation(set
, LLA
) < 0) {
939 setHome(internals::PointLatLng(LLA
[0], LLA
[1]), LLA
[2]);
942 // *************************************************************************************
946 Sets the home position on the map widget
948 void OPMapGadgetWidget::setHome(QPointF pos
)
950 if (!m_widget
|| !m_map
) {
954 double latitude
= pos
.x();
955 double longitude
= pos
.y();
959 } else if (latitude
< -90) {
963 if (longitude
!= longitude
) {
964 longitude
= 0; // nan detection
965 } else if (longitude
> 180) {
967 } else if (longitude
< -180) {
971 setHome(internals::PointLatLng(latitude
, longitude
), 0);
975 Sets the home position on the map widget
977 void OPMapGadgetWidget::setHome(internals::PointLatLng pos_lat_lon
, double altitude
)
979 if (!m_widget
|| !m_map
) {
983 if (pos_lat_lon
.Lat() != pos_lat_lon
.Lat() || pos_lat_lon
.Lng() != pos_lat_lon
.Lng()) {
988 double latitude
= pos_lat_lon
.Lat();
989 double longitude
= pos_lat_lon
.Lng();
991 if (latitude
!= latitude
) {
992 latitude
= 0; // nan detection
993 } else if (latitude
> 90) {
995 } else if (latitude
< -90) {
999 if (longitude
!= longitude
) {
1000 longitude
= 0; // nan detection
1001 } else if (longitude
> 180) {
1003 } else if (longitude
< -180) {
1009 m_home_position
.coord
= internals::PointLatLng(latitude
, longitude
);
1010 m_home_position
.altitude
= altitude
;
1012 m_map
->Home
->SetCoord(m_home_position
.coord
);
1013 m_map
->Home
->SetAltitude(altitude
);
1014 m_map
->Home
->RefreshPos();
1016 // move the magic waypoint to keep it within the safe area boundry
1017 keepMagicWaypointWithinSafeArea();
1022 Centers the map over the home position
1024 void OPMapGadgetWidget::goHome()
1026 if (!m_widget
|| !m_map
) {
1030 followUAVpositionAct
->setChecked(false);
1032 internals::PointLatLng home_pos
= m_home_position
.coord
; // get the home location
1033 m_map
->SetCurrentPosition(home_pos
); // center the map onto the home location
1037 void OPMapGadgetWidget::zoomIn()
1039 if (!m_widget
|| !m_map
) {
1043 int zoom
= m_map
->ZoomTotal() + 1;
1045 if (zoom
< m_min_zoom
) {
1047 } else if (zoom
> m_max_zoom
) {
1051 m_map
->SetZoom(zoom
);
1054 void OPMapGadgetWidget::zoomOut()
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::setMaxUpdateRate(int update_rate
)
1073 if (!m_widget
|| !m_map
) {
1077 int list_size
= sizeof(max_update_rate_list
) / sizeof(max_update_rate_list
[0]);
1078 int min_rate
= max_update_rate_list
[0];
1079 int max_rate
= max_update_rate_list
[list_size
- 1];
1081 if (update_rate
< min_rate
) {
1082 update_rate
= min_rate
;
1083 } else if (update_rate
> max_rate
) {
1084 update_rate
= max_rate
;
1087 m_maxUpdateRate
= update_rate
;
1089 if (m_updateTimer
) {
1090 m_updateTimer
->setInterval(m_maxUpdateRate
);
1093 // if (m_statusUpdateTimer)
1094 // m_statusUpdateTimer->setInterval(m_maxUpdateRate);
1097 void OPMapGadgetWidget::setZoom(int zoom
)
1099 if (!m_widget
|| !m_map
) {
1103 if (zoom
< m_min_zoom
) {
1105 } else if (zoom
> m_max_zoom
) {
1109 internals::MouseWheelZoomType::Types zoom_type
= m_map
->GetMouseWheelZoomType();
1110 m_map
->SetMouseWheelZoomType(internals::MouseWheelZoomType::ViewCenter
);
1112 m_map
->SetZoom(zoom
);
1114 m_map
->SetMouseWheelZoomType(zoom_type
);
1116 void OPMapGadgetWidget::setOverlayOpacity(qreal value
)
1118 if (!m_widget
|| !m_map
) {
1121 m_map
->setOverlayOpacity(value
);
1122 overlayOpacityAct
.at(value
* 10)->setChecked(true);
1125 void OPMapGadgetWidget::setHomePosition(QPointF pos
)
1127 if (!m_widget
|| !m_map
) {
1131 double latitude
= pos
.y();
1132 double longitude
= pos
.x();
1134 if (latitude
!= latitude
|| longitude
!= longitude
) {
1135 return; // nan prevention
1137 if (latitude
> 90) {
1139 } else if (latitude
< -90) {
1143 if (longitude
> 180) {
1145 } else if (longitude
< -180) {
1149 m_map
->Home
->SetCoord(internals::PointLatLng(latitude
, longitude
));
1151 if (!m_telemetry_connected
) {
1152 m_home_position
.coord
= internals::PointLatLng(latitude
, longitude
);
1156 void OPMapGadgetWidget::setPosition(QPointF pos
)
1158 if (!m_widget
|| !m_map
) {
1162 double latitude
= pos
.y();
1163 double longitude
= pos
.x();
1165 if (latitude
!= latitude
|| longitude
!= longitude
) {
1166 return; // nan prevention
1168 if (latitude
> 90) {
1170 } else if (latitude
< -90) {
1174 if (longitude
> 180) {
1176 } else if (longitude
< -180) {
1180 m_map
->SetCurrentPosition(internals::PointLatLng(latitude
, longitude
));
1183 void OPMapGadgetWidget::setMapProvider(QString provider
)
1185 if (!m_widget
|| !m_map
) {
1189 m_map
->SetMapType(mapcontrol::Helper::MapTypeFromString(provider
));
1192 void OPMapGadgetWidget::setAccessMode(QString accessMode
)
1194 if (!m_widget
|| !m_map
) {
1198 m_map
->configuration
->SetAccessMode(mapcontrol::Helper::AccessModeFromString(accessMode
));
1201 void OPMapGadgetWidget::setUseOpenGL(bool useOpenGL
)
1203 if (!m_widget
|| !m_map
) {
1207 m_map
->SetUseOpenGL(useOpenGL
);
1210 void OPMapGadgetWidget::setShowTileGridLines(bool showTileGridLines
)
1212 if (!m_widget
|| !m_map
) {
1216 m_map
->SetShowTileGridLines(showTileGridLines
);
1219 void OPMapGadgetWidget::setUseMemoryCache(bool useMemoryCache
)
1221 if (!m_widget
|| !m_map
) {
1225 m_map
->configuration
->SetUseMemoryCache(useMemoryCache
);
1228 void OPMapGadgetWidget::setCacheLocation(QString cacheLocation
)
1230 if (!m_widget
|| !m_map
) {
1234 cacheLocation
= cacheLocation
.simplified(); // remove any surrounding spaces
1236 if (cacheLocation
.isEmpty()) {
1240 if (!cacheLocation
.endsWith(QDir::separator())) {
1241 cacheLocation
+= QDir::separator();
1245 if (!dir
.exists(cacheLocation
)) {
1246 if (!dir
.mkpath(cacheLocation
)) {
1250 m_map
->configuration
->SetCacheLocation(cacheLocation
);
1253 void OPMapGadgetWidget::setMapMode(opMapModeType mode
)
1255 if (!m_widget
|| !m_map
) {
1259 if (mode
!= Normal_MapMode
&& mode
!= MagicWaypoint_MapMode
) {
1260 mode
= Normal_MapMode
; // fix error
1262 if (m_map_mode
== mode
) { // no change in map mode
1263 switch (mode
) { // make sure the UI buttons are set correctly
1264 case Normal_MapMode
:
1265 m_widget
->toolButtonMagicWaypointMapMode
->setChecked(false);
1266 m_widget
->toolButtonNormalMapMode
->setChecked(true);
1268 case MagicWaypoint_MapMode
:
1269 m_widget
->toolButtonNormalMapMode
->setChecked(false);
1270 m_widget
->toolButtonMagicWaypointMapMode
->setChecked(true);
1277 case Normal_MapMode
:
1278 m_map_mode
= Normal_MapMode
;
1280 m_widget
->toolButtonMagicWaypointMapMode
->setChecked(false);
1281 m_widget
->toolButtonNormalMapMode
->setChecked(true);
1283 hideMagicWaypointControls();
1285 magicWayPoint
->setVisible(false);
1286 m_map
->WPSetVisibleAll(true);
1290 case MagicWaypoint_MapMode
:
1291 m_map_mode
= MagicWaypoint_MapMode
;
1293 m_widget
->toolButtonNormalMapMode
->setChecked(false);
1294 m_widget
->toolButtonMagicWaypointMapMode
->setChecked(true);
1296 showMagicWaypointControls();
1298 // delete the normal waypoints from the map
1300 m_map
->WPSetVisibleAll(false);
1301 magicWayPoint
->setVisible(true);
1307 // *************************************************************************************
1308 // Context menu stuff
1310 void OPMapGadgetWidget::createActions()
1314 if (!m_widget
|| !m_map
) {
1318 // ***********************
1319 // create menu actions
1321 reloadAct
= new QAction(tr("&Reload map"), this);
1322 reloadAct
->setShortcut(tr("F5"));
1323 reloadAct
->setStatusTip(tr("Reload the map tiles"));
1324 connect(reloadAct
, SIGNAL(triggered()), this, SLOT(onReloadAct_triggered()));
1325 this->addAction(reloadAct
);
1326 ripAct
= new QAction(tr("&Rip map"), this);
1327 ripAct
->setStatusTip(tr("Rip the map tiles"));
1328 connect(ripAct
, SIGNAL(triggered()), this, SLOT(onRipAct_triggered()));
1330 copyMouseLatLonToClipAct
= new QAction(tr("Mouse latitude and longitude"), this);
1331 copyMouseLatLonToClipAct
->setStatusTip(tr("Copy the mouse latitude and longitude to the clipboard"));
1332 connect(copyMouseLatLonToClipAct
, SIGNAL(triggered()), this, SLOT(onCopyMouseLatLonToClipAct_triggered()));
1334 copyMouseLatToClipAct
= new QAction(tr("Mouse latitude"), this);
1335 copyMouseLatToClipAct
->setStatusTip(tr("Copy the mouse latitude to the clipboard"));
1336 connect(copyMouseLatToClipAct
, SIGNAL(triggered()), this, SLOT(onCopyMouseLatToClipAct_triggered()));
1338 copyMouseLonToClipAct
= new QAction(tr("Mouse longitude"), this);
1339 copyMouseLonToClipAct
->setStatusTip(tr("Copy the mouse longitude to the clipboard"));
1340 connect(copyMouseLonToClipAct
, SIGNAL(triggered()), this, SLOT(onCopyMouseLonToClipAct_triggered()));
1342 showCompassAct
= new QAction(tr("Show compass"), this);
1343 showCompassAct
->setStatusTip(tr("Show/Hide the compass"));
1344 showCompassAct
->setCheckable(true);
1345 showCompassAct
->setChecked(true);
1346 connect(showCompassAct
, SIGNAL(toggled(bool)), this, SLOT(onShowCompassAct_toggled(bool)));
1348 showDiagnostics
= new QAction(tr("Show Diagnostics"), this);
1349 showDiagnostics
->setStatusTip(tr("Show/Hide the diagnostics"));
1350 showDiagnostics
->setCheckable(true);
1351 showDiagnostics
->setChecked(false);
1352 connect(showDiagnostics
, SIGNAL(toggled(bool)), this, SLOT(onShowDiagnostics_toggled(bool)));
1354 showNav
= new QAction(tr("Show Nav"), this);
1355 showNav
->setStatusTip(tr("Show/Hide pathfollower info"));
1356 showNav
->setCheckable(true);
1357 showNav
->setChecked(false);
1358 connect(showNav
, SIGNAL(toggled(bool)), this, SLOT(onShowNav_toggled(bool)));
1360 showUAVInfo
= new QAction(tr("Show UAV Info"), this);
1361 showUAVInfo
->setStatusTip(tr("Show/Hide the UAV info"));
1362 showUAVInfo
->setCheckable(true);
1363 showUAVInfo
->setChecked(false);
1364 connect(showUAVInfo
, SIGNAL(toggled(bool)), this, SLOT(onShowUAVInfo_toggled(bool)));
1366 showHomeAct
= new QAction(tr("Show Home"), this);
1367 showHomeAct
->setStatusTip(tr("Show/Hide the Home location"));
1368 showHomeAct
->setCheckable(true);
1369 showHomeAct
->setChecked(true);
1370 connect(showHomeAct
, SIGNAL(toggled(bool)), this, SLOT(onShowHomeAct_toggled(bool)));
1372 showUAVAct
= new QAction(tr("Show UAV"), this);
1373 showUAVAct
->setStatusTip(tr("Show/Hide the UAV"));
1374 showUAVAct
->setCheckable(true);
1375 showUAVAct
->setChecked(true);
1376 connect(showUAVAct
, SIGNAL(toggled(bool)), this, SLOT(onShowUAVAct_toggled(bool)));
1378 changeDefaultLocalAndZoom
= new QAction(tr("Set default zoom and location"), this);
1379 changeDefaultLocalAndZoom
->setStatusTip(tr("Changes the map default zoom and location to the current values"));
1380 connect(changeDefaultLocalAndZoom
, SIGNAL(triggered()), this, SLOT(onChangeDefaultLocalAndZoom()));
1382 zoomInAct
= new QAction(tr("Zoom &In"), this);
1383 zoomInAct
->setShortcut(Qt::Key_PageUp
);
1384 zoomInAct
->setStatusTip(tr("Zoom the map in"));
1385 connect(zoomInAct
, SIGNAL(triggered()), this, SLOT(onGoZoomInAct_triggered()));
1386 this->addAction(zoomInAct
);
1388 zoomOutAct
= new QAction(tr("Zoom &Out"), this);
1389 zoomOutAct
->setShortcut(Qt::Key_PageDown
);
1390 zoomOutAct
->setStatusTip(tr("Zoom the map out"));
1391 connect(zoomOutAct
, SIGNAL(triggered()), this, SLOT(onGoZoomOutAct_triggered()));
1392 this->addAction(zoomOutAct
);
1394 goMouseClickAct
= new QAction(tr("Go to where you right clicked the mouse"), this);
1395 goMouseClickAct
->setStatusTip(tr("Center the map onto where you right clicked the mouse"));
1396 connect(goMouseClickAct
, SIGNAL(triggered()), this, SLOT(onGoMouseClickAct_triggered()));
1398 setHomeAct
= new QAction(tr("Set the home location"), this);
1399 setHomeAct
->setStatusTip(tr("Set the home location to where you clicked"));
1400 #if !defined(allow_manual_home_location_move)
1401 setHomeAct
->setEnabled(false);
1403 connect(setHomeAct
, SIGNAL(triggered()), this, SLOT(onSetHomeAct_triggered()));
1405 goHomeAct
= new QAction(tr("Go to &Home location"), this);
1406 goHomeAct
->setShortcut(tr("Ctrl+H"));
1407 goHomeAct
->setStatusTip(tr("Center the map onto the home location"));
1408 connect(goHomeAct
, SIGNAL(triggered()), this, SLOT(onGoHomeAct_triggered()));
1410 goUAVAct
= new QAction(tr("Go to &UAV location"), this);
1411 goUAVAct
->setShortcut(tr("Ctrl+U"));
1412 goUAVAct
->setStatusTip(tr("Center the map onto the UAV location"));
1413 connect(goUAVAct
, SIGNAL(triggered()), this, SLOT(onGoUAVAct_triggered()));
1415 followUAVpositionAct
= new QAction(tr("Follow UAV position"), this);
1416 followUAVpositionAct
->setShortcut(tr("Ctrl+F"));
1417 followUAVpositionAct
->setStatusTip(tr("Keep the map centered onto the UAV"));
1418 followUAVpositionAct
->setCheckable(true);
1419 followUAVpositionAct
->setChecked(false);
1420 connect(followUAVpositionAct
, SIGNAL(toggled(bool)), this, SLOT(onFollowUAVpositionAct_toggled(bool)));
1422 followUAVheadingAct
= new QAction(tr("Follow UAV heading"), this);
1423 followUAVheadingAct
->setShortcut(tr("Ctrl+F"));
1424 followUAVheadingAct
->setStatusTip(tr("Keep the map rotation to the UAV heading"));
1425 followUAVheadingAct
->setCheckable(true);
1426 followUAVheadingAct
->setChecked(false);
1427 connect(followUAVheadingAct
, SIGNAL(toggled(bool)), this, SLOT(onFollowUAVheadingAct_toggled(bool)));
1430 TODO: Waypoint support is disabled for v1.0
1433 #ifdef USE_PATHPLANNER
1434 wayPointEditorAct
= new QAction(tr("&Waypoint editor"), this);
1435 wayPointEditorAct
->setShortcut(tr("Ctrl+W"));
1436 wayPointEditorAct
->setStatusTip(tr("Open the waypoint editor"));
1437 connect(wayPointEditorAct
, SIGNAL(triggered()), this, SLOT(onOpenWayPointEditorAct_triggered()));
1439 addWayPointActFromContextMenu
= new QAction(tr("&Add waypoint"), this);
1440 addWayPointActFromContextMenu
->setShortcut(tr("Ctrl+A"));
1441 addWayPointActFromContextMenu
->setStatusTip(tr("Add waypoint"));
1442 connect(addWayPointActFromContextMenu
, SIGNAL(triggered()), this, SLOT(onAddWayPointAct_triggeredFromContextMenu()));
1444 addWayPointActFromThis
= new QAction(tr("&Add waypoint"), this);
1445 addWayPointActFromThis
->setShortcut(tr("Ctrl+A"));
1446 addWayPointActFromThis
->setStatusTip(tr("Add waypoint"));
1447 connect(addWayPointActFromThis
, SIGNAL(triggered()), this, SLOT(onAddWayPointAct_triggeredFromThis()));
1448 this->addAction(addWayPointActFromThis
);
1450 editWayPointAct
= new QAction(tr("&Edit waypoint"), this);
1451 editWayPointAct
->setShortcut(tr("Ctrl+E"));
1452 editWayPointAct
->setStatusTip(tr("Edit waypoint"));
1453 connect(editWayPointAct
, SIGNAL(triggered()), this, SLOT(onEditWayPointAct_triggered()));
1455 lockWayPointAct
= new QAction(tr("&Lock waypoint"), this);
1456 lockWayPointAct
->setStatusTip(tr("Lock/Unlock a waypoint"));
1457 lockWayPointAct
->setCheckable(true);
1458 lockWayPointAct
->setChecked(false);
1459 connect(lockWayPointAct
, SIGNAL(triggered()), this, SLOT(onLockWayPointAct_triggered()));
1461 deleteWayPointAct
= new QAction(tr("&Delete waypoint"), this);
1462 deleteWayPointAct
->setShortcut(tr("Ctrl+D"));
1463 deleteWayPointAct
->setStatusTip(tr("Delete waypoint"));
1464 connect(deleteWayPointAct
, SIGNAL(triggered()), this, SLOT(onDeleteWayPointAct_triggered()));
1466 clearWayPointsAct
= new QAction(tr("&Clear waypoints"), this);
1467 clearWayPointsAct
->setShortcut(tr("Ctrl+C"));
1468 clearWayPointsAct
->setStatusTip(tr("Clear waypoints"));
1469 connect(clearWayPointsAct
, SIGNAL(triggered()), this, SLOT(onClearWayPointsAct_triggered()));
1470 #endif // ifdef USE_PATHPLANNER
1471 overlayOpacityActGroup
= new QActionGroup(this);
1472 connect(overlayOpacityActGroup
, SIGNAL(triggered(QAction
*)), this, SLOT(onOverlayOpacityActGroup_triggered(QAction
*)));
1473 overlayOpacityAct
.clear();
1474 for (int i
= 0; i
<= 10; i
++) {
1475 QAction
*overlayAct
= new QAction(QString::number(i
* 10), overlayOpacityActGroup
);
1476 overlayAct
->setCheckable(true);
1477 overlayAct
->setData(i
* 10);
1478 overlayOpacityAct
.append(overlayAct
);
1481 homeMagicWaypointAct
= new QAction(tr("Home magic waypoint"), this);
1482 homeMagicWaypointAct
->setStatusTip(tr("Move the magic waypoint to the home position"));
1483 connect(homeMagicWaypointAct
, SIGNAL(triggered()), this, SLOT(onHomeMagicWaypointAct_triggered()));
1485 mapModeActGroup
= new QActionGroup(this);
1486 connect(mapModeActGroup
, SIGNAL(triggered(QAction
*)), this, SLOT(onMapModeActGroup_triggered(QAction
*)));
1489 QAction
*map_mode_act
;
1491 map_mode_act
= new QAction(tr("Normal"), mapModeActGroup
);
1492 map_mode_act
->setCheckable(true);
1493 map_mode_act
->setChecked(m_map_mode
== Normal_MapMode
);
1494 map_mode_act
->setData((int)Normal_MapMode
);
1495 mapModeAct
.append(map_mode_act
);
1497 map_mode_act
= new QAction(tr("Magic Waypoint"), mapModeActGroup
);
1498 map_mode_act
->setCheckable(true);
1499 map_mode_act
->setChecked(m_map_mode
== MagicWaypoint_MapMode
);
1500 map_mode_act
->setData((int)MagicWaypoint_MapMode
);
1501 mapModeAct
.append(map_mode_act
);
1504 zoomActGroup
= new QActionGroup(this);
1505 connect(zoomActGroup
, SIGNAL(triggered(QAction
*)), this, SLOT(onZoomActGroup_triggered(QAction
*)));
1507 for (int i
= m_min_zoom
; i
<= m_max_zoom
; i
++) {
1508 QAction
*zoom_act
= new QAction(QString::number(i
), zoomActGroup
);
1509 zoom_act
->setCheckable(true);
1510 zoom_act
->setData(i
);
1511 zoomAct
.append(zoom_act
);
1514 maxUpdateRateActGroup
= new QActionGroup(this);
1515 connect(maxUpdateRateActGroup
, SIGNAL(triggered(QAction
*)), this, SLOT(onMaxUpdateRateActGroup_triggered(QAction
*)));
1516 maxUpdateRateAct
.clear();
1517 list_size
= sizeof(max_update_rate_list
) / sizeof(max_update_rate_list
[0]);
1518 for (int i
= 0; i
< list_size
; i
++) {
1519 QAction
*maxUpdateRate_act
;
1520 int j
= max_update_rate_list
[i
];
1521 maxUpdateRate_act
= new QAction(QString::number(j
), maxUpdateRateActGroup
);
1522 maxUpdateRate_act
->setCheckable(true);
1523 maxUpdateRate_act
->setData(j
);
1524 maxUpdateRate_act
->setChecked(j
== m_maxUpdateRate
);
1525 maxUpdateRateAct
.append(maxUpdateRate_act
);
1531 showSafeAreaAct
= new QAction(tr("Show Safe Area"), this);
1532 showSafeAreaAct
->setStatusTip(tr("Show/Hide the Safe Area around the home location"));
1533 showSafeAreaAct
->setCheckable(true);
1534 showSafeAreaAct
->setChecked(m_map
->Home
->ShowSafeArea());
1535 connect(showSafeAreaAct
, SIGNAL(toggled(bool)), this, SLOT(onShowSafeAreaAct_toggled(bool)));
1537 safeAreaActGroup
= new QActionGroup(this);
1538 connect(safeAreaActGroup
, SIGNAL(triggered(QAction
*)), this, SLOT(onSafeAreaActGroup_triggered(QAction
*)));
1539 safeAreaAct
.clear();
1540 list_size
= sizeof(safe_area_radius_list
) / sizeof(safe_area_radius_list
[0]);
1541 for (int i
= 0; i
< list_size
; i
++) {
1542 int safeArea
= safe_area_radius_list
[i
];
1543 QAction
*safeArea_act
= new QAction(QString::number(safeArea
) + "m", safeAreaActGroup
);
1544 safeArea_act
->setCheckable(true);
1545 safeArea_act
->setChecked(safeArea
== m_map
->Home
->SafeArea());
1546 safeArea_act
->setData(safeArea
);
1547 safeAreaAct
.append(safeArea_act
);
1553 uavTrailTypeActGroup
= new QActionGroup(this);
1554 connect(uavTrailTypeActGroup
, SIGNAL(triggered(QAction
*)), this, SLOT(onUAVTrailTypeActGroup_triggered(QAction
*)));
1555 uavTrailTypeAct
.clear();
1556 QStringList uav_trail_type_list
= mapcontrol::Helper::UAVTrailTypes();
1557 for (int i
= 0; i
< uav_trail_type_list
.count(); i
++) {
1558 mapcontrol::UAVTrailType::Types uav_trail_type
= mapcontrol::Helper::UAVTrailTypeFromString(uav_trail_type_list
[i
]);
1559 QAction
*uavTrailType_act
= new QAction(mapcontrol::Helper::StrFromUAVTrailType(uav_trail_type
), uavTrailTypeActGroup
);
1560 uavTrailType_act
->setCheckable(true);
1561 uavTrailType_act
->setChecked(uav_trail_type
== m_map
->UAV
->GetTrailType());
1562 uavTrailType_act
->setData(i
);
1563 uavTrailTypeAct
.append(uavTrailType_act
);
1566 showTrailAct
= new QAction(tr("Show Trail dots"), this);
1567 showTrailAct
->setStatusTip(tr("Show/Hide the Trail dots"));
1568 showTrailAct
->setCheckable(true);
1569 showTrailAct
->setChecked(true);
1570 connect(showTrailAct
, SIGNAL(toggled(bool)), this, SLOT(onShowTrailAct_toggled(bool)));
1572 showTrailLineAct
= new QAction(tr("Show Trail lines"), this);
1573 showTrailLineAct
->setStatusTip(tr("Show/Hide the Trail lines"));
1574 showTrailLineAct
->setCheckable(true);
1575 showTrailLineAct
->setChecked(true);
1576 connect(showTrailLineAct
, SIGNAL(toggled(bool)), this, SLOT(onShowTrailLineAct_toggled(bool)));
1578 clearUAVtrailAct
= new QAction(tr("Clear UAV trail"), this);
1579 clearUAVtrailAct
->setStatusTip(tr("Clear the UAV trail"));
1580 connect(clearUAVtrailAct
, SIGNAL(triggered()), this, SLOT(onClearUAVtrailAct_triggered()));
1582 uavTrailTimeActGroup
= new QActionGroup(this);
1583 connect(uavTrailTimeActGroup
, SIGNAL(triggered(QAction
*)), this, SLOT(onUAVTrailTimeActGroup_triggered(QAction
*)));
1584 uavTrailTimeAct
.clear();
1585 list_size
= sizeof(uav_trail_time_list
) / sizeof(uav_trail_time_list
[0]);
1586 for (int i
= 0; i
< list_size
; i
++) {
1587 int uav_trail_time
= uav_trail_time_list
[i
];
1588 QAction
*uavTrailTime_act
= new QAction(QString::number(uav_trail_time
) + " sec", uavTrailTimeActGroup
);
1589 uavTrailTime_act
->setCheckable(true);
1590 uavTrailTime_act
->setChecked(uav_trail_time
== m_map
->UAV
->TrailTime());
1591 uavTrailTime_act
->setData(uav_trail_time
);
1592 uavTrailTimeAct
.append(uavTrailTime_act
);
1595 uavTrailDistanceActGroup
= new QActionGroup(this);
1596 connect(uavTrailDistanceActGroup
, SIGNAL(triggered(QAction
*)), this, SLOT(onUAVTrailDistanceActGroup_triggered(QAction
*)));
1597 uavTrailDistanceAct
.clear();
1598 list_size
= sizeof(uav_trail_distance_list
) / sizeof(uav_trail_distance_list
[0]);
1599 for (int i
= 0; i
< list_size
; i
++) {
1600 int uav_trail_distance
= uav_trail_distance_list
[i
];
1601 QAction
*uavTrailDistance_act
= new QAction(QString::number(uav_trail_distance
) + " meters", uavTrailDistanceActGroup
);
1602 uavTrailDistance_act
->setCheckable(true);
1603 uavTrailDistance_act
->setChecked(uav_trail_distance
== m_map
->UAV
->TrailDistance());
1604 uavTrailDistance_act
->setData(uav_trail_distance
);
1605 uavTrailDistanceAct
.append(uavTrailDistance_act
);
1609 void OPMapGadgetWidget::onReloadAct_triggered()
1611 if (!m_widget
|| !m_map
) {
1618 void OPMapGadgetWidget::onRipAct_triggered()
1623 void OPMapGadgetWidget::onCopyMouseLatLonToClipAct_triggered()
1625 QClipboard
*clipboard
= QApplication::clipboard();
1627 clipboard
->setText(QString::number(m_context_menu_lat_lon
.Lat(), 'f', 7) + ", " + QString::number(m_context_menu_lat_lon
.Lng(), 'f', 7), QClipboard::Clipboard
);
1630 void OPMapGadgetWidget::onCopyMouseLatToClipAct_triggered()
1632 QClipboard
*clipboard
= QApplication::clipboard();
1634 clipboard
->setText(QString::number(m_context_menu_lat_lon
.Lat(), 'f', 7), QClipboard::Clipboard
);
1637 void OPMapGadgetWidget::onCopyMouseLonToClipAct_triggered()
1639 QClipboard
*clipboard
= QApplication::clipboard();
1641 clipboard
->setText(QString::number(m_context_menu_lat_lon
.Lng(), 'f', 7), QClipboard::Clipboard
);
1645 void OPMapGadgetWidget::onShowCompassAct_toggled(bool show
)
1647 if (!m_widget
|| !m_map
) {
1651 m_map
->SetShowCompass(show
);
1654 void OPMapGadgetWidget::onShowDiagnostics_toggled(bool show
)
1656 if (!m_widget
|| !m_map
) {
1660 m_map
->SetShowDiagnostics(show
);
1663 void OPMapGadgetWidget::onShowNav_toggled(bool show
)
1665 if (!m_widget
|| !m_map
) {
1669 m_map
->SetShowNav(show
);
1672 void OPMapGadgetWidget::onShowUAVInfo_toggled(bool show
)
1674 if (!m_widget
|| !m_map
) {
1678 m_map
->UAV
->SetShowUAVInfo(show
);
1681 void OPMapGadgetWidget::onShowHomeAct_toggled(bool show
)
1683 if (!m_widget
|| !m_map
) {
1687 m_map
->Home
->setVisible(show
);
1690 void OPMapGadgetWidget::onShowUAVAct_toggled(bool show
)
1692 if (!m_widget
|| !m_map
) {
1696 m_map
->UAV
->setVisible(show
);
1698 m_map
->GPS
->setVisible(show
);
1702 void OPMapGadgetWidget::onShowTrailAct_toggled(bool show
)
1704 if (!m_widget
|| !m_map
) {
1708 m_map
->UAV
->SetShowTrail(show
);
1710 m_map
->GPS
->SetShowTrail(show
);
1714 void OPMapGadgetWidget::onShowTrailLineAct_toggled(bool show
)
1716 if (!m_widget
|| !m_map
) {
1720 m_map
->UAV
->SetShowTrailLine(show
);
1722 m_map
->GPS
->SetShowTrailLine(show
);
1726 void OPMapGadgetWidget::onMapModeActGroup_triggered(QAction
*action
)
1728 if (!m_widget
|| !m_map
|| !action
) {
1732 opMapModeType mode
= (opMapModeType
)action
->data().toInt();
1737 void OPMapGadgetWidget::onGoZoomInAct_triggered()
1742 void OPMapGadgetWidget::onGoZoomOutAct_triggered()
1747 void OPMapGadgetWidget::onZoomActGroup_triggered(QAction
*action
)
1749 if (!m_widget
|| !m_map
|| !action
) {
1753 setZoom(action
->data().toInt());
1756 void OPMapGadgetWidget::onMaxUpdateRateActGroup_triggered(QAction
*action
)
1758 if (!m_widget
|| !m_map
|| !action
) {
1762 setMaxUpdateRate(action
->data().toInt());
1765 void OPMapGadgetWidget::onChangeDefaultLocalAndZoom()
1767 emit
defaultLocationAndZoomChanged(m_map
->CurrentPosition().Lng(), m_map
->CurrentPosition().Lat(), m_map
->ZoomTotal());
1770 void OPMapGadgetWidget::onGoMouseClickAct_triggered()
1772 if (!m_widget
|| !m_map
) {
1776 m_map
->SetCurrentPosition(m_map
->currentMousePosition()); // center the map onto the mouse position
1779 void OPMapGadgetWidget::onSetHomeAct_triggered()
1781 if (!m_widget
|| !m_map
) {
1788 // Get desired HomeLocation altitude from dialog box.
1789 // TODO: Populate box with altitude already in HomeLocation UAVO
1790 altitude
= QInputDialog::getDouble(this, tr("Set home altitude"),
1791 tr("In [m], referenced to WGS84:"), altitude
, -100, 100000, 2, &ok
);
1794 setHome(m_context_menu_lat_lon
, altitude
);
1795 setHomeLocationObject(); // update the HomeLocation UAVObject
1799 void OPMapGadgetWidget::onGoHomeAct_triggered()
1801 if (!m_widget
|| !m_map
) {
1808 void OPMapGadgetWidget::onGoUAVAct_triggered()
1810 if (!m_widget
|| !m_map
) {
1817 if (getUAVPosition(latitude
, longitude
, altitude
)) { // get current UAV position
1818 internals::PointLatLng uav_pos
= internals::PointLatLng(latitude
, longitude
); // current UAV position
1819 internals::PointLatLng map_pos
= m_map
->CurrentPosition(); // current MAP position
1820 if (map_pos
!= uav_pos
) {
1821 m_map
->SetCurrentPosition(uav_pos
); // center the map onto the UAV
1826 void OPMapGadgetWidget::onFollowUAVpositionAct_toggled(bool checked
)
1828 if (!m_widget
|| !m_map
) {
1832 if (m_widget
->toolButtonMapUAV
->isChecked() != checked
) {
1833 m_widget
->toolButtonMapUAV
->setChecked(checked
);
1836 setMapFollowingMode();
1839 void OPMapGadgetWidget::onFollowUAVheadingAct_toggled(bool checked
)
1841 if (!m_widget
|| !m_map
) {
1845 if (m_widget
->toolButtonMapUAVheading
->isChecked() != checked
) {
1846 m_widget
->toolButtonMapUAVheading
->setChecked(checked
);
1849 setMapFollowingMode();
1852 void OPMapGadgetWidget::onUAVTrailTypeActGroup_triggered(QAction
*action
)
1854 if (!m_widget
|| !m_map
|| !action
) {
1858 int trail_type_idx
= action
->data().toInt();
1860 QStringList uav_trail_type_list
= mapcontrol::Helper::UAVTrailTypes();
1861 mapcontrol::UAVTrailType::Types uav_trail_type
= mapcontrol::Helper::UAVTrailTypeFromString(uav_trail_type_list
[trail_type_idx
]);
1863 m_map
->UAV
->SetTrailType(uav_trail_type
);
1866 void OPMapGadgetWidget::onClearUAVtrailAct_triggered()
1868 if (!m_widget
|| !m_map
) {
1872 m_map
->UAV
->DeleteTrail();
1874 m_map
->GPS
->DeleteTrail();
1878 void OPMapGadgetWidget::onUAVTrailTimeActGroup_triggered(QAction
*action
)
1880 if (!m_widget
|| !m_map
|| !action
) {
1884 int trail_time
= (double)action
->data().toInt();
1886 m_map
->UAV
->SetTrailTime(trail_time
);
1889 void OPMapGadgetWidget::onUAVTrailDistanceActGroup_triggered(QAction
*action
)
1891 if (!m_widget
|| !m_map
|| !action
) {
1895 int trail_distance
= action
->data().toInt();
1897 m_map
->UAV
->SetTrailDistance(trail_distance
);
1900 void OPMapGadgetWidget::onOpenWayPointEditorAct_triggered()
1904 // bring dialog to the front in case it was already open and hidden away
1908 void OPMapGadgetWidget::onAddWayPointAct_triggeredFromContextMenu()
1910 onAddWayPointAct_triggered(m_context_menu_lat_lon
);
1912 void OPMapGadgetWidget::onAddWayPointAct_triggeredFromThis()
1914 onAddWayPointAct_triggered(lastLatLngMouse
);
1917 void OPMapGadgetWidget::onAddWayPointAct_triggered(internals::PointLatLng coord
)
1919 if (!m_widget
|| !m_map
) {
1923 if (m_map_mode
!= Normal_MapMode
) {
1927 mapProxy
->createWayPoint(coord
);
1932 * Called when the user asks to edit a waypoint from the map
1934 * TODO: should open an interface to edit waypoint properties, or
1935 * propagate the signal to a specific WP plugin (tbd).
1938 void OPMapGadgetWidget::onEditWayPointAct_triggered()
1940 if (!m_widget
|| !m_map
) {
1944 if (m_map_mode
!= Normal_MapMode
) {
1948 if (!m_mouse_waypoint
) {
1952 waypoint_edit_dialog
->editWaypoint(m_mouse_waypoint
);
1953 m_mouse_waypoint
= NULL
;
1958 * TODO: unused for v1.0
1961 void OPMapGadgetWidget::onLockWayPointAct_triggered()
1963 if (!m_widget
|| !m_map
|| !m_mouse_waypoint
) {
1967 if (m_map_mode
!= Normal_MapMode
) {
1971 bool locked
= (m_mouse_waypoint
->flags() & QGraphicsItem::ItemIsMovable
) == 0;
1972 m_mouse_waypoint
->setFlag(QGraphicsItem::ItemIsMovable
, locked
);
1975 m_mouse_waypoint
->picture
.load(":/markers/images/wp_marker_orange.png");
1977 m_mouse_waypoint
->picture
.load(":/markers/images/wp_marker_red.png");
1979 m_mouse_waypoint
->update();
1981 m_mouse_waypoint
= NULL
;
1984 void OPMapGadgetWidget::onDeleteWayPointAct_triggered()
1986 if (!m_widget
|| !m_map
) {
1990 if (m_map_mode
!= Normal_MapMode
) {
1994 if (!m_mouse_waypoint
) {
1998 mapProxy
->deleteWayPoint(m_mouse_waypoint
->Number());
2001 void OPMapGadgetWidget::onClearWayPointsAct_triggered()
2003 // First, ask to ensure this is what the user wants to do
2006 msgBox
.setText(tr("Are you sure you want to clear waypoints?"));
2007 msgBox
.setInformativeText(tr("All associated data will be lost."));
2008 msgBox
.setStandardButtons(QMessageBox::Yes
| QMessageBox::No
);
2009 int ret
= msgBox
.exec();
2011 if (ret
== QMessageBox::No
) {
2015 if (!m_widget
|| !m_map
) {
2019 if (m_map_mode
!= Normal_MapMode
) {
2023 mapProxy
->deleteAll();
2027 void OPMapGadgetWidget::onHomeMagicWaypointAct_triggered()
2029 // center the magic waypoint on the home position
2030 homeMagicWaypoint();
2033 void OPMapGadgetWidget::onShowSafeAreaAct_toggled(bool show
)
2035 if (!m_widget
|| !m_map
) {
2039 m_map
->Home
->SetShowSafeArea(show
); // show the safe area
2040 m_map
->Home
->SetToggleRefresh(true);
2041 m_map
->Home
->RefreshPos();
2044 void OPMapGadgetWidget::onSafeAreaActGroup_triggered(QAction
*action
)
2046 if (!m_widget
|| !m_map
|| !action
) {
2050 int radius
= action
->data().toInt();
2052 m_map
->Home
->SetSafeArea(radius
); // set the radius (meters)
2053 m_map
->Home
->RefreshPos();
2055 // move the magic waypoint if need be to keep it within the safe area around the home position
2056 keepMagicWaypointWithinSafeArea();
2060 * move the magic waypoint to the home position
2062 void OPMapGadgetWidget::homeMagicWaypoint()
2064 if (!m_widget
|| !m_map
) {
2068 if (m_map_mode
!= MagicWaypoint_MapMode
) {
2072 magicWayPoint
->SetCoord(m_home_position
.coord
);
2075 // *************************************************************************************
2076 // move the UAV to the magic waypoint position
2078 void OPMapGadgetWidget::moveToMagicWaypointPosition()
2080 if (!m_widget
|| !m_map
) {
2084 if (m_map_mode
!= MagicWaypoint_MapMode
) {
2088 magicWayPoint
->SetCoord(magicWayPoint
->Coord());
2089 keepMagicWaypointWithinSafeArea();
2092 // *************************************************************************************
2093 // show/hide the magic waypoint controls
2095 void OPMapGadgetWidget::hideMagicWaypointControls()
2097 m_widget
->lineWaypoint
->setVisible(false);
2098 m_widget
->toolButtonHomeWaypoint
->setVisible(false);
2099 m_widget
->toolButtonMoveToWP
->setVisible(false);
2102 void OPMapGadgetWidget::showMagicWaypointControls()
2104 m_widget
->lineWaypoint
->setVisible(true);
2105 m_widget
->toolButtonHomeWaypoint
->setVisible(true);
2107 #if defined(allow_manual_home_location_move)
2108 m_widget
->toolButtonMoveToWP
->setVisible(true);
2110 m_widget
->toolButtonMoveToWP
->setVisible(false);
2114 // *************************************************************************************
2115 // move the magic waypoint to keep it within the safe area boundry
2117 void OPMapGadgetWidget::keepMagicWaypointWithinSafeArea()
2119 bool moveMagicWP
= false;
2120 // calcute the bearing and distance from the home position to the magic waypoint
2121 double dist
= distance(m_home_position
.coord
, magicWayPoint
->Coord());
2122 double bear
= bearing(m_home_position
.coord
, magicWayPoint
->Coord());
2124 // get the maximum safe distance - in kilometers
2125 double boundry_dist
= (double)m_map
->Home
->SafeArea() / 1000;
2127 if (dist
> boundry_dist
) {
2128 dist
= boundry_dist
;
2132 // move the magic waypoint;
2133 if ((m_map_mode
== MagicWaypoint_MapMode
) && moveMagicWP
) { // if needed, move the on-screen waypoint to the safe area
2134 if (magicWayPoint
) {
2135 magicWayPoint
->SetCoord(destPoint(m_home_position
.coord
, bear
, dist
));
2140 // *************************************************************************************
2141 // return the distance between two points .. in kilometers
2143 double OPMapGadgetWidget::distance(internals::PointLatLng from
, internals::PointLatLng to
)
2145 double lat1
= from
.Lat() * deg_to_rad
;
2146 double lon1
= from
.Lng() * deg_to_rad
;
2148 double lat2
= to
.Lat() * deg_to_rad
;
2149 double lon2
= to
.Lng() * deg_to_rad
;
2151 return acos(sin(lat1
) * sin(lat2
) + cos(lat1
) * cos(lat2
) * cos(lon2
- lon1
)) * earth_mean_radius
;
2153 // ***********************
2156 // *************************************************************************************
2157 // return the bearing from one point to another .. in degrees
2159 double OPMapGadgetWidget::bearing(internals::PointLatLng from
, internals::PointLatLng to
)
2161 double lat1
= from
.Lat() * deg_to_rad
;
2162 double lon1
= from
.Lng() * deg_to_rad
;
2164 double lat2
= to
.Lat() * deg_to_rad
;
2165 double lon2
= to
.Lng() * deg_to_rad
;
2167 // double delta_lat = lat2 - lat1;
2168 double delta_lon
= lon2
- lon1
;
2170 double y
= sin(delta_lon
) * cos(lat2
);
2171 double x
= cos(lat1
) * sin(lat2
) - sin(lat1
) * cos(lat2
) * cos(delta_lon
);
2172 double bear
= atan2(y
, x
) * rad_to_deg
;
2178 while (bear
>= 360) {
2185 // *************************************************************************************
2186 // return a destination lat/lon point given a source lat/lon point and the bearing and distance from the source point
2188 internals::PointLatLng
OPMapGadgetWidget::destPoint(internals::PointLatLng source
, double bear
, double dist
)
2190 double lat1
= source
.Lat() * deg_to_rad
;
2191 double lon1
= source
.Lng() * deg_to_rad
;
2195 double ad
= dist
/ earth_mean_radius
;
2197 double lat2
= asin(sin(lat1
) * cos(ad
) + cos(lat1
) * sin(ad
) * cos(bear
));
2198 double lon2
= lon1
+ atan2(sin(bear
) * sin(ad
) * cos(lat1
), cos(ad
) - sin(lat1
) * sin(lat2
));
2200 return internals::PointLatLng(lat2
* rad_to_deg
, lon2
* rad_to_deg
);
2203 // *************************************************************************************
2205 bool OPMapGadgetWidget::getUAVPosition(double &latitude
, double &longitude
, double &altitude
)
2211 Q_ASSERT(obm
!= NULL
);
2213 PositionState
*positionState
= PositionState::GetInstance(obm
);
2214 Q_ASSERT(positionState
!= NULL
);
2215 PositionState::DataFields positionStateData
= positionState
->getData();
2216 if (positionStateData
.North
== 0 && positionStateData
.East
== 0 && positionStateData
.Down
== 0) {
2217 GPSPositionSensor
*gpsPositionObj
= GPSPositionSensor::GetInstance(obm
);
2218 Q_ASSERT(gpsPositionObj
);
2220 GPSPositionSensor::DataFields gpsPositionData
= gpsPositionObj
->getData();
2221 latitude
= gpsPositionData
.Latitude
/ 1.0e7
;
2222 longitude
= gpsPositionData
.Longitude
/ 1.0e7
;
2223 altitude
= gpsPositionData
.Altitude
;
2226 HomeLocation
*homeLocation
= HomeLocation::GetInstance(obm
);
2227 Q_ASSERT(homeLocation
!= NULL
);
2228 HomeLocation::DataFields homeLocationData
= homeLocation
->getData();
2230 homeLLA
[0] = homeLocationData
.Latitude
/ 1.0e7
;
2231 homeLLA
[1] = homeLocationData
.Longitude
/ 1.0e7
;
2232 homeLLA
[2] = homeLocationData
.Altitude
;
2234 NED
[0] = positionStateData
.North
;
2235 NED
[1] = positionStateData
.East
;
2236 NED
[2] = positionStateData
.Down
;
2238 Utils::CoordinateConversions().NED2LLA_HomeLLA(homeLLA
, NED
, LLA
);
2244 if (latitude
!= latitude
) {
2245 latitude
= 0; // nan detection
2246 } else if (latitude
> 90) {
2248 } else if (latitude
< -90) {
2252 if (longitude
!= longitude
) {
2253 longitude
= 0; // nan detection
2254 } else if (longitude
> 180) {
2256 } else if (longitude
< -180) {
2260 if (altitude
!= altitude
) {
2261 altitude
= 0; // nan detection
2266 bool OPMapGadgetWidget::getNavPosition(double &latitude
, double &longitude
, double &altitude
)
2272 Q_ASSERT(obm
!= NULL
);
2274 PathDesired
*pathDesired
= PathDesired::GetInstance(obm
);
2275 Q_ASSERT(pathDesired
!= NULL
);
2276 PathDesired::DataFields pathDesiredData
= pathDesired
->getData();
2277 HomeLocation
*homeLocation
= HomeLocation::GetInstance(obm
);
2278 Q_ASSERT(homeLocation
!= NULL
);
2279 HomeLocation::DataFields homeLocationData
= homeLocation
->getData();
2281 homeLLA
[0] = homeLocationData
.Latitude
/ 1.0e7
;
2282 homeLLA
[1] = homeLocationData
.Longitude
/ 1.0e7
;
2283 homeLLA
[2] = homeLocationData
.Altitude
;
2285 NED
[0] = pathDesiredData
.End
[0];
2286 NED
[1] = pathDesiredData
.End
[1];
2287 NED
[2] = pathDesiredData
.End
[2];
2289 Utils::CoordinateConversions().NED2LLA_HomeLLA(homeLLA
, NED
, LLA
);
2295 if (latitude
!= latitude
) {
2296 latitude
= 0; // nan detection
2297 } else if (latitude
> 90) {
2299 } else if (latitude
< -90) {
2303 if (longitude
!= longitude
) {
2304 longitude
= 0; // nan detection
2305 } else if (longitude
> 180) {
2307 } else if (longitude
< -180) {
2311 if (altitude
!= altitude
) {
2312 altitude
= 0; // nan detection
2317 double OPMapGadgetWidget::getUAV_Yaw()
2323 UAVObject
*obj
= dynamic_cast<UAVDataObject
*>(obm
->getObject(QString("AttitudeState")));
2324 double yaw
= obj
->getField(QString("Yaw"))->getDouble();
2327 yaw
= 0; // nan detection
2332 while (yaw
>= 360) {
2339 bool OPMapGadgetWidget::getGPSPositionSensor(double &latitude
, double &longitude
, double &altitude
)
2347 if (obum
->getGPSPositionSensor(LLA
) < 0) {
2348 return false; // error
2357 bool OPMapGadgetWidget::applyHomeLocationOnMap()
2366 // fetch the home location
2367 if (obum
->getHomeLocation(set
, LLA
) < 0) {
2368 return false; // error
2371 if (m_telemetry_connected
) {
2372 setHome(internals::PointLatLng(LLA
[0], LLA
[1]), LLA
[2]);
2374 if (m_map
->UAV
->GetMapFollowType() != UAVMapFollowType::None
) {
2375 m_map
->SetCurrentPosition(m_home_position
.coord
); // set the map position
2383 // *************************************************************************************
2385 void OPMapGadgetWidget::setMapFollowingMode()
2387 if (!m_widget
|| !m_map
) {
2391 if (!followUAVpositionAct
->isChecked()) {
2392 m_map
->UAV
->SetMapFollowType(UAVMapFollowType::None
);
2393 m_map
->SetRotate(0); // reset map rotation to 0deg
2394 } else if (!followUAVheadingAct
->isChecked()) {
2395 m_map
->UAV
->SetMapFollowType(UAVMapFollowType::CenterMap
);
2396 m_map
->SetRotate(0); // reset map rotation to 0deg
2398 m_map
->UAV
->SetMapFollowType(UAVMapFollowType::CenterMap
); // the map library won't let you reset the uav rotation if it's already in rotate mode
2400 m_map
->UAV
->SetUAVHeading(0); // reset the UAV heading to 0deg
2401 m_map
->UAV
->SetMapFollowType(UAVMapFollowType::CenterAndRotateMap
);
2405 // *************************************************************************************
2406 // update the HomeLocation UAV Object
2408 bool OPMapGadgetWidget::setHomeLocationObject()
2414 double LLA
[3] = { m_home_position
.coord
.Lat(), m_home_position
.coord
.Lng(), m_home_position
.altitude
};
2415 return obum
->setHomeLocation(LLA
, true) >= 0;
2418 // *************************************************************************************
2420 void OPMapGadgetWidget::SetUavPic(QString UAVPic
)
2422 m_map
->SetUavPic(UAVPic
);
2425 void OPMapGadgetWidget::on_tbFind_clicked()
2427 QPalette pal
= m_widget
->leFind
->palette();
2429 QString status
= m_map
->SetCurrentPositionByKeywords(m_widget
->leFind
->text());
2431 if (status
== "OK") {
2432 pal
.setColor(m_widget
->leFind
->backgroundRole(), Qt::green
);
2433 m_widget
->leFind
->setPalette(pal
);
2435 } else if (status
== "ZERO_RESULTS") {
2436 pal
.setColor(m_widget
->leFind
->backgroundRole(), Qt::red
);
2437 m_widget
->leFind
->setPalette(pal
);
2438 qDebug() << "No results";
2439 } else if (status
== "OVER_QUERY_LIMIT") {
2440 pal
.setColor(m_widget
->leFind
->backgroundRole(), Qt::yellow
);
2441 m_widget
->leFind
->setPalette(pal
);
2442 qDebug() << "You are over quota on queries";
2443 } else if (status
== "REQUEST_DENIED") {
2444 pal
.setColor(m_widget
->leFind
->backgroundRole(), Qt::darkRed
);
2445 m_widget
->leFind
->setPalette(pal
);
2446 qDebug() << "Request was denied";
2447 } else if (status
== "INVALID_REQUEST") {
2448 pal
.setColor(m_widget
->leFind
->backgroundRole(), Qt::darkYellow
);
2449 m_widget
->leFind
->setPalette(pal
);
2450 qDebug() << "Invalid request, missing address, lat long or location";
2451 } else if (status
== "UNKNOWN_ERROR") {
2452 pal
.setColor(m_widget
->leFind
->backgroundRole(), Qt::darkYellow
);
2453 m_widget
->leFind
->setPalette(pal
);
2454 qDebug() << "Some sort of server error.";
2456 pal
.setColor(m_widget
->leFind
->backgroundRole(), Qt::gray
);
2457 m_widget
->leFind
->setPalette(pal
);
2458 qDebug() << "Some sort of code error!";
2462 void OPMapGadgetWidget::onHomeDoubleClick(HomeItem
*)
2464 new homeEditor(m_map
->Home
, this);
2467 void OPMapGadgetWidget::onOverlayOpacityActGroup_triggered(QAction
*action
)
2469 if (!m_widget
|| !m_map
|| !action
) {
2473 m_map
->setOverlayOpacity(action
->data().toReal() / 100);
2474 emit
overlayOpacityChanged(action
->data().toReal() / 100);
2477 void OPMapGadgetWidget::on_leFind_returnPressed()
2479 on_tbFind_clicked();
2482 void OPMapGadgetWidget::setDefaultWaypointAltitude(qreal default_altitude
)
2484 m_defaultWaypointAltitude
= default_altitude
;
2486 model
->setDefaultWaypointAltitude(default_altitude
);
2490 void OPMapGadgetWidget::setDefaultWaypointVelocity(qreal default_velocity
)
2492 m_defaultWaypointVelocity
= default_velocity
;
2494 model
->setDefaultWaypointVelocity(default_velocity
);