From 6922951750a270e7529b64b2833675662bac4c82 Mon Sep 17 00:00:00 2001 From: lm Date: Sat, 9 Jul 2011 19:41:03 +0200 Subject: [PATCH] Map caching works now, uav following as well. Waypoint lines and some graphical tweaks needed, but its very close to an alpha release now --- .../opmapcontrol/opmapcontrol_external.pri | 6 +- .../src/mapwidget/mapgraphicitem.h | 8 +- .../src/mapwidget/opmapwidget.cpp | 6 + .../src/mapwidget/waypointlineitem.cpp | 5 + .../src/mapwidget/waypointlineitem.h | 12 ++ src/ui/map/QGCMapToolBar.cc | 36 ++++ src/ui/map/QGCMapToolbar.h | 5 + src/ui/map/QGCMapToolbar.ui | 21 ++- src/ui/map/QGCMapWidget.cc | 174 +++++++++++------- src/ui/map/QGCMapWidget.h | 9 + 10 files changed, 204 insertions(+), 78 deletions(-) create mode 100644 src/libs/opmapcontrol/src/mapwidget/waypointlineitem.cpp create mode 100644 src/libs/opmapcontrol/src/mapwidget/waypointlineitem.h diff --git a/src/libs/opmapcontrol/opmapcontrol_external.pri b/src/libs/opmapcontrol/opmapcontrol_external.pri index 8068e4e89..6441bdd26 100644 --- a/src/libs/opmapcontrol/opmapcontrol_external.pri +++ b/src/libs/opmapcontrol/opmapcontrol_external.pri @@ -60,7 +60,8 @@ HEADERS += opmapcontrol.h \ src/internals/projections/mercatorprojection.h \ src/internals/projections/mercatorprojectionyandex.h \ src/internals/projections/platecarreeprojection.h \ - src/internals/projections/platecarreeprojectionpergo.h + src/internals/projections/platecarreeprojectionpergo.h \ + src/libs/opmapcontrol/src/mapwidget/waypointlineitem.h FORMS += src/mapwidget/mapripform.ui SOURCES += src/core/alllayersoftype.cpp \ src/core/cache.cpp \ @@ -104,5 +105,6 @@ SOURCES += src/core/alllayersoftype.cpp \ src/internals/projections/mercatorprojection.cpp \ src/internals/projections/mercatorprojectionyandex.cpp \ src/internals/projections/platecarreeprojection.cpp \ - src/internals/projections/platecarreeprojectionpergo.cpp + src/internals/projections/platecarreeprojectionpergo.cpp \ + src/libs/opmapcontrol/src/mapwidget/waypointlineitem.cpp RESOURCES += src/mapwidget/mapresources.qrc diff --git a/src/libs/opmapcontrol/src/mapwidget/mapgraphicitem.h b/src/libs/opmapcontrol/src/mapwidget/mapgraphicitem.h index f9a7db35d..2c78d27f5 100644 --- a/src/libs/opmapcontrol/src/mapwidget/mapgraphicitem.h +++ b/src/libs/opmapcontrol/src/mapwidget/mapgraphicitem.h @@ -109,6 +109,13 @@ namespace mapcontrol double ZoomDigi(); double ZoomTotal(); + /** + * @brief The area currently selected by the user + * + * @return The rectangle in lat/lon coordinates currently selected + */ + internals::RectLatLng SelectedArea()const{return selectedArea;} + protected: void mouseMoveEvent ( QGraphicsSceneMouseEvent * event ); void mousePressEvent ( QGraphicsSceneMouseEvent * event ); @@ -190,7 +197,6 @@ namespace mapcontrol int MinZoom()const{return minZoom;} internals::MouseWheelZoomType::Types GetMouseWheelZoomType(){return core->GetMouseWheelZoomType();} void SetSelectedArea(internals::RectLatLng const& value){selectedArea = value;this->update();} - internals::RectLatLng SelectedArea()const{return selectedArea;} internals::RectLatLng BoundsOfMap; void Offset(int const& x, int const& y); bool CanDragMap()const{return core->CanDragMap;} diff --git a/src/libs/opmapcontrol/src/mapwidget/opmapwidget.cpp b/src/libs/opmapcontrol/src/mapwidget/opmapwidget.cpp index 013671f30..f8f44e45a 100644 --- a/src/libs/opmapcontrol/src/mapwidget/opmapwidget.cpp +++ b/src/libs/opmapcontrol/src/mapwidget/opmapwidget.cpp @@ -94,12 +94,18 @@ namespace mapcontrol UAVItem* newUAV = new UAVItem(map,this); newUAV->setParentItem(map); UAVS.insert(id, newUAV); + QGraphicsItemGroup* waypointLine = new QGraphicsItemGroup(); + waypointLine->setParentItem(map); + waypointLines.insert(id, waypointLine); return newUAV; } void OPMapWidget::AddUAV(int id, UAVItem* uav) { uav->setParentItem(map); + QGraphicsItemGroup* waypointLine = new QGraphicsItemGroup(); + waypointLine->setParentItem(map); + waypointLines.insert(id, waypointLine); UAVS.insert(id, uav); } diff --git a/src/libs/opmapcontrol/src/mapwidget/waypointlineitem.cpp b/src/libs/opmapcontrol/src/mapwidget/waypointlineitem.cpp new file mode 100644 index 000000000..89969588b --- /dev/null +++ b/src/libs/opmapcontrol/src/mapwidget/waypointlineitem.cpp @@ -0,0 +1,5 @@ +#include "waypointlineitem.h" + +WaypointLineItem::WaypointLineItem() +{ +} diff --git a/src/libs/opmapcontrol/src/mapwidget/waypointlineitem.h b/src/libs/opmapcontrol/src/mapwidget/waypointlineitem.h new file mode 100644 index 000000000..2532c4398 --- /dev/null +++ b/src/libs/opmapcontrol/src/mapwidget/waypointlineitem.h @@ -0,0 +1,12 @@ +#ifndef WAYPOINTLINEITEM_H +#define WAYPOINTLINEITEM_H + +#include + +class WaypointLineItem : public QGraphicsLineItem +{ +public: + WaypointLineItem(); +}; + +#endif // WAYPOINTLINEITEM_H diff --git a/src/ui/map/QGCMapToolBar.cc b/src/ui/map/QGCMapToolBar.cc index 2d70fd316..462d35a43 100644 --- a/src/ui/map/QGCMapToolBar.cc +++ b/src/ui/map/QGCMapToolBar.cc @@ -18,6 +18,42 @@ void QGCMapToolBar::setMap(QGCMapWidget* map) { connect(ui->goToButton, SIGNAL(clicked()), map, SLOT(showGoToDialog())); connect(ui->goHomeButton, SIGNAL(clicked()), map, SLOT(goHome())); + connect(map, SIGNAL(OnTileLoadStart()), this, SLOT(tileLoadStart())); + connect(map, SIGNAL(OnTileLoadComplete()), this, SLOT(tileLoadEnd())); + connect(map, SIGNAL(OnTilesStillToLoad(int)), this, SLOT(tileLoadProgress(int))); + connect(ui->ripMapButton, SIGNAL(clicked()), map, SLOT(cacheVisibleRegion())); + + ui->followCheckBox->setChecked(map->getFollowUAVEnabled()); + connect(ui->followCheckBox, SIGNAL(clicked(bool)), map, SLOT(setFollowUAVEnabled(bool))); + + // Edit mode handling + ui->editButton->hide(); + } +} + +void QGCMapToolBar::tileLoadStart() +{ + ui->posLabel->setText(QString("Starting to load tiles..")); +} + +void QGCMapToolBar::tileLoadEnd() +{ + ui->posLabel->setText(QString("Finished")); +} + +void QGCMapToolBar::tileLoadProgress(int progress) +{ + if (progress == 1) + { + ui->posLabel->setText(QString("1 tile to load..")); + } + else if (progress > 0) + { + ui->posLabel->setText(QString("%1 tiles to load..").arg(progress)); + } + else + { + tileLoadEnd(); } } diff --git a/src/ui/map/QGCMapToolbar.h b/src/ui/map/QGCMapToolbar.h index ea773f030..8b61d776b 100644 --- a/src/ui/map/QGCMapToolbar.h +++ b/src/ui/map/QGCMapToolbar.h @@ -19,6 +19,11 @@ public: void setMap(QGCMapWidget* map); +public slots: + void tileLoadStart(); + void tileLoadEnd(); + void tileLoadProgress(int progress); + protected: QGCMapWidget* map; diff --git a/src/ui/map/QGCMapToolbar.ui b/src/ui/map/QGCMapToolbar.ui index f11c923e7..3189d5063 100644 --- a/src/ui/map/QGCMapToolbar.ui +++ b/src/ui/map/QGCMapToolbar.ui @@ -20,13 +20,6 @@ 4 - - - - 00.00 00.00 - - - @@ -48,6 +41,13 @@ + + + + Cache + + + @@ -55,6 +55,13 @@ + + + + 00.00 00.00 + + + diff --git a/src/ui/map/QGCMapWidget.cc b/src/ui/map/QGCMapWidget.cc index ded9b140c..c21d6b5ed 100644 --- a/src/ui/map/QGCMapWidget.cc +++ b/src/ui/map/QGCMapWidget.cc @@ -10,9 +10,12 @@ QGCMapWidget::QGCMapWidget(QWidget *parent) : mapcontrol::OPMapWidget(parent), currWPManager(NULL), firingWaypointChange(NULL), - maxUpdateInterval(2) // 2 seconds + maxUpdateInterval(2), // 2 seconds + followUAVEnabled(false) { // Widget is inactive until shown + + // Set cache mode } QGCMapWidget::~QGCMapWidget() @@ -152,7 +155,7 @@ void QGCMapWidget::storeSettings() void QGCMapWidget::mouseDoubleClickEvent(QMouseEvent* event) { - //OPMapWidget::mouseDoubleClickEvent(event); + OPMapWidget::mouseDoubleClickEvent(event); if (currEditMode == EDIT_MODE_WAYPOINTS) { // If a waypoint manager is available @@ -213,6 +216,7 @@ void QGCMapWidget::activeUASSet(UASInterface* uas) connect(this, SIGNAL(waypointCreated(Waypoint*)), currWPManager, SLOT(addWaypoint(Waypoint*))); connect(this, SIGNAL(waypointChanged(Waypoint*)), currWPManager, SLOT(notifyOfChange(Waypoint*))); updateSelectedSystem(uas->getUASID()); + followUAVID = uas->getUASID(); } } @@ -246,6 +250,8 @@ void QGCMapWidget::updateGlobalPosition(UASInterface* uas, double lat, double lo // Set new lat/lon position of UAV icon internals::PointLatLng pos_lat_lon = internals::PointLatLng(lat, lon); uav->SetUAVPos(pos_lat_lon, alt); + // Follow status + if (followUAVEnabled && uas->getUASID() == followUAVID) SetCurrentPosition(pos_lat_lon); // Convert from radians to degrees and apply uav->SetUAVHeading((uas->getYaw()/M_PI)*180.0f); } @@ -265,14 +271,15 @@ void QGCMapWidget::updateGlobalPosition() if (uav == NULL) { MAV2DIcon* newUAV = new MAV2DIcon(map, this, system); - newUAV->setParentItem(map); - UAVS.insert(system->getUASID(), newUAV); - uav = GetUAV(system->getUASID()); + AddUAV(system->getUASID(), newUAV); + uav = newUAV; } // Set new lat/lon position of UAV icon internals::PointLatLng pos_lat_lon = internals::PointLatLng(system->getLatitude(), system->getLongitude()); uav->SetUAVPos(pos_lat_lon, system->getAltitude()); + // Follow status + if (followUAVEnabled && system->getUASID() == followUAVID) SetCurrentPosition(pos_lat_lon); // Convert from radians to degrees and apply uav->SetUAVHeading((system->getYaw()/M_PI)*180.0f); } @@ -316,7 +323,7 @@ void QGCMapWidget::showGoToDialog() bool ok; QString text = QInputDialog::getText(this, tr("Please enter coordinates"), tr("Coordinates (Lat,Lon):"), QLineEdit::Normal, - QString("%1,%2").arg(CurrentPosition().Lat()).arg( CurrentPosition().Lng()), &ok); + QString("%1,%2").arg(CurrentPosition().Lat(), 0, 'g', 6).arg(CurrentPosition().Lng(), 0, 'g', 6), &ok); if (ok && !text.isEmpty()) { QStringList split = text.split(","); if (split.length() == 2) { @@ -357,6 +364,26 @@ void QGCMapWidget::setUpdateRateLimit(float seconds) updateTimer.start(maxUpdateInterval*1000); } +void QGCMapWidget::cacheVisibleRegion() +{ + internals::RectLatLng rect = map->SelectedArea(); + + if (rect.IsEmpty()) + { + QMessageBox msgBox(this); + msgBox.setIcon(QMessageBox::Information); + msgBox.setText("Cannot cache tiles for offline use"); + msgBox.setInformativeText("Please select an area first by holding down SHIFT or ALT and selecting the area with the left mouse button."); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.setDefaultButton(QMessageBox::Ok); + msgBox.exec(); + } + + RipMap(); + + // FIXME UNSELECT AREA NOW +} + // WAYPOINT MAP INTERACTION FUNCTIONS @@ -407,73 +434,84 @@ void QGCMapWidget::updateWaypoint(int uas, Waypoint* wp) { // Source of the event was in this widget, do nothing if (firingWaypointChange == wp) return; - // Currently only accept waypoint updates from the UAS in focus - // this has to be changed to accept read-only updates from other systems as well. - if (UASManager::instance()->getUASForId(uas)->getWaypointManager() == currWPManager) { - // Only accept waypoints in global coordinate frame - if (((wp->getFrame() == MAV_FRAME_GLOBAL) || (wp->getFrame() == MAV_FRAME_GLOBAL_RELATIVE_ALT)) && wp->isNavigationType()) { - // We're good, this is a global waypoint - - // Get the index of this waypoint - // note the call to getGlobalFrameAndNavTypeIndexOf() - // as we're only handling global waypoints - int wpindex = UASManager::instance()->getUASForId(uas)->getWaypointManager()->getGlobalFrameAndNavTypeIndexOf(wp); - UASInterface* uasInstance = UASManager::instance()->getUASForId(uas); - // If not found, return (this should never happen, but helps safety) - if (wpindex == -1) return; - // Mark this wp as currently edited - firingWaypointChange = wp; - - // Check if wp exists yet in map - if (!waypointsToIcons.contains(wp)) { - // Create icon for new WP - Waypoint2DIcon* icon = new Waypoint2DIcon(map, this, wp, uasInstance->getColor(), wpindex); - ConnectWP(icon); - icon->setParentItem(map); - // Update maps to allow inverse data association - waypointsToIcons.insert(wp, icon); - iconsToWaypoints.insert(icon, wp); - } else { - // Waypoint exists, block it's signals and update it - mapcontrol::WayPointItem* icon = waypointsToIcons.value(wp); - // Make sure we don't die on a null pointer - // this should never happen, just a precaution - if (!icon) return; - // Block outgoing signals to prevent an infinite signal loop - // should not happen, just a precaution - this->blockSignals(true); - // Update the WP - Waypoint2DIcon* wpicon = dynamic_cast(icon); - if (wpicon) - { - // Let icon read out values directly from waypoint - icon->SetNumber(wpindex); - wpicon->updateWaypoint(); - } - else - { - // Use safe standard interfaces for non Waypoint-class based wps - icon->SetCoord(internals::PointLatLng(wp->getLatitude(), wp->getLongitude())); - icon->SetAltitude(wp->getAltitude()); - icon->SetHeading(wp->getYaw()); - icon->SetNumber(wpindex); - } - // Re-enable signals again - this->blockSignals(false); + // Currently only accept waypoint updates from the UAS in focus + // this has to be changed to accept read-only updates from other systems as well. + if (UASManager::instance()->getUASForId(uas)->getWaypointManager() == currWPManager) { + // Only accept waypoints in global coordinate frame + if (((wp->getFrame() == MAV_FRAME_GLOBAL) || (wp->getFrame() == MAV_FRAME_GLOBAL_RELATIVE_ALT)) && wp->isNavigationType()) { + // We're good, this is a global waypoint + + // Get the index of this waypoint + // note the call to getGlobalFrameAndNavTypeIndexOf() + // as we're only handling global waypoints + int wpindex = UASManager::instance()->getUASForId(uas)->getWaypointManager()->getGlobalFrameAndNavTypeIndexOf(wp); + UASInterface* uasInstance = UASManager::instance()->getUASForId(uas); + // If not found, return (this should never happen, but helps safety) + if (wpindex == -1) return; + // Mark this wp as currently edited + firingWaypointChange = wp; + + // Check if wp exists yet in map + if (!waypointsToIcons.contains(wp)) { + // Create icon for new WP + Waypoint2DIcon* icon = new Waypoint2DIcon(map, this, wp, uasInstance->getColor(), wpindex); + ConnectWP(icon); + icon->setParentItem(map); + // Update maps to allow inverse data association + waypointsToIcons.insert(wp, icon); + iconsToWaypoints.insert(icon, wp); + + // Add line element + qDebug() << "ADDING LINE"; + mapcontrol::TrailLineItem* line = new mapcontrol::TrailLineItem(internals::PointLatLng(0.2, 0.2), icon->Coord(), QBrush(Qt::red), map); + QGraphicsItemGroup* group = waypointLines.value(uas, NULL); + if (group) + { + group->addToGroup(line); + qDebug() << "ADDED LINE!"; + } + line->setVisible(true); + } else { + // Waypoint exists, block it's signals and update it + mapcontrol::WayPointItem* icon = waypointsToIcons.value(wp); + // Make sure we don't die on a null pointer + // this should never happen, just a precaution + if (!icon) return; + // Block outgoing signals to prevent an infinite signal loop + // should not happen, just a precaution + this->blockSignals(true); + // Update the WP + Waypoint2DIcon* wpicon = dynamic_cast(icon); + if (wpicon) + { + // Let icon read out values directly from waypoint + icon->SetNumber(wpindex); + wpicon->updateWaypoint(); + } + else + { + // Use safe standard interfaces for non Waypoint-class based wps + icon->SetCoord(internals::PointLatLng(wp->getLatitude(), wp->getLongitude())); + icon->SetAltitude(wp->getAltitude()); + icon->SetHeading(wp->getYaw()); + icon->SetNumber(wpindex); } + // Re-enable signals again + this->blockSignals(false); + } - firingWaypointChange = NULL; + firingWaypointChange = NULL; - } else { - // Check if the index of this waypoint is larger than the global - // waypoint list. This implies that the coordinate frame of this - // waypoint was changed and the list containing only global - // waypoints was shortened. Thus update the whole list - if (waypointsToIcons.size() > UASManager::instance()->getUASForId(uas)->getWaypointManager()->getGlobalFrameAndNavTypeCount()) { - updateWaypointList(uas); - } + } else { + // Check if the index of this waypoint is larger than the global + // waypoint list. This implies that the coordinate frame of this + // waypoint was changed and the list containing only global + // waypoints was shortened. Thus update the whole list + if (waypointsToIcons.size() > UASManager::instance()->getUASForId(uas)->getWaypointManager()->getGlobalFrameAndNavTypeCount()) { + updateWaypointList(uas); } } + } } /** diff --git a/src/ui/map/QGCMapWidget.h b/src/ui/map/QGCMapWidget.h index a9fab564e..2b6048161 100644 --- a/src/ui/map/QGCMapWidget.h +++ b/src/ui/map/QGCMapWidget.h @@ -24,6 +24,9 @@ public: // double headingP1P2(internals::PointLatLng p1, internals::PointLatLng p2); // internals::PointLatLng targetLatLon(internals::PointLatLng source, double heading, double dist); + /** @brief Map centered on current active system */ + bool getFollowUAVEnabled() { return followUAVEnabled; } + signals: void homePositionChanged(double latitude, double longitude, double altitude); /** @brief Signal for newly created map waypoints */ @@ -53,6 +56,10 @@ public slots: void updateHomePosition(double latitude, double longitude, double altitude); /** @brief Set update rate limit */ void setUpdateRateLimit(float seconds); + /** @brief Cache visible region to harddisk */ + void cacheVisibleRegion(); + /** @brief Set follow mode */ + void setFollowUAVEnabled(bool enabled) { followUAVEnabled = enabled; } void loadSettings(); void storeSettings(); @@ -85,6 +92,8 @@ protected: EDIT_MODE_CACHING }; editMode currEditMode; ///< The current edit mode on the map + bool followUAVEnabled; ///< Does the map follow the UAV? + int followUAVID; ///< Which UAV should be tracked? }; -- 2.22.0