diff --git a/docs/pvcollada_coordinate_transformation_with_diagram.md b/docs/pvcollada_coordinate_transformation_with_diagram.md index 6242da2..e7ffccc 100644 --- a/docs/pvcollada_coordinate_transformation_with_diagram.md +++ b/docs/pvcollada_coordinate_transformation_with_diagram.md @@ -1,5 +1,5 @@ -# PVCollada Coordinate Transformation Guide +# Guide to Coordinates and Coordinate Transformations ## ENU Coordinate Frame @@ -14,44 +14,31 @@ latitude, longitude and altitude stored in the COLLADA document. ## Example Geometry -Cube definition in local coordinates: +We'll illustrate coordinates and transformations using a cube defined in PVCollada's local coordinates: - lower corner `(1,1,1)` - size `(3,2,1)` -Assume that the topocentric coordinate origin is at the this geolocation: +![PVCollada cube](pvcollada_cube_diagram.png) + + +## From Local ENU to Geographic Coordinates + +Assume that the topocentric coordinate origin is at this geolocation in the WGS84 datum: - Albuquerque, NM, USA - Latitude `35.0845` - Longitude `-106.651` - Altitude `1619` -- Projection `EPSG:32613` - -## Diagram - -![PVCollada cube](pvcollada_cube_diagram.png) - -The diagram shows the cube in the local coordinate system along with the ENU axes. +- Projection `EPSG:4326` -## Computed Geographic Coordinates +EPSG:4326 is the identifier for the WGS-84 geographic coordinate system. -The geocoordinate of the cube are computed using the python library pymap3d. +The WGS-84 geocoordinates of the cube can be computed using either the pymap3d or pyproj. -| x | y | z | latitude | longitude | altitude | -|-----------:|-----------:|-----------:|------------:|--------------:|--------------:| -| 1.00000000 | 1.00000000 | 1.00000000 | 35.08450901 | -106.65098904 | 1620.00000016 | -| 4.00000000 | 1.00000000 | 1.00000000 | 35.08453605 | -106.65098904 | 1620.00000134 | -| 1.00000000 | 3.00000000 | 1.00000000 | 35.08450901 | -106.65096711 | 1620.00000078 | -| 4.00000000 | 3.00000000 | 1.00000000 | 35.08453605 | -106.65096711 | 1620.00000196 | -| 1.00000000 | 1.00000000 | 2.00000000 | 35.08450901 | -106.65098904 | 1621.00000016 | -| 4.00000000 | 1.00000000 | 2.00000000 | 35.08453605 | -106.65098904 | 1621.00000134 | -| 1.00000000 | 3.00000000 | 2.00000000 | 35.08450901 | -106.65096711 | 1621.00000078 | -| 4.00000000 | 3.00000000 | 2.00000000 | 35.08453605 | -106.65096711 | 1621.00000196 | - -## Python Examples +### Using pymap3d ```python -# Using pymap3d import pandas as pd import pymap3d as pm @@ -61,7 +48,7 @@ lon0 = -106.651 alt0 = 1619.0 # Local coordinates of corners of the cube -coords = pd.DataFrame( +topocentric_coords = pd.DataFrame( columns=['x', 'y', 'z'], data=[[1., 1., 1.], [4., 1., 1.], @@ -74,21 +61,35 @@ coords = pd.DataFrame( ) # Translate the cube to geocoordinates +# pymap3d.enu2geodetic uses WGS-84 by default. We'll specify a datum to show how +# it is done. + +datum = pm.Ellipsoid.from_name('wgs84') lat, lon, alt = pm.enu2geodetic(coords['y'], coords['x'], coords['z'], - lat0, lon0, alt0) + lat0, lon0, alt0, ell=datum) -coords['lat'] = lat -coords['lon'] = lon -coords['alt'] = alt +geodetic_coords = pd.DataFrame({'lat': lat, 'lon': lon, 'alt': alt}) -print('Topocentric to Geodetic coordinates') -print(coords.to_markdown(index=False)) +print('Topocentric to Geodetic coordinates using pymap3d') +print(geodetic_coords.to_markdown(index=False, floatfmt=".8f")) ``` +Topocentric to Geodetic coordinates using pymap3d +| lat | lon | alt | +|------------:|--------------:|--------------:| +| 35.08450901 | -106.65098904 | 1620.00000016 | +| 35.08453605 | -106.65098904 | 1620.00000134 | +| 35.08450901 | -106.65096711 | 1620.00000078 | +| 35.08453605 | -106.65096711 | 1620.00000196 | +| 35.08450901 | -106.65098904 | 1621.00000016 | +| 35.08453605 | -106.65098904 | 1621.00000134 | +| 35.08450901 | -106.65096711 | 1621.00000078 | +| 35.08453605 | -106.65096711 | 1621.00000196 | + +### Using pyproj ```python -# Using pyproj import pandas as pd import pyproj @@ -132,11 +133,57 @@ coords = pd.DataFrame( lon, lat, alt = transformer.transform( coords['x'], coords['y'], coords['z']) -coords['latitude'] = lat -coords['longitude'] = lon -coords['altitude'] = alt +geodetic_coords = pd.DataFrame({'lat': lat, 'lon': lon, 'alt': alt}) + +print('Topocentric to Geodetic coordinates using pymap3d') +print(geodetic_coords.to_markdown(index=False, floatfmt=".8f")) + +``` + +## From Geographic or Projected Coordinates to PVCollada ENU + +We'll show how we can reverse the above transformation, from WGS-84 geographic coordinates to PVCollada's ENU coordinates, +using either pymap3d or pyproj. + +### Using pymap3d -print('Topocentric to Geodetic coordinates') +```python + +import numpy as np +import pandas as pd +import pymap3d as pm + + +geocoords = pd.DataFrame( + columns=['lat', 'lon', 'alt'], + data = np.array( + [[35.08450901, -106.65098904, 1620.00000016], + [35.08453605, -106.65098904, 1620.00000134], + [35.08450901, -106.65096711, 1620.00000078], + [35.08453605, -106.65096711, 1620.00000196], + [35.08450901, -106.65098904, 1621.00000016], + [35.08453605, -106.65098904, 1621.00000134], + [35.08450901, -106.65096711, 1621.00000078], + [35.08453605, -106.65096711, 1621.00000196]] + ) + ) + +# origin of ENU coordinates +lat0 = 35.0845 +lon0 = -106.651 +alt0 = 1619.0 +datum = pm.Ellipsoid.from_name('wgs84') + +x, y, z = pm.geodetic2enu( + geocoords['lat'], geocoords['lon'], geocoords['alt'], + lat0, lon0, alt0, ell=datum + ) + +# put x, y, z into a DataFrame for convenient printing +enucoords = pd.DataFrame({'x': x, 'y': y, 'z': z}) + +print('Geodetic to Topocentric coordinates using pymap3d') print(coords.to_markdown(index=False, floatfmt=".8f")) ``` +