|
| 1 | +/** |
| 2 | + * @file gps.cpp |
| 3 | + * @author WARG |
| 4 | + * |
| 5 | + * @section LICENSE |
| 6 | + * |
| 7 | + * Copyright (c) 2015-2017, Waterloo Aerial Robotics Group (WARG) |
| 8 | + * All rights reserved. |
| 9 | + * |
| 10 | + * This software is licensed under a modified version of the BSD 3 clause license |
| 11 | + * that should have been included with this software in a file called COPYING.txt |
| 12 | + * Otherwise it is available at: |
| 13 | + * https://raw.githubusercontent.com/UWARG/computer-vision/master/COPYING.txt |
| 14 | + */ |
| 15 | + |
| 16 | +#include <iomanip> |
| 17 | +#include <boost/log/trivial.hpp> |
| 18 | +#include "frame.h" |
| 19 | + |
| 20 | +#define RAD2DEG(rad) ((rad)*180.0/M_PI) |
| 21 | +#define DEG2RAD(deg) ((deg)*M_PI/180.0) |
| 22 | +#define EARTH_RADIUS 6371000 |
| 23 | + |
| 24 | +//Based on the GPS location of the image, calculates the |
| 25 | +//GPS location of a certain pixel in the image. |
| 26 | +bool get_gps(cv::Point2d point, Frame* f, cv::Point2d* returnResult){ |
| 27 | + if (f == NULL) { |
| 28 | + BOOST_LOG_TRIVIAL(error) << "Frame is null"; |
| 29 | + return false; |
| 30 | + } |
| 31 | + BOOST_LOG_TRIVIAL(trace) << "get_gps(" << point << ", " << f->get_id() << ")"; |
| 32 | + |
| 33 | + const Metadata* m = f->get_metadata(); |
| 34 | + cv::Mat img = f->get_img(); |
| 35 | + int h = img.cols; |
| 36 | + int w = img.rows; |
| 37 | + |
| 38 | + if (w <= 0 || h <= 0){ |
| 39 | + BOOST_LOG_TRIVIAL(error) << "Invalid frame size w:" << w << " h:" << h; |
| 40 | + return false; |
| 41 | + } |
| 42 | + |
| 43 | + cv::Point2d imgCenter(w/2, h/2); |
| 44 | + |
| 45 | + //(0,0) is in the center of the image |
| 46 | + cv::Point2d biasedPoint = point - imgCenter; |
| 47 | + |
| 48 | + double altitude = m->altitude; |
| 49 | + double heading = m->heading; |
| 50 | + double latitude = m->lat; |
| 51 | + double longitude = m->lon; |
| 52 | + |
| 53 | + BOOST_LOG_TRIVIAL(trace) << "Camera FOV: " << f->get_camera().get_fov(); |
| 54 | + |
| 55 | + BOOST_LOG_TRIVIAL(trace) << "Dist from Center (pixels: " << biasedPoint; |
| 56 | + |
| 57 | + double cameraXEdge = altitude * tan(DEG2RAD(f->get_camera().get_fov().width/2)); //meters from center of photo to edge |
| 58 | + double cameraYEdge = altitude * tan(DEG2RAD(f->get_camera().get_fov().height/2)); //meters from center of photo to edge |
| 59 | + |
| 60 | + BOOST_LOG_TRIVIAL(trace) << "X Edge: " << cameraXEdge << " Y Edge: " << cameraYEdge; |
| 61 | + |
| 62 | + //Rotation Matrix - Heading |
| 63 | + //Note: The '-heading' compensates for the fact that directional heading is |
| 64 | + //a clockwise quantity, but cos(theta) assumes theta is a counterclockwise |
| 65 | + //quantity. |
| 66 | + double realX = cos(DEG2RAD(-heading)) * biasedPoint.x/(w/2)*cameraXEdge - sin(DEG2RAD(-heading)) * biasedPoint.y/(h/2)*cameraYEdge; |
| 67 | + double realY = sin(DEG2RAD(-heading)) * biasedPoint.x/(w/2)*cameraXEdge + cos(DEG2RAD(-heading)) * biasedPoint.y/(h/2)*cameraYEdge; |
| 68 | + |
| 69 | + BOOST_LOG_TRIVIAL(trace) << "Real X: " << realX << " Real Y: " << realY; |
| 70 | + |
| 71 | + double lon = RAD2DEG(realX/EARTH_RADIUS)/cos(DEG2RAD(latitude)) + longitude; |
| 72 | + double lat = RAD2DEG(realY/EARTH_RADIUS) + latitude; |
| 73 | + |
| 74 | + BOOST_LOG_TRIVIAL(trace) << "Distance from centre: " << RAD2DEG(realY/EARTH_RADIUS) << " " << RAD2DEG(realX/EARTH_RADIUS)/cos(DEG2RAD(latitude)); |
| 75 | + |
| 76 | + BOOST_LOG_TRIVIAL(trace) << std::setprecision(10) << "Result: " << lat << " " << lon; |
| 77 | + |
| 78 | + *returnResult = cv::Point2d(lat,lon); |
| 79 | + return true; |
| 80 | +} |
| 81 | + |
| 82 | +double gps_dist(cv::Point2d p1, cv::Point2d p2) { |
| 83 | + double dLat = DEG2RAD(p2.x-p1.x); |
| 84 | + double dLon = DEG2RAD(p2.y-p1.y); |
| 85 | + |
| 86 | + double rLat1 = DEG2RAD(p1.x); |
| 87 | + double rLat2 = DEG2RAD(p2.x); |
| 88 | + |
| 89 | + double a = sin(dLat/2) * sin(dLat/2) + |
| 90 | + sin(dLon/2) * sin(dLon/2) * cos(rLat1) * cos(rLat2); |
| 91 | + double c = 2 * atan2(sqrt(a), sqrt(1-a)); |
| 92 | + return EARTH_RADIUS * c; |
| 93 | +} |
0 commit comments