sbg_utm.cpp
Go to the documentation of this file.
1 // File header
2 #include "sbg_utm.h"
3 
4 // STL headers
5 #include <cmath>
6 
7 using sbg::Utm;
8 
9 //---------------------------------------------------------------------//
10 //- Constructor -//
11 //---------------------------------------------------------------------//
12 
13 Utm::Utm(double latitude, double longitude)
14 {
15  init(latitude, longitude);
16 }
17 
18 //---------------------------------------------------------------------//
19 //- Parameters -//
20 //---------------------------------------------------------------------//
21 
22 bool Utm::isInit() const
23 {
24  return is_init_;
25 }
26 
27 int Utm::getZoneNumber() const
28 {
29  return zone_number_;
30 }
31 
32 double Utm::getMeridian() const
33 {
34  return meridian_;
35 }
36 
38 {
39  return letter_designator_;
40 }
41 
42 //---------------------------------------------------------------------//
43 //- Operations -//
44 //---------------------------------------------------------------------//
45 
46 void Utm::init(double latitude, double longitude)
47 {
48  zone_number_ = computeZoneNumber(latitude, longitude);
51  is_init_ = true;
52 }
53 
54 void Utm::clear()
55 {
56  is_init_ = false;
57  meridian_ = {};
58  zone_number_ = {};
59  letter_designator_ = {};
60 }
61 
62 /*
63  * Originally written by Chuck Gantz - chuck.gantz@globalstar.com
64  */
65 std::array<double, 2> Utm::computeEastingNorthing(double latitude, double longitude) const
66 {
67  constexpr double RADIANS_PER_DEGREE = M_PI / 180.0;
68 
69  // WGS84 Parameters
70  constexpr double WGS84_A = 6378137.0; // major axis
71  constexpr double WGS84_E = 0.0818191908; // first eccentricity
72 
73  // UTM Parameters
74  constexpr double UTM_K0 = 0.9996; // scale factor
75  constexpr double UTM_E2 = (WGS84_E * WGS84_E); // e^2
76 
77  double long_origin;
78  double ecc_prime_squared;
79  double n, t, c, a, m;
80 
81  // Make sure the longitude is between -180.00 .. 179.9
82  double long_temp = (longitude + 180) - int((longitude + 180) / 360) * 360 - 180;
83 
84  double lat_rad = latitude * RADIANS_PER_DEGREE;
85  double long_rad = long_temp * RADIANS_PER_DEGREE;
86  double long_origin_rad;
87 
88  // +3 puts origin in middle of zone
89  long_origin = (zone_number_ - 1) * 6 - 180 + 3;
90  long_origin_rad = long_origin * RADIANS_PER_DEGREE;
91 
92  ecc_prime_squared = (UTM_E2)/(1 - UTM_E2);
93 
94  n = WGS84_A/sqrt(1 - UTM_E2 * sin(lat_rad) * sin(lat_rad));
95  t = tan(lat_rad) * tan(lat_rad);
96  c = ecc_prime_squared * cos(lat_rad) * cos(lat_rad);
97  a = cos(lat_rad) * (long_rad-long_origin_rad);
98 
99  m = WGS84_A * ((1 - UTM_E2/4 - 3*UTM_E2*UTM_E2/64 - 5*UTM_E2*UTM_E2*UTM_E2/256) * lat_rad
100  - (3 * UTM_E2/8 + 3*UTM_E2*UTM_E2/32 + 45*UTM_E2*UTM_E2*UTM_E2/1024) * sin(2*lat_rad)
101  + (15*UTM_E2*UTM_E2/256 + 45*UTM_E2*UTM_E2*UTM_E2/1024) * sin(4*lat_rad)
102  - (35*UTM_E2*UTM_E2*UTM_E2/3072) * sin(6*lat_rad));
103 
104  double utm_easting = (double)(UTM_K0*n*(a+(1-t+c)*a*a*a/6
105  + (5-18*t+t*t+72*c-58*ecc_prime_squared)*a*a*a*a*a/120)
106  + 500000.0);
107 
108  double utm_northing = (double)(UTM_K0*(m+n*tan(lat_rad)*(a*a/2+(5-t+9*c+4*c*c)*a*a*a*a/24
109  + (61-58*t+t*t+600*c-330*ecc_prime_squared)*a*a*a*a*a*a/720)));
110 
111 
112  if (latitude < 0)
113  {
114  utm_northing += 10000000.0; //10000000 meter offset for southern hemisphere
115  }
116 
117  std::array<double, 2> easting_northing{utm_easting, utm_northing};
118  return (easting_northing);
119 }
120 
121 int Utm::computeZoneNumber(double latitude, double longitude)
122 {
123  int zone_number;
124 
125  // Make sure the longitude is between -180.00 .. 179.9
126  double long_temp = (longitude + 180) - int((longitude + 180) / 360) * 360 - 180;
127 
128  zone_number = int((long_temp + 180) / 6) + 1;
129 
130  if ( latitude >= 56.0 && latitude < 64.0 && long_temp >= 3.0 && long_temp < 12.0 )
131  {
132  zone_number = 32;
133  }
134 
135  // Special zones for Svalbard
136  if ( latitude >= 72.0 && latitude < 84.0 )
137  {
138  if ( long_temp >= 0.0 && long_temp < 9.0 )
139  {
140  zone_number = 31;
141  }
142  else if ( long_temp >= 9.0 && long_temp < 21.0 )
143  {
144  zone_number = 33;
145  }
146  else if ( long_temp >= 21.0 && long_temp < 33.0 )
147  {
148  zone_number = 35;
149  }
150  else if ( long_temp >= 33.0 && long_temp < 42.0 )
151  {
152  zone_number = 37;
153  }
154  }
155 
156  return zone_number;
157 }
158 
159 /*
160  * Originally written by Chuck Gantz - chuck.gantz@globalstar.com
161  */
162 char Utm::computeLetterDesignator(double latitude)
163 {
164  char letter_designator;
165 
166  if ((84 >= latitude) && (latitude >= 72))
167  {
168  letter_designator = 'X';
169  }
170  else if ((72 > latitude) && (latitude >= 64))
171  {
172  letter_designator = 'W';
173  }
174  else if ((64 > latitude) && (latitude >= 56))
175  {
176  letter_designator = 'V';
177  }
178  else if ((56 > latitude) && (latitude >= 48))
179  {
180  letter_designator = 'U';
181  }
182  else if ((48 > latitude) && (latitude >= 40))
183  {
184  letter_designator = 'T';
185  }
186  else if ((40 > latitude) && (latitude >= 32))
187  {
188  letter_designator = 'S';
189  }
190  else if ((32 > latitude) && (latitude >= 24))
191  {
192  letter_designator = 'R';
193  }
194  else if ((24 > latitude) && (latitude >= 16))
195  {
196  letter_designator = 'Q';
197  }
198  else if ((16 > latitude) && (latitude >= 8))
199  {
200  letter_designator = 'P';
201  }
202  else if ((8 > latitude) && (latitude >= 0))
203  {
204  letter_designator = 'N';
205  }
206  else if ((0 > latitude) && (latitude >= -8))
207  {
208  letter_designator = 'M';
209  }
210  else if ((-8 > latitude) && (latitude >= -16))
211  {
212  letter_designator = 'L';
213  }
214  else if ((-16 > latitude) && (latitude >= -24))
215  {
216  letter_designator = 'K';
217  }
218  else if ((-24 > latitude) && (latitude >= -32))
219  {
220  letter_designator = 'J';
221  }
222  else if ((-32 > latitude) && (latitude >= -40))
223  {
224  letter_designator = 'H';
225  }
226  else if ((-40 > latitude) && (latitude >= -48))
227  {
228  letter_designator = 'G';
229  }
230  else if ((-48 > latitude) && (latitude >= -56))
231  {
232  letter_designator = 'F';
233  }
234  else if ((-56 > latitude) && (latitude >= -64))
235  {
236  letter_designator = 'E';
237  }
238  else if ((-64 > latitude) && (latitude >= -72))
239  {
240  letter_designator = 'D';
241  }
242  else if ((-72 > latitude) && (latitude >= -80))
243  {
244  letter_designator = 'C';
245  }
246  else
247  {
248  // 'Z' is an error flag, the Latitude is outside the UTM limits
249  letter_designator = 'Z';
250  }
251  return letter_designator;
252 }
253 
254 double Utm::computeMeridian() const
255 {
256  return (zone_number_ == 0) ? 0.0 : (zone_number_ - 1) * 6.0 - 177.0;
257 }
sbg::Utm::computeEastingNorthing
std::array< double, 2 > computeEastingNorthing(double latitude, double longitude) const
Definition: sbg_utm.cpp:65
sbg::Utm::letter_designator_
char letter_designator_
Definition: sbg_utm.h:153
sbg::Utm::zone_number_
int zone_number_
Definition: sbg_utm.h:152
sbg_utm.h
Implement simple UTM projections.
sbg::Utm
Definition: sbg_utm.h:44
sbg::Utm::is_init_
bool is_init_
Definition: sbg_utm.h:150
sbg::Utm::computeLetterDesignator
static char computeLetterDesignator(double latitude)
Definition: sbg_utm.cpp:162
sbg::Utm::init
void init(double latitude, double longitude)
Definition: sbg_utm.cpp:46
sbg::Utm::computeZoneNumber
static int computeZoneNumber(double latitude, double longitude)
Definition: sbg_utm.cpp:121
sbg::Utm::computeMeridian
double computeMeridian() const
Definition: sbg_utm.cpp:254
sbg::Utm::clear
void clear()
Definition: sbg_utm.cpp:54
sbg::Utm::getMeridian
double getMeridian() const
Definition: sbg_utm.cpp:32
sbg::Utm::getZoneNumber
int getZoneNumber() const
Definition: sbg_utm.cpp:27
sbg::Utm::isInit
bool isInit() const
Definition: sbg_utm.cpp:22
sbg::Utm::meridian_
double meridian_
Definition: sbg_utm.h:151
sbg::Utm::getLetterDesignator
char getLetterDesignator() const
Definition: sbg_utm.cpp:37
t
geometry_msgs::TransformStamped t


sbg_driver
Author(s): SBG Systems
autogenerated on Fri Oct 11 2024 02:13:40