package org.droidplanner.services.android.impl.core.survey; import com.MAVLink.ardupilotmega.msg_camera_feedback; import org.droidplanner.services.android.impl.core.helpers.geoTools.GeoTools; import com.o3dr.services.android.lib.coordinate.LatLong; import com.o3dr.services.android.lib.util.MathUtils; import java.util.ArrayList; import java.util.List; public class Footprint { /** * Vertex of the footprint in local frame index 0 is top right, where top is * direction of longitudinal travel. Index increases CCW */ private final List<LatLong> vertex = new ArrayList<>(); private double meanGSD; public Footprint(CameraInfo camera, double altitude) { this(camera, new LatLong(0, 0), (float) altitude, 0, 0, 0); } public Footprint(CameraInfo camera, msg_camera_feedback msg) { this(camera, new LatLong(msg.lat / 1E7, msg.lng / 1E7), msg.alt_rel, msg.pitch, msg.roll, msg.yaw); } public Footprint(CameraInfo camera, LatLong center, double alt, double pitch, double roll, double yaw) { double sx = camera.getSensorLateralSize() / 2; double sy = camera.getSensorLongitudinalSize() / 2; double f = camera.focalLength; double[][] dcm = MathUtils.dcmFromEuler(Math.toRadians(pitch), Math.toRadians(-roll + 180), Math.toRadians(-yaw)); vertex.add(cameraFrameToLocalFrame(new LatLong(-sx, -sy), dcm, alt, f, center)); vertex.add(cameraFrameToLocalFrame(new LatLong(+sx, -sy), dcm, alt, f, center)); vertex.add(cameraFrameToLocalFrame(new LatLong(+sx, +sy), dcm, alt, f, center)); vertex.add(cameraFrameToLocalFrame(new LatLong(-sx, +sy), dcm, alt, f, center)); meanGSD = 0.001 * getLateralSize() * (sy / sx) / Math.sqrt(camera.sensorResolution); } /** * based on http://www.asprs.org/a/publications/pers/2005journal/july/2005_july_863-871.pdf */ static private LatLong cameraFrameToLocalFrame(LatLong img, double[][] dcm, double alt, double focalLength, LatLong center) { double x = alt * (dcm[0][0] * img.getLatitude() + dcm[1][0] * img.getLongitude() + dcm[2][0] * (-focalLength)) / (dcm[0][2] * img.getLatitude() + dcm[1][2] * img.getLongitude() + dcm[2][2] * (-focalLength)); double y = alt * (dcm[0][1] * img.getLatitude() + dcm[1][1] * img.getLongitude() + dcm[2][1] * (-focalLength)) / (dcm[0][2] * img.getLatitude() + dcm[1][2] * img.getLongitude() + dcm[2][2] * (-focalLength)); return GeoTools.moveCoordinate(center, x, y); } public double getLateralSize() { return (GeoTools.getDistance(vertex.get(0), vertex.get(1)) + GeoTools .getDistance(vertex.get(2), vertex.get(3))) / 2; } public double getLongitudinalSize() { return (GeoTools.getDistance(vertex.get(0), vertex.get(3)) + GeoTools .getDistance(vertex.get(1), vertex.get(2))) / 2; } public List<LatLong> getVertexInGlobalFrame() { return vertex; } public double getGSD() { return meanGSD; } }