diff --git a/References/GDA2020TechnicalManualV1.1.1.pdf b/References/GDA2020TechnicalManualV1.2.pdf similarity index 67% rename from References/GDA2020TechnicalManualV1.1.1.pdf rename to References/GDA2020TechnicalManualV1.2.pdf index 67eb6f8..f772134 100644 Binary files a/References/GDA2020TechnicalManualV1.1.1.pdf and b/References/GDA2020TechnicalManualV1.2.pdf differ diff --git a/docs/tutorials/GeodePy Tutorial - Time-Dependent Datum Transformations.ipynb b/docs/tutorials/GeodePy Tutorial - Time-Dependent Datum Transformations.ipynb index 741fe4e..53435d7 100644 --- a/docs/tutorials/GeodePy Tutorial - Time-Dependent Datum Transformations.ipynb +++ b/docs/tutorials/GeodePy Tutorial - Time-Dependent Datum Transformations.ipynb @@ -13,15 +13,16 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Start by importing the following GeodePy Functions and Modules:" + "Start by importing the following Functions and Modules (datetime is used for the representation of epochs):" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 55, "metadata": {}, "outputs": [], "source": [ + "from datetime import date\n", "from geodepy.constants import itrf14togda20, itrf14to05\n", "from geodepy.transform import *" ] @@ -35,7 +36,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 56, "metadata": {}, "outputs": [], "source": [ @@ -52,7 +53,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 57, "metadata": {}, "outputs": [ { @@ -61,7 +62,7 @@ "(-23.67011015602, 133.88552163574)" ] }, - "execution_count": 4, + "execution_count": 57, "metadata": {}, "output_type": "execute_result" } @@ -80,7 +81,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 58, "metadata": {}, "outputs": [ { @@ -89,7 +90,7 @@ "(-4052042.792092285, 4212825.645301948, -2545098.3015855583)" ] }, - "execution_count": 5, + "execution_count": 58, "metadata": {}, "output_type": "execute_result" } @@ -109,14 +110,14 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 59, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Transformation: From 'ITRF2005' to 'ITRF2014'\n", - "Reference Epoch: 2010.0\n", + "Reference Epoch: datetime.date(2010, 1, 1)\n", " tx: -0.0026m + -0.0003m/yr\n", " ty: -0.001m + -0.0m/yr\n", " tz: 0.0023m + 0.0001m/yr\n", @@ -126,7 +127,7 @@ " rz: -0.0\" + -0.0\"/yr" ] }, - "execution_count": 6, + "execution_count": 59, "metadata": {}, "output_type": "execute_result" } @@ -139,19 +140,19 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Before we can use this, we need to get our coordinates into the Reference Epoch of the transformation we plan to use (in this case, 2010.0). Because Bob is in Australia, we need to use the Australian Plate Motion Model to do this. It's parameters are in `itrf14togda20`:" + "Before we can use this, we need to get our coordinates into the Reference Epoch of the transformation we plan to use (in this case, 2010.0 or the 1st Jan 2010). Because Bob is in Australia, we need to use the Australian Plate Motion Model to do this. It's parameters are in `itrf14togda20`:" ] }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 60, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Transformation: From 'ITRF2014' to 'GDA2020'\n", - "Reference Epoch: 2020\n", + "Reference Epoch: datetime.date(2020, 1, 1)\n", " tx: 0m + 0m/yr\n", " ty: 0m + 0m/yr\n", " tz: 0m + 0m/yr\n", @@ -161,7 +162,7 @@ " rz: 0\" + 0.00120716\"/yr" ] }, - "execution_count": 7, + "execution_count": 60, "metadata": {}, "output_type": "execute_result" } @@ -179,7 +180,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 61, "metadata": {}, "outputs": [ { @@ -188,7 +189,7 @@ "(-4052042.792092285, 4212825.645301948, -2545098.3015855583)" ] }, - "execution_count": 8, + "execution_count": 61, "metadata": {}, "output_type": "execute_result" } @@ -199,22 +200,22 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 62, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "(-4052042.3995643803, 4212825.696887399, -2545098.841140103)" + "(-4052042.3994570016, 4212825.69690139, -2545098.841287901)" ] }, - "execution_count": 9, + "execution_count": 62, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "x2, y2, z2 = conform14(x, y, z, 2030, itrf14togda20)\n", + "x2, y2, z2 = conform14(x, y, z, date(2030, 1, 1), itrf14togda20)\n", "x2, y2, z2" ] }, @@ -235,16 +236,16 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 63, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "(-4052042.398436501, 4212825.692011599, -2545098.8364986125)" + "(-4052042.3983291225, 4212825.692025591, -2545098.8366464106)" ] }, - "execution_count": 10, + "execution_count": 63, "metadata": {}, "output_type": "execute_result" } @@ -258,29 +259,29 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "This gives us Bob's Cartesian Coordinates in ITRF2014 at epoch 20100.\n", + "This gives us Bob's Cartesian Coordinates in ITRF2014 at epoch 2010.0.\n", "#### Part 4: Moving to the Final Epoch\n", "The final tranformation is moving Bob's epoch to it's final destination (2020.0) using `itrf14togda20`. As the period of movement (2010.0 to 2020.0) is the same (+10.0 years), we use the same `to_epoch` of 2030.0 as in Part 2:" ] }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 64, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "(-4052042.005908563, 4212825.743596989, -2545099.376053138)" + "(-4052042.0056938054, 4212825.743624971, -2545099.376348734)" ] }, - "execution_count": 11, + "execution_count": 64, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "x4, y4, z4 = conform14(x3, y3, z3, 2030, itrf14togda20)\n", + "x4, y4, z4 = conform14(x3, y3, z3, date(2030, 1, 1), itrf14togda20)\n", "x4, y4, z4" ] }, @@ -295,16 +296,16 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 65, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "(-23.67012075907436, 133.88551541372001, 587.5785021279007)" + "(-23.670120761985057, 133.8855154120127, 587.5785029223189)" ] }, - "execution_count": 12, + "execution_count": 65, "metadata": {}, "output_type": "execute_result" } @@ -323,16 +324,16 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 66, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "(53, 386352.6117, 7381851.1177)" + "(53, 386352.6116, 7381851.1174)" ] }, - "execution_count": 13, + "execution_count": 66, "metadata": {}, "output_type": "execute_result" } @@ -351,16 +352,16 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 67, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "(53, 386352.6117, 7381851.1177, 587.5785021279007)" + "(53, 386352.6116, 7381851.1174, 587.5785029223189)" ] }, - "execution_count": 14, + "execution_count": 67, "metadata": {}, "output_type": "execute_result" } @@ -378,16 +379,16 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 68, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "(53, 386352.6117, 7381851.1177, 587.5785021279007)" + "(53, 386352.6116, 7381851.1174, 587.5785029223189)" ] }, - "execution_count": 15, + "execution_count": 68, "metadata": {}, "output_type": "execute_result" } @@ -399,7 +400,7 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 69, "metadata": {}, "outputs": [ { @@ -408,7 +409,7 @@ "(53, 386353.2371, 7381852.2967, 587.5814)" ] }, - "execution_count": 16, + "execution_count": 69, "metadata": {}, "output_type": "execute_result" } @@ -427,16 +428,16 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 70, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "(53, 386352.6117, 7381851.1177, 587.5785021279007)" + "(53, 386352.6116, 7381851.1174, 587.5785029223189)" ] }, - "execution_count": 18, + "execution_count": 70, "metadata": {}, "output_type": "execute_result" } @@ -445,9 +446,9 @@ "def bobtransform(zone, east, north, ell_ht):\n", " lat, lon, psf, grid_conv = grid2geo(zone, east, north)\n", " x, y, z = llh2xyz(lat, lon, ell_ht)\n", - " x2, y2, z2 = conform14(x, y, z, 2030, itrf14togda20)\n", + " x2, y2, z2 = conform14(x, y, z, date(2030, 1, 1), itrf14togda20)\n", " x3, y3, z3 = conform7(x2, y2, z2, -itrf14to05)\n", - " x4, y4, z4 = conform14(x3, y3, z3, 2030, itrf14togda20)\n", + " x4, y4, z4 = conform14(x3, y3, z3, date(2030, 1, 1), itrf14togda20)\n", " lat_end, lon_end, ell_ht_end = xyz2llh(x4, y4, z4)\n", " hem_end, zone_end, east_end, north_end, psf_end, grid_conv_end = geo2grid(lat_end, lon_end)\n", " return zone_end, east_end, north_end, ell_ht_end\n", diff --git a/geodepy/constants.py b/geodepy/constants.py index c44cfb2..9c80799 100644 --- a/geodepy/constants.py +++ b/geodepy/constants.py @@ -158,14 +158,24 @@ def iers2trans(itrf_from, itrf_to, ref_epoch, tx, ty, tz, sc, rx, ry, rz, d_tx, round(d_sc / 1000, 8), round(-d_rx / 1000, 8), round(-d_ry / 1000, 8), round(-d_rz / 1000, 8)) -# GDA1994 to GDA2020 Transformation Parameters from GDA2020 Tech Manual v1.1.1 +# GDA1994 to GDA2020 Transformation Parameters from GDA2020 Tech Manual v1.2 gda94to20 = Transformation('GDA1994', 'GDA2020', 0, 0.06155, -0.01087, -0.04019, -0.009994, -0.0394924, -0.0327221, -0.0328979) +# ITRF2014 to GDA2020 (Australian Plate Motion Model) Transformation Parameters from GDA2020 Tech Manual v1.2. The +# model was derived using 109 ARGN and AuScope GNSS CORS which were used to define the RVS. + itrf14togda20 = Transformation('ITRF2014', 'GDA2020', date(2020, 1, 1), - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0.00150379, 0.00118346, 0.00120716) + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0.00150379, 0.00118346, 0.00120716) + +# ATRF to GDA2020 (Australian Plate Motion Model) Transformation Parameters (as advised by N. Brown, Geoscience +# Australia). The model was derived using 109 ARGN and AuScope GNSS CORS which were used to define the RVS. + +atrf_gda2020 = Transformation('ATRF', 'GDA2020', date(2020, 1, 1), + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0.00150379, 0.00118346, 0.00120716) # GDA1994 to ITRF Transformation Parameters from Dawson and Woods (2010) # AGD66 and AGD84 to GDA94 Transformation Parameters from GDA94 Tech Manual v2.4 diff --git a/geodepy/tests/test_transform.py b/geodepy/tests/test_transform.py index 3d785b2..16f0bc3 100644 --- a/geodepy/tests/test_transform.py +++ b/geodepy/tests/test_transform.py @@ -1,6 +1,6 @@ import unittest -from geodepy.transform import geo2grid, grid2geo, llh2xyz, xyz2llh, conform7, conform14 +from geodepy.transform import geo2grid, grid2geo, llh2xyz, xyz2llh, conform7, conform14, atrftogda2020, gda2020toatrf from geodepy.convert import dms2dd_v, read_dnacoord from geodepy.constants import itrf14togda20, gda94to20 from datetime import date @@ -106,5 +106,18 @@ def test_conform14(self): assert (abs(alic_gda2020_comp[2] - alic_gda2020[2]) < 5e-5) + def test_atrftogda2020(self): + alic_gda2020 = (-4052052.7373, 4212835.9835, -2545104.5867) + alic_itrf14at2018 = (-4052052.6588, 4212835.9938, -2545104.6946) + alic_itrf14at2018_comp = gda2020toatrf(*alic_gda2020, date(2018, 1, 1)) + alic_gda2020_comp = atrftogda2020(*alic_itrf14at2018, date(2018, 1, 1)) + assert (abs(alic_itrf14at2018_comp[0] - alic_itrf14at2018[0]) < 5e-5) + assert (abs(alic_itrf14at2018_comp[1] - alic_itrf14at2018[1]) < 5e-5) + assert (abs(alic_itrf14at2018_comp[2] - alic_itrf14at2018[2]) < 5e-5) + assert (abs(alic_gda2020_comp[0] - alic_gda2020[0]) < 5e-5) + assert (abs(alic_gda2020_comp[1] - alic_gda2020[1]) < 5e-5) + assert (abs(alic_gda2020_comp[2] - alic_gda2020[2]) < 5e-5) + + if __name__ == '__main__': unittest.main() diff --git a/geodepy/transform.py b/geodepy/transform.py index 0a30727..6521429 100644 --- a/geodepy/transform.py +++ b/geodepy/transform.py @@ -12,9 +12,9 @@ import os import csv import datetime -from math import sqrt, log, degrees, radians, sin, cos, tan, sinh, cosh, atan, atan2, modf +from math import sqrt, log, degrees, radians, sin, cos, tan, sinh, cosh, atan, atan2 import numpy as np -from geodepy.constants import grs80, utm, Transformation +from geodepy.constants import grs80, utm, Transformation, atrf_gda2020 from geodepy.convert import dec2hp, hp2dec @@ -528,6 +528,33 @@ def conform14(x, y, z, to_epoch, trans): return xtrans, ytrans, ztrans +def atrftogda2020(x, y, z, epoch_from): + """ + Transforms Cartesian (x, y, z) Coordinates in terms of the Australian Terrestrial Reference Frame (ATRF) at + a specified epoch to coordinates in terms of Geocentric Datum of Australia 2020 (GDA2020 - reference epoch 2020.0) + :param x: ATRF Cartesian X Coordinate (m) + :param y: ATRF Cartesian Y Coordinate (m) + :param z: ATRF Cartesian Z Coordinate (m) + :param epoch_from: ATRF Coordinate Epoch (datetime.date Object) + :return: Cartesian X, Y, Z Coordinates in terms of GDA2020 + """ + return conform14(x, y, z, epoch_from, atrf_gda2020) + + +def gda2020toatrf(x, y, z, epoch_to): + """ + Transforms Cartesian (x, y, z) Coordinates in terms of Geocentric Datum of Australia 2020 + (GDA2020 - reference epoch 2020.0) to coordinates in terms of the Australian Terrestrial Reference Frame (ATRF) at + a specified epoch + :param x: GDA2020 Cartesian X Coordinate (m) + :param y: GDA2020 Cartesian Y Coordinate (m) + :param z: GDA2020 Cartesian Z Coordinate (m) + :param epoch_to: ATRF Coordinate Epoch (datetime.date Object) + :return: Cartesian X, Y, Z Coordinate in terms of ATRF at the specified Epoch + """ + return conform14(x, y, z, epoch_to, -atrf_gda2020) + + def grid2geoio(): """ No Input: