1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package com.irurueta.navigation.frames.converters;
17
18 import com.irurueta.algebra.Matrix;
19 import com.irurueta.algebra.WrongSizeException;
20 import com.irurueta.geometry.InvalidRotationMatrixException;
21 import com.irurueta.navigation.frames.CoordinateTransformation;
22 import com.irurueta.navigation.frames.ECEFFrame;
23 import com.irurueta.navigation.frames.ECIorECEFFrame;
24 import com.irurueta.navigation.frames.FrameType;
25 import com.irurueta.navigation.frames.InvalidSourceAndDestinationFrameTypeException;
26 import com.irurueta.navigation.frames.NEDFrame;
27 import com.irurueta.navigation.geodesic.Constants;
28
29
30
31
32
33
34
35
36
37 public class ECEFtoNEDFrameConverter implements FrameConverter<ECEFFrame, NEDFrame> {
38
39
40
41
42 public static final double EARTH_EQUATORIAL_RADIUS_WGS84 = Constants.EARTH_EQUATORIAL_RADIUS_WGS84;
43
44
45
46
47 public static final double EARTH_ECCENTRICITY = Constants.EARTH_ECCENTRICITY;
48
49
50
51
52
53
54
55 @Override
56 public NEDFrame convertAndReturnNew(final ECEFFrame source) {
57 final var result = new NEDFrame();
58 convert(source, result);
59 return result;
60 }
61
62
63
64
65
66
67
68 @Override
69 public void convert(final ECEFFrame source, final NEDFrame destination) {
70 convertECEFtoNED(source, destination);
71 }
72
73
74
75
76
77
78 @Override
79 public FrameType getSourceType() {
80 return FrameType.EARTH_CENTERED_EARTH_FIXED_FRAME;
81 }
82
83
84
85
86
87
88 @Override
89 public FrameType getDestinationType() {
90 return FrameType.LOCAL_NAVIGATION_FRAME;
91 }
92
93
94
95
96
97
98
99 public static NEDFrame convertECEFtoNEDAndReturnNew(final ECEFFrame source) {
100 final var result = new NEDFrame();
101 convertECEFtoNED(source, result);
102 return result;
103 }
104
105
106
107
108
109
110
111 @SuppressWarnings("DuplicatedCode")
112 public static void convertECEFtoNED(final ECEFFrame source, final NEDFrame destination) {
113 final var x = source.getX();
114 final var y = source.getY();
115 final var z = source.getZ();
116
117
118 final var longitude = Math.atan2(y, x);
119
120
121 final var ecc2 = EARTH_ECCENTRICITY * EARTH_ECCENTRICITY;
122 final var k1 = Math.sqrt(1.0 - ecc2) * Math.abs(z);
123 final var k2 = ecc2 * EARTH_EQUATORIAL_RADIUS_WGS84;
124
125 final var x2 = x * x;
126 final var y2 = y * y;
127 final var beta = Math.sqrt(x2 + y2);
128
129 final var e = (k1 - k2) / beta;
130 final var f = (k1 + k2) / beta;
131
132
133 final var p = 4.0 / 3.0 * (e * f + 1.0);
134
135
136 final var e2 = e * e;
137 final var f2 = f * f;
138 final var q = 2.0 * (e2 - f2);
139
140
141 final var p3 = p * p * p;
142 final var q2 = q * q;
143 final var d = p3 + q2;
144
145
146 final var sqrtD = Math.sqrt(d);
147 final var exp = 1.0 / 3.0;
148 final var v = Math.pow(sqrtD - q, exp) - Math.pow(sqrtD + q, exp);
149
150
151 final var g = 0.5 * (Math.sqrt(e2 + v) + e);
152
153
154 final var g2 = g * g;
155 final var t = Math.sqrt(g2 + (f - v * g) / (2.0 * g - e)) - g;
156
157
158 final var t2 = t * t;
159 final var latitude = Math.signum(z) * Math.atan((1.0 - t2) / (2.0 * t * Math.sqrt(1.0 - ecc2)));
160
161
162 final var height = (beta - EARTH_EQUATORIAL_RADIUS_WGS84 * t) * Math.cos(latitude)
163 + (z - Math.signum(z) * EARTH_EQUATORIAL_RADIUS_WGS84 * Math.sqrt(1.0 - ecc2))
164 * Math.sin(latitude);
165
166 try {
167
168 final var cen = CoordinateTransformation.ecefToNedMatrix(latitude, longitude);
169
170
171 final var vx = source.getVx();
172 final var vy = source.getVy();
173 final var vz = source.getVz();
174 final var vEbe = new Matrix(ECIorECEFFrame.NUM_VELOCITY_COORDINATES, 1);
175 vEbe.setElementAtIndex(0, vx);
176 vEbe.setElementAtIndex(1, vy);
177 vEbe.setElementAtIndex(2, vz);
178
179 final var vEbn = cen.multiplyAndReturnNew(vEbe);
180 final var vn = vEbn.getElementAtIndex(0);
181 final var ve = vEbn.getElementAtIndex(1);
182 final var vd = vEbn.getElementAtIndex(2);
183
184
185 final var cbe = source.getCoordinateTransformation().getMatrix();
186 cen.multiply(cbe);
187
188 final var c = new CoordinateTransformation(cen, FrameType.BODY_FRAME, FrameType.LOCAL_NAVIGATION_FRAME);
189
190
191 destination.setLatitude(latitude);
192 destination.setLongitude(longitude);
193 destination.setHeight(height);
194
195 destination.setVn(vn);
196 destination.setVe(ve);
197 destination.setVd(vd);
198
199 destination.setCoordinateTransformation(c);
200
201 } catch (final WrongSizeException | InvalidRotationMatrixException
202 | InvalidSourceAndDestinationFrameTypeException ignore) {
203
204 }
205 }
206 }