def c(points): x, y, z = p3d.enu2ecef(points[:, 0], points[:, 1], points[:, 2], fromCrs.lat, fromCrs.lon, fromCrs.alt) x, y, z = p3d.ecef2enu(x, y, z, toCrs.lat, toCrs.lon, toCrs.alt) return np.column_stack((x, y, z))
def test_scalar_aer_enu(xyz): """ verify we can handle the wide variety of input data type users might use """ enu = pm.ecef2enu(*xyz, 0, 90, -100) assert pm.enu2ecef(*enu, 0, 90, -100) == approx([0, A, 50])
def test_aer_enu(): xyz = pm.aer2ecef(*aer0, *lla0) enu = pm.aer2enu(*aer0) assert enu == approx(enu0) assert pm.aer2enu(*raer0, deg=False) == approx(enu0) with pytest.raises(ValueError): pm.aer2enu(aer0[0], aer0[1], -1) assert pm.enu2ecef(*enu, *lla0) == approx(xyz) assert pm.enu2ecef(*enu, *rlla0, deg=False) == approx(xyz) assert pm.ecef2enu(*xyz, *lla0) == approx(enu) assert pm.ecef2enu(*xyz, *rlla0, deg=False) == approx(enu)
def test_aer_enu(): xyz = pm.aer2ecef(*aer0, *lla0) enu = pm.aer2enu(*aer0) assert enu == approx(enu0) assert pm.aer2enu(*raer0, deg=False) == approx(enu0) with pytest.raises(ValueError): pm.aer2enu(aer0[0], aer0[1], -1) assert pm.enu2ecef(*enu, *lla0) == approx(xyz) assert pm.enu2ecef(*enu, *rlla0, deg=False) == approx(xyz) assert pm.ecef2enu(*xyz, *lla0) == approx(enu) assert pm.ecef2enu(*xyz, *rlla0, deg=False) == approx(enu)
def test_enu_ecef(enu, lla, xyz): x, y, z = pm.enu2ecef(*enu, *lla) assert x == approx(xyz[0]) assert y == approx(xyz[1]) assert z == approx(xyz[2]) rlla = (radians(lla[0]), radians(lla[1]), lla[2]) assert pm.enu2ecef(*enu, *rlla, deg=False) == approx(xyz) e, n, u = pm.ecef2enu(*xyz, *lla) assert e == approx(enu[0]) assert n == approx(enu[1]) assert u == approx(enu[2]) e, n, u = pm.ecef2enu(*xyz, *rlla, deg=False) assert e == approx(enu[0]) assert n == approx(enu[1]) assert u == approx(enu[2])
def test_scalar_enu(xyz): """ verify we can handle the wide variety of input data type users might use """ if isinstance(xyz[0], list): pytest.importorskip("numpy") enu = pm.ecef2enu(*xyz, 0, 90, -100) assert pm.enu2ecef(*enu, 0, 90, -100) == approx([0, A, 50])
def placemark_to_component(placemark, origin): point = placemark.geometry if origin is None: origin = np.array([point.y, point.x, point.z]) ecef_x, ecef_y, ecef_z = pm.geodetic2ecef(point.y, point.x, point.z) x, y, z = pm.ecef2enu(ecef_x, ecef_y, ecef_z, origin[0], origin[1], origin[2]) pos = np.array([x, y, z]) name = placemark.description return WellpadComponent(pos, name), origin
def unpack_deltas_cm( dx: Sequence[int], dy: Sequence[int], dz: Sequence[int], g: GeoFrame # type: ignore ) -> Tuple[np.ndarray, np.ndarray, np.ndarray]: x = np.cumsum(np.asarray(dx) / 100) y = np.cumsum(np.asarray(dy) / 100) z = np.cumsum(np.asarray(dz) / 100) x, y, z = pm.enu2ecef(x, y, z, g.origin.lat_e7 * 1e-7, g.origin.lng_e7 * 1e-7, 0) # type: ignore return pm.ecef2enu(x, y, z, lat, lon, 0) # type:ignore
def ecef2enu(self, M, origin, scene_origin = np.array([4.40145e+06, 597011, 4.56599e+06])): """M is a row-wise atrix of 3D ecef points origin is a vector in ecef defining the origin for ENU scene_origin will be added to both origin and each point in M before the transformation """ ell = pm3d.EarthEllipsoid(model='wgs84') lat, lon, alt = pm3d.ecef2geodetic(origin[0] + scene_origin[0], origin[1] + scene_origin[1], origin[2] + scene_origin[2], ell) res = [] for i in range(M.shape[0]): e,n,u = pm3d.ecef2enu(M[i,0] + scene_origin[0], M[i,1] + scene_origin[1], M[i,2] + scene_origin[2], lat, lon, alt, ell) res.append(np.array([e,n,u])) return np.array(res)
def test_enu_ecef(enu, lla, xyz): x, y, z = pm.enu2ecef(*enu, *lla) assert x == approx(xyz[0]) assert y == approx(xyz[1]) assert z == approx(xyz[2]) assert isinstance(x, float) assert isinstance(y, float) assert isinstance(z, float) rlla = (radians(lla[0]), radians(lla[1]), lla[2]) assert pm.enu2ecef(*enu, *rlla, deg=False) == approx(xyz) e, n, u = pm.ecef2enu(*xyz, *lla) assert e == approx(enu[0]) assert n == approx(enu[1]) assert u == approx(enu[2]) assert isinstance(e, float) assert isinstance(n, float) assert isinstance(u, float) e, n, u = pm.ecef2enu(*xyz, *rlla, deg=False) assert e == approx(enu[0]) assert n == approx(enu[1]) assert u == approx(enu[2])
def convert_point(point, config): """ Convert Point to geodetic coordinates to ECEF coordinates to ENU coordinates and return camera perspective coordinates """ # Convert point geodetic coordinates (lat, lon, alt) to ECEF coordinates (x, y, z) x_ecef, y_ecef, z_ecef = pymap3d.geodetic2ecef(point[0], point[1], point[2]) # Convert point ECEF coordinates (x, y, z) to ENU coordinates (East, North, Up) # pymap3d.ecef2enuv(x, y, z, lat0, lon0, h0) where 0 is camera coordinates u_east, v_north, w_up = pymap3d.ecef2enu(x_ecef, y_ecef, z_ecef, config[0], config[1], config[2]) # Convert ENU coordinates to camera perspective camera_x, camera_y, camera_z = enu_to_camera_coords( u_east, v_north, w_up, config) return camera_x, camera_y, camera_z
def rasterize(self, history_frames: np.ndarray, history_agents: List[np.ndarray], agent: Optional[np.ndarray] = None) -> np.ndarray: if agent is None: ego_translation = history_frames[0]["ego_translation"] ego_yaw = -rotation33_as_yaw(history_frames[0]["ego_rotation"]) else: ego_translation = np.append( agent["centroid"], history_frames[0]["ego_translation"][-1]) ego_yaw = -agent["yaw"] # move pose to enu frame the semantic map is stored in xyz = transform_point(ego_translation, self.pose_to_ecef) x, y, z = pm.ecef2enu(xyz[0], xyz[1], xyz[2], self.semantic_map["lat"], self.semantic_map["lon"], 0) # Apply ego_center offset # get_sat_image_crop_scaled crops around a point. # That point is ego_translation iff ego_center is [0.5, 0.5] # if not, we can compute by how much we need to translate in meters in the two directions and rotate the vector ego_offset = (0.5, 0.5) - np.asarray(self.ego_center) ego_offset_meters = np.asarray(self.pixel_size) * np.asarray( self.raster_size) * ego_offset rot_m = np.asarray([[np.cos(ego_yaw), np.sin(ego_yaw)], [-np.sin(ego_yaw), np.cos(ego_yaw)]]) ego_offset_meters = rot_m @ ego_offset_meters sem_im = render_semantic_map( self.semantic_map, x + ego_offset_meters[0], y + ego_offset_meters[1], ego_yaw, raster_size=self.raster_size, pixel_size=self.pixel_size, ) return sem_im.astype(np.float32) / 255
def get_data(path): lat0 = None lon0 = None h0 = 0 filepath = [] for root, dirs, files in os.walk(path): for filename in sorted( filter(lambda x: os.path.splitext(x)[1].lower() == '.jpg', files)): filepath.append(os.path.join(root, filename)) for im in filepath: pitch = 0 yaw = 0 roll = 0 lat, lon, alt = get_data_1(im) if lat0 is None: lat0 = lat lon0 = lon x, y, z = geodetic2ecef(lat, lon, alt) x, y, z = ecef2enu(x, y, z, lat0, lon0, h0) yield filename, '{:f}'.format(x), '{:f}'.format(y), '{:f}'.format( z), yaw, pitch, roll
def get_data(path): lat0 = None lon0 = None h0 = 0 for root, dirs, files in os.walk(path): for filename in sorted(filter(lambda x: os.path.splitext(x)[1].lower() == '.jpg', files)): filepath = os.path.join(root, filename) with Image.open(filepath) as im: for segment, content in im.applist: marker, body = content.split('\x00', 1) if segment == 'APP1' and marker == 'http://ns.adobe.com/xap/1.0/': soup = BeautifulSoup(body, features='html.parser') description = soup.find('x:xmpmeta').find('rdf:rdf').find('rdf:description') pitch = float(description['drone-dji:gimbalpitchdegree']) + 90 yaw = float(description['drone-dji:gimbalyawdegree']) roll = float(description['drone-dji:gimbalrolldegree']) alt = float(description['drone-dji:relativealtitude']) lat, lon = get_gps_coords(im) if lat0 is None: lat0 = lat lon0 = lon x, y, z = geodetic2ecef(lat, lon, alt) x, y, z = ecef2enu(x, y, z, lat0, lon0, h0) yield filename, '{:f}'.format(x), '{:f}'.format(y), '{:f}'.format(z), yaw, pitch, roll
def import_inflight_measurements(self, filename): print('running') csv = pd.read_csv(filename) col_renames = { 'GPS_Time(s)': 'time', 'Wind_Velocity(m/s)': 'wind_speeds', 'Wind_Direction(deg)': 'wind_directions', 'CH4(vmr)': 'ch4_conc', 'Latitude(DD)': 'lat', 'Longitude(DD)': 'lon', 'LiDAR_Alt(m)': 'alt' } csv = csv.rename(columns=col_renames) ecef_x, ecef_y, ecef_z = pm.geodetic2ecef(csv['lat'], csv['lon'], csv['alt']) if self.origin is None: self.origin = np.array( [csv['lat'][0], csv['lon'][0], csv['alt'][0]]) csv['x'], csv['y'], csv['z'] = pm.ecef2enu(ecef_x, ecef_y, ecef_z, self.origin[0], self.origin[1], self.origin[2]) self.inflight_data = csv
def test_ecefenu(): assert_allclose(pm.aer2ecef(taz, tel, tsrange, tlat, tlon, talt), (a2x, a2y, a2z), rtol=0.01, err_msg='aer2ecef: {}'.format( pm.aer2ecef(taz, tel, tsrange, tlat, tlon, talt))) assert_allclose(pm.aer2enu(taz, tel, tsrange), (a2e, a2n, a2u), rtol=0.01, err_msg='aer2enu: ' + str(pm.aer2enu(taz, tel, tsrange))) assert_allclose(pm.aer2ned(taz, tel, tsrange), (a2n, a2e, -a2u), rtol=0.01, err_msg='aer2ned: ' + str(pm.aer2ned(taz, tel, tsrange))) assert_allclose(pm.ecef2enu(tx, ty, tz, tlat, tlon, talt), (e2e, e2n, e2u), rtol=0.01, err_msg='ecef2enu: {}'.format( pm.ecef2enu(tx, ty, tz, tlat, tlon, talt))) assert_allclose(pm.ecef2enuv(vx, vy, vz, tlat, tlon), (ve, vn, vu)) assert_allclose(pm.ecef2ned(tx, ty, tz, tlat, tlon, talt), (e2n, e2e, -e2u), rtol=0.01, err_msg='ecef2ned: {}'.format( pm.ecef2enu(tx, ty, tz, tlat, tlon, talt))) assert_allclose(pm.ecef2nedv(vx, vy, vz, tlat, tlon), (vn, ve, -vu)) assert_allclose(pm.aer2geodetic(taz, tel, tsrange, tlat, tlon, talt), (a2la, a2lo, a2a), rtol=0.01, err_msg='aer2geodetic {}'.format( pm.aer2geodetic(taz, tel, tsrange, tlat, tlon, talt))) assert_allclose(pm.ecef2aer(tx, ty, tz, tlat, tlon, talt), (ec2az, ec2el, ec2rn), rtol=0.01, err_msg='ecef2aer {}'.format( pm.ecef2aer(a2x, a2y, a2z, tlat, tlon, talt))) #%% assert_allclose(pm.enu2aer(te, tn, tu), (e2az, e2el, e2rn), rtol=0.01, err_msg='enu2aer: ' + str(pm.enu2aer(te, tn, tu))) assert_allclose(pm.ned2aer(tn, te, -tu), (e2az, e2el, e2rn), rtol=0.01, err_msg='enu2aer: ' + str(pm.enu2aer(te, tn, tu))) assert_allclose(pm.enu2geodetic(te, tn, tu, tlat, tlon, talt), (lat2, lon2, alt2), rtol=0.01, err_msg='enu2geodetic: ' + str(pm.enu2geodetic(te, tn, tu, tlat, tlon, talt))) assert_allclose(pm.ned2geodetic(tn, te, -tu, tlat, tlon, talt), (lat2, lon2, alt2), rtol=0.01, err_msg='enu2geodetic: ' + str(pm.enu2geodetic(te, tn, tu, tlat, tlon, talt))) assert_allclose(pm.enu2ecef(te, tn, tu, tlat, tlon, talt), (e2x, e2y, e2z), rtol=0.01, err_msg='enu2ecef: ' + str(pm.enu2ecef(te, tn, tu, tlat, tlon, talt))) assert_allclose( pm.ned2ecef(tn, te, -tu, tlat, tlon, talt), (e2x, e2y, e2z), rtol=0.01, err_msg='ned2ecef: ' + str(pm.ned2ecef(tn, te, -tu, tlat, tlon, talt)))
def terminate(t, X): return pm.ecef2enu(*X[:3], phi0, lambda0, h0)[2] < 0.0
# from __future__ import absolute_import import pymap3d as pm # print(pm.__file__) # from pm import geodetic2ecef # from pymap3d import geodetic2ecef # import pymap3d x, y, z = pm.geodetic2ecef(-25.1, -49.5, 978.2) wgs = pm.Ellipsoid() e, n, u = pm.ecef2enu(x, y, z, -25.0, -49.0, wgs, True) # print([x,y,z]) print([e, n, u]) # def main(): # x,y,z = pm.geodetic2ecef(-25.1,-49.5,978.2) # # x,y,z = pymap3d.geodetic2ecef(-25.1,-49.5,978.2) # print([x,y,z]) # if __name__ == "__main__": # main()
minute = '17' second = '8' #ECEF TO ENU import pymap3d as pm tilecoordsx = [] tilecoordsy = [] coordslist = np.loadtxt('ECEF_SWAN.txt') lat = 13.6183 long = 77.5146 h = 691.09 zeropoint = pm.ecef2enu(coordslist[0, 0], coordslist[0, 1], coordslist[0, 2], lat, long, h, ell=None, deg=True) for i in range(np.shape(coordslist)[0]): converted = pm.ecef2enu(coordslist[i, 0], coordslist[i, 1], coordslist[i, 2], lat, long, h, ell=None, deg=True) tilecoordsx.append(converted[0] - zeropoint[0]) tilecoordsy.append(converted[1] - zeropoint[1])
f = open(file_name, 'r') line = f.readline() while 1: line = f.readline() if line: if str(line[0:1]) == '%': continue x = float(line[25:38]) y = float(line[40:53]) z = float(line[56:68]) ecef_x.append(x) ecef_y.append(y) ecef_z.append(z) l1, l2, h = pm.ecef2geodetic(x, y, z) e, n, u = pm.ecef2enu(x, y, z, True_Lat, True_Lon, True_Hei) E.append(e) N.append(n) U.append(u) error = getDistance(l1, l2, True_Lat, True_Lon) Distance_2Derror.append(error * 1000) #to m else: break f.close() #error=getDistance(25.060835, 121.544242,True_Lat, True_Lon) #Distance_2Derror.append(error) plot_enu(E, N, U) plot_cdf(Distance_2Derror)
def test_geodetic(self): if pyproj: ecef = pyproj.Proj(proj='geocent', ellps='WGS84', datum='WGS84') lla = pyproj.Proj(proj='latlong', ellps='WGS84', datum='WGS84') x1, y1, z1 = pm.geodetic2ecef(tlat, tlon, talt) assert_allclose( pm.geodetic2ecef(radians(tlat), radians(tlon), talt, deg=False), (x1, y1, z1)) assert_allclose((x1, y1, z1), (x0, y0, z0), err_msg='geodetic2ecef') assert_allclose(pm.ecef2geodetic(x1, y1, z1), (tlat, tlon, talt), err_msg='ecef2geodetic') if pyproj: assert_allclose(pyproj.transform(lla, ecef, tlon, tlat, talt), (x1, y1, z1)) assert_allclose(pyproj.transform(ecef, lla, x1, y1, z1), (tlon, tlat, talt)) lat2, lon2, alt2 = pm.aer2geodetic(taz, tel, tsrange, tlat, tlon, talt) assert_allclose((lat2, lon2, alt2), (lat1, lon1, alt1), err_msg='aer2geodetic') assert_allclose(pm.geodetic2aer(lat2, lon2, alt2, tlat, tlon, talt), (taz, tel, tsrange), err_msg='geodetic2aer') x2, y2, z2 = pm.aer2ecef(taz, tel, tsrange, tlat, tlon, talt) assert_allclose( pm.aer2ecef(radians(taz), radians(tel), tsrange, radians(tlat), radians(tlon), talt, deg=False), (a2x, a2y, a2z)) assert_allclose((x2, y2, z2), (a2x, a2y, a2z), err_msg='aer2ecef') assert_allclose(pm.ecef2aer(x2, y2, z2, tlat, tlon, talt), (taz, tel, tsrange), err_msg='ecef2aer') e1, n1, u1 = pm.aer2enu(taz, tel, tsrange) assert_allclose((e1, n1, u1), (e0, n0, u0), err_msg='aer2enu') assert_allclose(pm.aer2ned(taz, tel, tsrange), (n0, e0, -u0), err_msg='aer2ned') assert_allclose(pm.enu2aer(e1, n1, u1), (taz, tel, tsrange), err_msg='enu2aer') assert_allclose(pm.ned2aer(n1, e1, -u1), (taz, tel, tsrange), err_msg='ned2aer') assert_allclose(pm.enu2ecef(e1, n1, u1, tlat, tlon, talt), (x2, y2, z2), err_msg='enu2ecef') assert_allclose(pm.ecef2enu(x2, y2, z2, tlat, tlon, talt), (e1, n1, u1), err_msg='ecef2enu') assert_allclose(pm.ecef2ned(x2, y2, z2, tlat, tlon, talt), (n1, e1, -u1), err_msg='ecef2ned') assert_allclose(pm.ned2ecef(n1, e1, -u1, tlat, tlon, talt), (x2, y2, z2), err_msg='ned2ecef') # %% assert_allclose(pm.ecef2enuv(vx, vy, vz, tlat, tlon), (ve, vn, vu)) assert_allclose(pm.ecef2nedv(vx, vy, vz, tlat, tlon), (vn, ve, -vu)) #%% e3, n3, u3 = pm.geodetic2enu(lat2, lon2, alt2, tlat, tlon, talt) assert_allclose(pm.geodetic2ned(lat2, lon2, alt2, tlat, tlon, talt), (n3, e3, -u3)) assert_allclose(pm.enu2geodetic(e3, n3, u3, tlat, tlon, talt), (lat2, lon2, alt2), err_msg='enu2geodetic') assert_allclose(pm.ned2geodetic(n3, e3, -u3, tlat, tlon, talt), (lat2, lon2, alt2), err_msg='ned2geodetic')
def test_3d_enu(): np = pytest.importorskip("numpy") xyz = (np.atleast_3d(0), np.atleast_3d(A), np.atleast_3d(50)) enu = pm.ecef2enu(*xyz, 0, 90, -100) assert pm.enu2ecef(*enu, 0, 90, -100) == approx([0, A, 50])
t, state0, terminate=terminate) t, soln = dsolve(partial(rhs, T=T_0, omega=np.zeros_like(Omega)), t, state0, terminate=terminate) pos_magnus, dpos_magnus = np.vsplit(soln_magnus, 2) pos, dpos = np.vsplit(soln, 2) pos_enu_magnus = np.zeros_like(pos_magnus).T pos_enu = np.zeros_like(pos).T for i, coord in enumerate(tqdm(pos.T)): pos_enu[i] = pm.ecef2enu(*coord, phi0, lambda0, h0) for i, coord_magnus in enumerate(tqdm(pos_magnus.T)): pos_enu_magnus[i] = pm.ecef2enu(*coord_magnus, phi0, lambda0, h0) pos_enu = pos_enu.T pos_enu_magnus = pos_enu_magnus.T print( f'\n\nDisplacement (East, North, Up): {(pos_enu_magnus[:,-1]-pos_enu_magnus[:,0])/1000} [km]' ) # ### Plotting # In[180]:
def test_geodetic(self): if pyproj: ecef = pyproj.Proj(proj='geocent', ellps='WGS84', datum='WGS84') lla = pyproj.Proj(proj='latlong', ellps='WGS84', datum='WGS84') xyz1 = pm.geodetic2ecef(*lla0) assert_allclose(pm.geodetic2ecef(*rlla0, deg=False), xyz1, err_msg='geodetic2ecef: rad') assert_allclose(xyz1, xyz0, err_msg='geodetic2ecef: deg') assert_allclose(pm.ecef2geodetic(*xyz1), lla0, err_msg='ecef2geodetic: deg') assert_allclose(pm.ecef2geodetic(*xyz1, deg=False), rlla0, err_msg='ecef2geodetic: rad') if pyproj: assert_allclose( pyproj.transform(lla, ecef, lla0[1], lla0[0], lla0[2]), xyz1) assert_allclose(pyproj.transform(ecef, lla, *xyz1), (lla0[1], lla0[0], lla0[2])) lla2 = pm.aer2geodetic(*aer0, *lla0) rlla2 = pm.aer2geodetic(*raer0, *rlla0, deg=False) assert_allclose(lla2, lla1, err_msg='aer2geodetic: deg') assert_allclose(rlla2, rlla1, err_msg='aer2geodetic:rad') assert_allclose(pm.geodetic2aer(*lla2, *lla0), aer0, err_msg='geodetic2aer: deg') assert_allclose(pm.geodetic2aer(*rlla2, *rlla0, deg=False), raer0, err_msg='geodetic2aer: rad') # %% aer-ecef xyz2 = pm.aer2ecef(*aer0, *lla0) assert_allclose(pm.aer2ecef(*raer0, *rlla0, deg=False), axyz0, err_msg='aer2ecef:rad') assert_allclose(xyz2, axyz0, err_msg='aer2ecef: deg') assert_allclose(pm.ecef2aer(*xyz2, *lla0), aer0, err_msg='ecef2aer:deg') assert_allclose(pm.ecef2aer(*xyz2, *rlla0, deg=False), raer0, err_msg='ecef2aer:rad') # %% aer-enu enu1 = pm.aer2enu(*aer0) ned1 = (enu1[1], enu1[0], -enu1[2]) assert_allclose(enu1, enu0, err_msg='aer2enu: deg') assert_allclose(pm.aer2enu(*raer0, deg=False), enu0, err_msg='aer2enu: rad') assert_allclose(pm.aer2ned(*aer0), ned0, err_msg='aer2ned') assert_allclose(pm.enu2aer(*enu1), aer0, err_msg='enu2aer: deg') assert_allclose(pm.enu2aer(*enu1, deg=False), raer0, err_msg='enu2aer: rad') assert_allclose(pm.ned2aer(*ned1), aer0, err_msg='ned2aer') # %% enu-ecef assert_allclose(pm.enu2ecef(*enu1, *lla0), xyz2, err_msg='enu2ecef: deg') assert_allclose(pm.enu2ecef(*enu1, *rlla0, deg=False), xyz2, err_msg='enu2ecef: rad') assert_allclose(pm.ecef2enu(*xyz2, *lla0), enu1, err_msg='ecef2enu:deg') assert_allclose(pm.ecef2enu(*xyz2, *rlla0, deg=False), enu1, err_msg='ecef2enu:rad') assert_allclose(pm.ecef2ned(*xyz2, *lla0), ned1, err_msg='ecef2ned') assert_allclose(pm.ned2ecef(*ned1, *lla0), xyz2, err_msg='ned2ecef') # %% assert_allclose(pm.ecef2enuv(vx, vy, vz, *lla0[:2]), (ve, vn, vu)) assert_allclose(pm.ecef2nedv(vx, vy, vz, *lla0[:2]), (vn, ve, -vu)) # %% enu3 = pm.geodetic2enu(*lla2, *lla0) ned3 = (enu3[1], enu3[0], -enu3[2]) assert_allclose(pm.geodetic2ned(*lla2, *lla0), ned3, err_msg='geodetic2ned: deg') assert_allclose(pm.enu2geodetic(*enu3, *lla0), lla2, err_msg='enu2geodetic') assert_allclose(pm.ned2geodetic(*ned3, *lla0), lla2, err_msg='ned2geodetic')