HomePositionManager.cc 5.84 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
/*=====================================================================
 
 QGroundControl Open Source Ground Control Station
 
 (c) 2009 - 2015 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
 
 This file is part of the QGROUNDCONTROL project
 
 QGROUNDCONTROL is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.
 
 QGROUNDCONTROL is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
 
 ======================================================================*/
pixhawk's avatar
pixhawk committed
23 24 25 26

#include <QList>
#include <QApplication>
#include <QTimer>
27
#include <QSettings>
Don Gagne's avatar
Don Gagne committed
28

pixhawk's avatar
pixhawk committed
29
#include "UAS.h"
30
#include "UASInterface.h"
31
#include "HomePositionManager.h"
32
#include "QGC.h"
Don Gagne's avatar
Don Gagne committed
33
#include "QGCMessageBox.h"
34
#include "QGCApplication.h"
35
#include "MultiVehicleManager.h"
pixhawk's avatar
pixhawk committed
36

LM's avatar
LM committed
37 38 39 40
#define PI 3.1415926535897932384626433832795
#define MEAN_EARTH_DIAMETER	12756274.0
#define UMR	0.017453292519943295769236907684886

41
IMPLEMENT_QGC_SINGLETON(HomePositionManager, HomePositionManager)
42

43 44
HomePositionManager::HomePositionManager(QObject* parent) :
    QObject(parent),
Don Gagne's avatar
Don Gagne committed
45 46 47 48
    homeLat(47.3769),
    homeLon(8.549444),
    homeAlt(470.0),
    homeFrame(MAV_FRAME_GLOBAL)
49
{
Don Gagne's avatar
Don Gagne committed
50
    loadSettings();
51 52
}

53
HomePositionManager::~HomePositionManager()
54
{
Don Gagne's avatar
Don Gagne committed
55
    storeSettings();
56 57
}

58
void HomePositionManager::storeSettings()
59 60 61 62 63 64 65 66 67
{
    QSettings settings;
    settings.beginGroup("QGC_UASMANAGER");
    settings.setValue("HOMELAT", homeLat);
    settings.setValue("HOMELON", homeLon);
    settings.setValue("HOMEALT", homeAlt);
    settings.endGroup();
}

68
void HomePositionManager::loadSettings()
69 70 71
{
    QSettings settings;
    settings.beginGroup("QGC_UASMANAGER");
72
    bool changed =  setHomePosition(settings.value("HOMELAT", homeLat).toDouble(),
73 74
                                    settings.value("HOMELON", homeLon).toDouble(),
                                    settings.value("HOMEALT", homeAlt).toDouble());
75 76 77 78 79 80 81 82

    // Make sure to fire the change - this will
    // make sure widgets get the signal once
    if (!changed)
    {
        emit homePositionChanged(homeLat, homeLon, homeAlt);
    }

83 84 85
    settings.endGroup();
}

86
bool HomePositionManager::setHomePosition(double lat, double lon, double alt)
87 88
{
    // Checking for NaN and infitiny
89 90 91 92 93 94
    // and checking for borders
    bool changed = false;
    if (!isnan(lat) && !isnan(lon) && !isnan(alt)
        && !isinf(lat) && !isinf(lon) && !isinf(alt)
        && lat <= 90.0 && lat >= -90.0 && lon <= 180.0 && lon >= -180.0)
        {
95

96 97 98
        if (fabs(homeLat - lat) > 1e-7) changed = true;
        if (fabs(homeLon - lon) > 1e-7) changed = true;
        if (fabs(homeAlt - alt) > 0.5f) changed = true;
99

100 101 102
        // Initialize conversion reference in any case
        initReference(lat, lon, alt);

103 104 105 106 107
        if (changed)
        {
            homeLat = lat;
            homeLon = lon;
            homeAlt = alt;
108

109 110 111 112 113
            emit homePositionChanged(homeLat, homeLon, homeAlt);
        }
    }
    return changed;
}
114

115
bool HomePositionManager::setHomePositionAndNotify(double lat, double lon, double alt)
116 117 118 119 120
{
    // Checking for NaN and infitiny
    // and checking for borders
    bool changed = setHomePosition(lat, lon, alt);

121 122
    if (changed) {
        MultiVehicleManager::instance()->setHomePositionForAllVehicles(homeLat, homeLon, homeAlt);
123
    }
Lorenz Meier's avatar
Lorenz Meier committed
124 125

	return changed;
126 127
}

128
void HomePositionManager::initReference(const double & latitude, const double & longitude, const double & altitude)
129 130 131 132 133
{
    Eigen::Matrix3d R;
    double s_long, s_lat, c_long, c_lat;
    sincos(latitude * DEG2RAD, &s_lat, &c_lat);
    sincos(longitude * DEG2RAD, &s_long, &c_long);
LM's avatar
LM committed
134

135 136 137
    R(0, 0) = -s_long;
    R(0, 1) = c_long;
    R(0, 2) = 0;
LM's avatar
LM committed
138

139 140 141
    R(1, 0) = -s_lat * c_long;
    R(1, 1) = -s_lat * s_long;
    R(1, 2) = c_lat;
LM's avatar
LM committed
142

143 144 145
    R(2, 0) = c_lat * c_long;
    R(2, 1) = c_lat * s_long;
    R(2, 2) = s_lat;
LM's avatar
LM committed
146

147
    ecef_ref_orientation_ = Eigen::Quaterniond(R);
LM's avatar
LM committed
148

149 150
    ecef_ref_point_ = wgs84ToEcef(latitude, longitude, altitude);
}
LM's avatar
LM committed
151

152
Eigen::Vector3d HomePositionManager::wgs84ToEcef(const double & latitude, const double & longitude, const double & altitude)
153 154 155
{
    const double a = 6378137.0; // semi-major axis
    const double e_sq = 6.69437999014e-3; // first eccentricity squared
LM's avatar
LM committed
156

157 158 159
    double s_long, s_lat, c_long, c_lat;
    sincos(latitude * DEG2RAD, &s_lat, &c_lat);
    sincos(longitude * DEG2RAD, &s_long, &c_long);
LM's avatar
LM committed
160

161
    const double N = a / sqrt(1 - e_sq * s_lat * s_lat);
LM's avatar
LM committed
162

163
    Eigen::Vector3d ecef;
LM's avatar
LM committed
164

165 166 167
    ecef[0] = (N + altitude) * c_lat * c_long;
    ecef[1] = (N + altitude) * c_lat * s_long;
    ecef[2] = (N * (1 - e_sq) + altitude) * s_lat;
LM's avatar
LM committed
168

169 170 171
    return ecef;
}

172
Eigen::Vector3d HomePositionManager::ecefToEnu(const Eigen::Vector3d & ecef)
173 174 175 176
{
    return ecef_ref_orientation_ * (ecef - ecef_ref_point_);
}

177
void HomePositionManager::wgs84ToEnu(const double& lat, const double& lon, const double& alt, double* east, double* north, double* up)
178 179 180 181 182 183 184
{
    Eigen::Vector3d ecef = wgs84ToEcef(lat, lon, alt);
    Eigen::Vector3d enu = ecefToEnu(ecef);
    *east = enu.x();
    *north = enu.y();
    *up = enu.z();
}
LM's avatar
LM committed
185

186
void HomePositionManager::enuToWgs84(const double& x, const double& y, const double& z, double* lat, double* lon, double* alt)
LM's avatar
LM committed
187 188 189 190 191 192
{
    *lat=homeLat+y/MEAN_EARTH_DIAMETER*360./PI;
    *lon=homeLon+x/MEAN_EARTH_DIAMETER*360./PI/cos(homeLat*UMR);
    *alt=homeAlt+z;
}

193
void HomePositionManager::nedToWgs84(const double& x, const double& y, const double& z, double* lat, double* lon, double* alt)
LM's avatar
LM committed
194 195 196 197 198 199
{
    *lat=homeLat+x/MEAN_EARTH_DIAMETER*360./PI;
    *lon=homeLon+y/MEAN_EARTH_DIAMETER*360./PI/cos(homeLat*UMR);
    *alt=homeAlt-z;
}