@@ -235,7 +235,7 @@ pub fn ll2utm(ll_vec: &Vector2<f64>, ellipsoid: &geo_ellipsoid::geo_ellipsoid) -
235
235
ret_utm
236
236
}
237
237
238
- /// Converts 3-d LLA origin coordinates plus 3-d LLA coordinates and an ellipsoid to local NED cartesian coordinates
238
+ /// Converts 3-d LLA origin coordinates plus 3-d LLA coordinates and an ellipsoid to 3-d local NED cartesian coordinates
239
239
///
240
240
/// # Arguments
241
241
///
@@ -256,7 +256,7 @@ pub fn lla2ned(lla_origin: &Vector3<f64>, lla_vec: &Vector3<f64>, ellipsoid: &ge
256
256
ned_rot * ( actual - orig)
257
257
}
258
258
259
- /// Converts 3-d LLA origin coordinates plus 3-d LLA coordinates and an ellipsoid to local ENU cartesian coordinates
259
+ /// Converts 3-d LLA origin coordinates plus 3-d LLA coordinates and an ellipsoid to 3-d local ENU cartesian coordinates
260
260
///
261
261
/// # Arguments
262
262
///
@@ -277,6 +277,52 @@ pub fn lla2enu(lla_origin: &Vector3<f64>, lla_vec: &Vector3<f64>, ellipsoid: &ge
277
277
enu_rot * ( actual - orig)
278
278
}
279
279
280
+ /// Converts 3-d local cartesian NED coordinates plus 3-d LLA origin coordinates and an ellipsoid to 3-d LLA coordinates
281
+ ///
282
+ /// # Arguments
283
+ ///
284
+ /// * `lla_origin` - Vector3 reference to the LLA origin vector (lat, long, alt) (radians, radians, meters)
285
+ /// * `ned_vec` - Vector3 reference to the local NED cartesian vector (x, y, z)
286
+ /// * `ellipsoid` - geo_ellipsoid reference to the ellipsoid
287
+ ///
288
+ /// # Return Value
289
+ ///
290
+ /// * `nalgebra::Vector3<f64>` - (lat, long, alt) (radians, radians, meters)
291
+ ///
292
+ pub fn ned2lla ( lla_origin : & Vector3 < f64 > , ned_vec : & Vector3 < f64 > , ellipsoid : & geo_ellipsoid:: geo_ellipsoid ) -> Vector3 < f64 > {
293
+ let orig = lla2ecef ( lla_origin, ellipsoid) ;
294
+ let ned_rot = Matrix3 :: new ( -lla_origin. x . sin ( ) * lla_origin. y . cos ( ) , -lla_origin. y . sin ( ) , -lla_origin. x . cos ( ) * lla_origin. y . cos ( ) ,
295
+ -lla_origin. x . sin ( ) * lla_origin. y . sin ( ) , lla_origin. y . cos ( ) , -lla_origin. x . cos ( ) * lla_origin. y . sin ( ) ,
296
+ lla_origin. x . cos ( ) , 0.0 , -lla_origin. x . sin ( ) ) ;
297
+ let actual = ned_rot * ned_vec;
298
+ let total = actual + orig;
299
+ let ret_vec = ecef2lla ( & total, ellipsoid) ;
300
+ ret_vec
301
+ }
302
+
303
+ /// Converts 3-d local cartesian ENU coordinates plus 3-d LLA origin coordinates and an ellipsoid to 3-d LLA coordinates
304
+ ///
305
+ /// # Arguments
306
+ ///
307
+ /// * `lla_origin` - Vector3 reference to the LLA origin vector (lat, long, alt) (radians, radians, meters)
308
+ /// * `enu_vec` - Vector3 reference to the local NED cartesian vector (x, y, z)
309
+ /// * `ellipsoid` - geo_ellipsoid reference to the ellipsoid
310
+ ///
311
+ /// # Return Value
312
+ ///
313
+ /// * `nalgebra::Vector3<f64>` - (lat, long, alt) (radians, radians, meters)
314
+ ///
315
+ pub fn enu2lla ( lla_origin : & Vector3 < f64 > , enu_vec : & Vector3 < f64 > , ellipsoid : & geo_ellipsoid:: geo_ellipsoid ) -> Vector3 < f64 > {
316
+ let orig = lla2ecef ( lla_origin, ellipsoid) ;
317
+ let enu_rot = Matrix3 :: new ( -lla_origin. y . sin ( ) , -lla_origin. y . cos ( ) * lla_origin. x . sin ( ) , lla_origin. y . cos ( ) * lla_origin. x . cos ( ) ,
318
+ lla_origin. y . cos ( ) , -lla_origin. y . sin ( ) * lla_origin. x . sin ( ) , lla_origin. y . sin ( ) * lla_origin. x . cos ( ) ,
319
+ 0.0 , lla_origin. x . cos ( ) , lla_origin. x . sin ( ) ) ;
320
+ let actual = enu_rot * enu_vec;
321
+ let total = actual + orig;
322
+ let ret_vec = ecef2lla ( & total, ellipsoid) ;
323
+ ret_vec
324
+ }
325
+
280
326
//Unit tests
281
327
#[ cfg( test) ]
282
328
mod tests {
@@ -317,9 +363,9 @@ mod tests {
317
363
let test_x = 4201570.9492264455 ;
318
364
let test_y = 172588.3449531975 ;
319
365
let test_z = 4780835.4317144295 ;
320
- assert ! ( ecef_vec. x. approx_eq_ratio( & test_x, 0.0000000001 ) ) ;
321
- assert ! ( ecef_vec. y. approx_eq_ratio( & test_y, 0.0000000001 ) ) ;
322
- assert ! ( ecef_vec. z. approx_eq_ratio( & test_z, 0.0000000001 ) ) ;
366
+ assert ! ( ecef_vec. x. approx_eq_ratio( & test_x, 0.0000000000001 ) ) ;
367
+ assert ! ( ecef_vec. y. approx_eq_ratio( & test_y, 0.0000000000001 ) ) ;
368
+ assert ! ( ecef_vec. z. approx_eq_ratio( & test_z, 0.0000000000001 ) ) ;
323
369
}
324
370
#[ test]
325
371
fn test_ecef2lla ( ) {
@@ -331,9 +377,9 @@ mod tests {
331
377
let test_x = 0.8527087756759584 ;
332
378
let test_y = 0.04105401863784606 ;
333
379
let test_z = 1000.000000000 ;
334
- assert ! ( lla_vec. x. approx_eq_ratio( & test_x, 0.0000000001 ) ) ;
335
- assert ! ( lla_vec. y. approx_eq_ratio( & test_y, 0.0000000001 ) ) ;
336
- assert ! ( lla_vec. z. approx_eq_ratio( & test_z, 0.0000000001 ) ) ;
380
+ assert ! ( lla_vec. x. approx_eq_ratio( & test_x, 0.0000000000001 ) ) ;
381
+ assert ! ( lla_vec. y. approx_eq_ratio( & test_y, 0.0000000000001 ) ) ;
382
+ assert ! ( lla_vec. z. approx_eq_ratio( & test_z, 0.00001 ) ) ;
337
383
}
338
384
#[ test]
339
385
fn test_ll2utm ( ) {
@@ -351,10 +397,10 @@ mod tests {
351
397
352
398
assert_eq ! ( utm. get_zone( ) , test_zone) ;
353
399
assert_eq ! ( utm. get_hem( ) , test_hem) ;
354
- assert ! ( utm. get_easting( ) . approx_eq_ratio( & test_easting, 0.0000000001 ) ) ;
355
- assert ! ( utm. get_northing( ) . approx_eq_ratio( & test_northing, 0.0000000001 ) ) ;
356
- assert ! ( utm. get_convergence( ) . approx_eq_ratio( & test_convergence, 0.0000000001 ) ) ;
357
- assert ! ( utm. get_scale( ) . approx_eq_ratio( & test_scale, 0.0000000001 ) ) ;
400
+ assert ! ( utm. get_easting( ) . approx_eq_ratio( & test_easting, 0.0000000000001 ) ) ;
401
+ assert ! ( utm. get_northing( ) . approx_eq_ratio( & test_northing, 0.0000000000001 ) ) ;
402
+ assert ! ( utm. get_convergence( ) . approx_eq_ratio( & test_convergence, 0.0000000000001 ) ) ;
403
+ assert ! ( utm. get_scale( ) . approx_eq_ratio( & test_scale, 0.0000000000001 ) ) ;
358
404
}
359
405
#[ test]
360
406
fn test_lla2ned ( ) {
@@ -364,9 +410,9 @@ mod tests {
364
410
let lla_vec: Vector3 < f64 > = Vector3 :: new ( 0.8527087756759584 , 0.042799347889836060477 , 1000.000000000 ) ;
365
411
let ned_vec = lla2ned ( & lla_orig_vec, & lla_vec, & ellipsoid) ;
366
412
367
- let test_x = 4.823198223193799 ;
368
- let test_y = 7339.305041782073 ;
369
- let test_z = 4.2139798876589225 ;
413
+ let test_x = 4.8231982231937990945 ;
414
+ let test_y = 7339.3050417820732036 ;
415
+ let test_z = 4.2139798876589225073 ;
370
416
assert ! ( ned_vec. x. approx_eq_ulps( & test_x, 2 ) ) ;
371
417
assert ! ( ned_vec. y. approx_eq_ulps( & test_y, 2 ) ) ;
372
418
assert ! ( ned_vec. z. approx_eq_ulps( & test_z, 2 ) ) ;
@@ -378,12 +424,42 @@ mod tests {
378
424
let lla_orig_vec: Vector3 < f64 > = Vector3 :: new ( 0.8527087756759584 , 0.04105401863784606 , 1000.000000000 ) ;
379
425
let lla_vec: Vector3 < f64 > = Vector3 :: new ( 0.8527087756759584 , 0.042799347889836060477 , 1000.000000000 ) ;
380
426
let enu_vec = lla2enu ( & lla_orig_vec, & lla_vec, & ellipsoid) ;
381
-
382
- let test_x = 7339.305041782073 ;
383
- let test_y = 4.823198223193799 ;
384
- let test_z = -4.2139798876589225 ;
385
- assert ! ( enu_vec. x. approx_eq_ulps( & test_x, 2 ) ) ;
386
- assert ! ( enu_vec. y. approx_eq_ulps( & test_y, 2 ) ) ;
387
- assert ! ( enu_vec. z. approx_eq_ulps( & test_z, 2 ) ) ;
427
+
428
+ let test_x = 7339.3050417820732036 ;
429
+ let test_y = 4.8231982231937990945 ;
430
+ let test_z = -4.2139798876589225073 ;
431
+ assert ! ( enu_vec. x. approx_eq_ratio( & test_x, 0.0000000000001 ) ) ;
432
+ assert ! ( enu_vec. y. approx_eq_ratio( & test_y, 0.0000000000001 ) ) ;
433
+ assert ! ( enu_vec. z. approx_eq_ratio( & test_z, 0.0000000000001 ) ) ;
434
+ }
435
+ #[ test]
436
+ fn test_ned2lla ( ) {
437
+ let ellipsoid = geo_ellipsoid:: geo_ellipsoid:: new ( geo_ellipsoid:: WGS84_SEMI_MAJOR_AXIS_METERS ,
438
+ geo_ellipsoid:: WGS84_FLATTENING ) ;
439
+ let lla_orig_vec: Vector3 < f64 > = Vector3 :: new ( 0.8527087756759584 , 0.04105401863784606 , 1000.000000000 ) ;
440
+ let ned_vec: Vector3 < f64 > = Vector3 :: new ( 4.8231982231937990945 , 7339.3050417820732036 , 4.2139798876589225073 ) ;
441
+ let lla_vec = ned2lla ( & lla_orig_vec, & ned_vec, & ellipsoid) ;
442
+
443
+ let test_x = 0.8527087756759584 ;
444
+ let test_y = 0.042799347889836060477 ;
445
+ let test_z = 1000.000000000 ;
446
+ assert ! ( lla_vec. x. approx_eq_ratio( & test_x, 0.0000000000001 ) ) ;
447
+ assert ! ( lla_vec. y. approx_eq_ratio( & test_y, 0.0000000000001 ) ) ;
448
+ assert ! ( lla_vec. z. approx_eq_ratio( & test_z, 0.00001 ) ) ;
449
+ }
450
+ #[ test]
451
+ fn test_enu2lla ( ) {
452
+ let ellipsoid = geo_ellipsoid:: geo_ellipsoid:: new ( geo_ellipsoid:: WGS84_SEMI_MAJOR_AXIS_METERS ,
453
+ geo_ellipsoid:: WGS84_FLATTENING ) ;
454
+ let lla_orig_vec: Vector3 < f64 > = Vector3 :: new ( 0.8527087756759584 , 0.04105401863784606 , 1000.000000000 ) ;
455
+ let enu_vec: Vector3 < f64 > = Vector3 :: new ( 7339.3050417820732036 , 4.8231982231937990945 , -4.2139798876589225073 ) ;
456
+ let lla_vec = enu2lla ( & lla_orig_vec, & enu_vec, & ellipsoid) ;
457
+
458
+ let test_x = 0.8527087756759584 ;
459
+ let test_y = 0.042799347889836060477 ;
460
+ let test_z = 1000.000000000 ;
461
+ assert ! ( lla_vec. x. approx_eq_ratio( & test_x, 0.0000000000001 ) ) ;
462
+ assert ! ( lla_vec. y. approx_eq_ratio( & test_y, 0.0000000000001 ) ) ;
463
+ assert ! ( lla_vec. z. approx_eq_ratio( & test_z, 0.00001 ) ) ;
388
464
}
389
465
}
0 commit comments