PX4 Firmware
PX4 Autopilot Software http://px4.io
geo.cpp
Go to the documentation of this file.
1 /****************************************************************************
2  *
3  * Copyright (c) 2012-2014 PX4 Development Team. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in
13  * the documentation and/or other materials provided with the
14  * distribution.
15  * 3. Neither the name PX4 nor the names of its contributors may be
16  * used to endorse or promote products derived from this software
17  * without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
26  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  *
32  ****************************************************************************/
33 
34 /**
35  * @file geo.c
36  *
37  * Geo / math functions to perform geodesic calculations
38  *
39  * @author Thomas Gubler <thomasgubler@student.ethz.ch>
40  * @author Julian Oes <joes@student.ethz.ch>
41  * @author Lorenz Meier <lm@inf.ethz.ch>
42  * @author Anton Babushkin <anton.babushkin@me.com>
43  */
44 
45 #include "geo.h"
46 #include <ecl.h>
47 
48 #include <mathlib/mathlib.h>
49 #include <matrix/math.hpp>
50 #include <float.h>
51 
52 using matrix::wrap_pi;
53 using matrix::wrap_2pi;
54 
55 /*
56  * Azimuthal Equidistant Projection
57  * formulas according to: http://mathworld.wolfram.com/AzimuthalEquidistantProjection.html
58  */
59 
61 static struct globallocal_converter_reference_s gl_ref = {0.0f, false};
62 
64 {
66 }
67 
69 {
70  return ref->init_done;
71 }
72 
74 {
76 }
77 
79 {
80  return ref->timestamp;
81 }
82 
83 // lat_0, lon_0 are expected to be in correct format: -> 47.1234567 and not 471234567
84 int map_projection_global_init(double lat_0, double lon_0, uint64_t timestamp)
85 {
86  return map_projection_init_timestamped(&mp_ref, lat_0, lon_0, timestamp);
87 }
88 
89 // lat_0, lon_0 are expected to be in correct format: -> 47.1234567 and not 471234567
90 int map_projection_init_timestamped(struct map_projection_reference_s *ref, double lat_0, double lon_0, uint64_t timestamp)
91 {
92 
93  ref->lat_rad = math::radians(lat_0);
94  ref->lon_rad = math::radians(lon_0);
95  ref->sin_lat = sin(ref->lat_rad);
96  ref->cos_lat = cos(ref->lat_rad);
97 
98  ref->timestamp = timestamp;
99  ref->init_done = true;
100 
101  return 0;
102 }
103 
104 //lat_0, lon_0 are expected to be in correct format: -> 47.1234567 and not 471234567
105 int map_projection_init(struct map_projection_reference_s *ref, double lat_0, double lon_0)
106 {
107  return map_projection_init_timestamped(ref, lat_0, lon_0, ecl_absolute_time());
108 }
109 
110 int map_projection_global_reference(double *ref_lat_rad, double *ref_lon_rad)
111 {
112  return map_projection_reference(&mp_ref, ref_lat_rad, ref_lon_rad);
113 }
114 
115 int map_projection_reference(const struct map_projection_reference_s *ref, double *ref_lat_rad, double *ref_lon_rad)
116 {
117  if (!map_projection_initialized(ref)) {
118  return -1;
119  }
120 
121  *ref_lat_rad = ref->lat_rad;
122  *ref_lon_rad = ref->lon_rad;
123 
124  return 0;
125 }
126 
127 int map_projection_global_project(double lat, double lon, float *x, float *y)
128 {
129  return map_projection_project(&mp_ref, lat, lon, x, y);
130 }
131 
132 int map_projection_project(const struct map_projection_reference_s *ref, double lat, double lon, float *x, float *y)
133 {
134  if (!map_projection_initialized(ref)) {
135  return -1;
136  }
137 
138  const double lat_rad = math::radians(lat);
139  const double lon_rad = math::radians(lon);
140 
141  const double sin_lat = sin(lat_rad);
142  const double cos_lat = cos(lat_rad);
143 
144  const double cos_d_lon = cos(lon_rad - ref->lon_rad);
145 
146  const double arg = math::constrain(ref->sin_lat * sin_lat + ref->cos_lat * cos_lat * cos_d_lon, -1.0, 1.0);
147  const double c = acos(arg);
148 
149  double k = 1.0;
150 
151  if (fabs(c) > 0) {
152  k = (c / sin(c));
153  }
154 
155  *x = static_cast<float>(k * (ref->cos_lat * sin_lat - ref->sin_lat * cos_lat * cos_d_lon) * CONSTANTS_RADIUS_OF_EARTH);
156  *y = static_cast<float>(k * cos_lat * sin(lon_rad - ref->lon_rad) * CONSTANTS_RADIUS_OF_EARTH);
157 
158  return 0;
159 }
160 
161 int map_projection_global_reproject(float x, float y, double *lat, double *lon)
162 {
163  return map_projection_reproject(&mp_ref, x, y, lat, lon);
164 }
165 
166 int map_projection_reproject(const struct map_projection_reference_s *ref, float x, float y, double *lat, double *lon)
167 {
168  if (!map_projection_initialized(ref)) {
169  return -1;
170  }
171 
172  const double x_rad = (double)x / CONSTANTS_RADIUS_OF_EARTH;
173  const double y_rad = (double)y / CONSTANTS_RADIUS_OF_EARTH;
174  const double c = sqrt(x_rad * x_rad + y_rad * y_rad);
175 
176  if (fabs(c) > 0) {
177  const double sin_c = sin(c);
178  const double cos_c = cos(c);
179 
180  const double lat_rad = asin(cos_c * ref->sin_lat + (x_rad * sin_c * ref->cos_lat) / c);
181  const double lon_rad = (ref->lon_rad + atan2(y_rad * sin_c, c * ref->cos_lat * cos_c - x_rad * ref->sin_lat * sin_c));
182 
183  *lat = math::degrees(lat_rad);
184  *lon = math::degrees(lon_rad);
185 
186  } else {
187  *lat = math::degrees(ref->lat_rad);
188  *lon = math::degrees(ref->lon_rad);
189  }
190 
191  return 0;
192 }
193 
194 int map_projection_global_getref(double *lat_0, double *lon_0)
195 {
197  return -1;
198  }
199 
200  if (lat_0 != nullptr) {
201  *lat_0 = math::degrees(mp_ref.lat_rad);
202  }
203 
204  if (lon_0 != nullptr) {
205  *lon_0 = math::degrees(mp_ref.lon_rad);
206  }
207 
208  return 0;
209 
210 }
211 int globallocalconverter_init(double lat_0, double lon_0, float alt_0, uint64_t timestamp)
212 {
213  gl_ref.alt = alt_0;
214 
215  if (!map_projection_global_init(lat_0, lon_0, timestamp)) {
216  gl_ref.init_done = true;
217  return 0;
218  }
219 
220  gl_ref.init_done = false;
221  return -1;
222 }
223 
225 {
226  return gl_ref.init_done && map_projection_global_initialized();
227 }
228 
229 int globallocalconverter_tolocal(double lat, double lon, float alt, float *x, float *y, float *z)
230 {
232  return -1;
233  }
234 
235  map_projection_global_project(lat, lon, x, y);
236  *z = gl_ref.alt - alt;
237 
238  return 0;
239 }
240 
241 int globallocalconverter_toglobal(float x, float y, float z, double *lat, double *lon, float *alt)
242 {
244  return -1;
245  }
246 
247  map_projection_global_reproject(x, y, lat, lon);
248  *alt = gl_ref.alt - z;
249 
250  return 0;
251 }
252 
253 int globallocalconverter_getref(double *lat_0, double *lon_0, float *alt_0)
254 {
256  return -1;
257  }
258 
259  if (map_projection_global_getref(lat_0, lon_0)) {
260  return -1;
261  }
262 
263  if (alt_0 != nullptr) {
264  *alt_0 = gl_ref.alt;
265  }
266 
267  return 0;
268 }
269 
270 float get_distance_to_next_waypoint(double lat_now, double lon_now, double lat_next, double lon_next)
271 {
272  const double lat_now_rad = math::radians(lat_now);
273  const double lat_next_rad = math::radians(lat_next);
274 
275  const double d_lat = lat_next_rad - lat_now_rad;
276  const double d_lon = math::radians(lon_next) - math::radians(lon_now);
277 
278  const double a = sin(d_lat / 2.0) * sin(d_lat / 2.0) + sin(d_lon / 2.0) * sin(d_lon / 2.0) * cos(lat_now_rad) * cos(lat_next_rad);
279 
280  const double c = atan2(sqrt(a), sqrt(1.0 - a));
281 
282  return static_cast<float>(CONSTANTS_RADIUS_OF_EARTH * 2.0 * c);
283 }
284 
285 void create_waypoint_from_line_and_dist(double lat_A, double lon_A, double lat_B, double lon_B, float dist,
286  double *lat_target, double *lon_target)
287 {
288  if (fabsf(dist) < FLT_EPSILON) {
289  *lat_target = lat_A;
290  *lon_target = lon_A;
291 
292  } else if (dist >= FLT_EPSILON) {
293  float heading = get_bearing_to_next_waypoint(lat_A, lon_A, lat_B, lon_B);
294  waypoint_from_heading_and_distance(lat_A, lon_A, heading, dist, lat_target, lon_target);
295 
296  } else {
297  float heading = get_bearing_to_next_waypoint(lat_A, lon_A, lat_B, lon_B);
298  heading = wrap_2pi(heading + M_PI_F);
299  waypoint_from_heading_and_distance(lat_A, lon_A, heading, dist, lat_target, lon_target);
300  }
301 }
302 
303 void waypoint_from_heading_and_distance(double lat_start, double lon_start, float bearing, float dist,
304  double *lat_target, double *lon_target)
305 {
306  bearing = wrap_2pi(bearing);
307  double radius_ratio = (double)fabs((double)dist) / CONSTANTS_RADIUS_OF_EARTH;
308 
309  double lat_start_rad = math::radians(lat_start);
310  double lon_start_rad = math::radians(lon_start);
311 
312  *lat_target = asin(sin(lat_start_rad) * cos(radius_ratio) + cos(lat_start_rad) * sin(radius_ratio) * cos((double)bearing));
313  *lon_target = lon_start_rad + atan2(sin((double)bearing) * sin(radius_ratio) * cos(lat_start_rad),
314  cos(radius_ratio) - sin(lat_start_rad) * sin(*lat_target));
315 
316  *lat_target = math::degrees(*lat_target);
317  *lon_target = math::degrees(*lon_target);
318 }
319 
320 float get_bearing_to_next_waypoint(double lat_now, double lon_now, double lat_next, double lon_next)
321 {
322  const double lat_now_rad = math::radians(lat_now);
323  const double lat_next_rad = math::radians(lat_next);
324 
325  const double cos_lat_next = cos(lat_next_rad);
326  const double d_lon = math::radians(lon_next - lon_now);
327 
328  /* conscious mix of double and float trig function to maximize speed and efficiency */
329 
330  const float y = static_cast<float>(sin(d_lon) * cos_lat_next);
331  const float x = static_cast<float>(cos(lat_now_rad) * sin(lat_next_rad) - sin(lat_now_rad) * cos_lat_next * cos(d_lon));
332 
333  return wrap_pi(atan2f(y, x));
334 }
335 
336 void
337 get_vector_to_next_waypoint(double lat_now, double lon_now, double lat_next, double lon_next, float *v_n, float *v_e)
338 {
339  const double lat_now_rad = math::radians(lat_now);
340  const double lat_next_rad = math::radians(lat_next);
341  const double d_lon = math::radians(lon_next) - math::radians(lon_now);
342 
343  /* conscious mix of double and float trig function to maximize speed and efficiency */
344  *v_n = static_cast<float>(CONSTANTS_RADIUS_OF_EARTH * (cos(lat_now_rad) * sin(lat_next_rad) - sin(lat_now_rad) * cos(lat_next_rad) * cos(d_lon)));
345  *v_e = static_cast<float>(CONSTANTS_RADIUS_OF_EARTH * sin(d_lon) * cos(lat_next_rad));
346 }
347 
348 void
349 get_vector_to_next_waypoint_fast(double lat_now, double lon_now, double lat_next, double lon_next, float *v_n, float *v_e)
350 {
351  double lat_now_rad = math::radians(lat_now);
352  double lon_now_rad = math::radians(lon_now);
353  double lat_next_rad = math::radians(lat_next);
354  double lon_next_rad = math::radians(lon_next);
355 
356  double d_lat = lat_next_rad - lat_now_rad;
357  double d_lon = lon_next_rad - lon_now_rad;
358 
359  /* conscious mix of double and float trig function to maximize speed and efficiency */
360  *v_n = static_cast<float>(CONSTANTS_RADIUS_OF_EARTH * d_lat);
361  *v_e = static_cast<float>(CONSTANTS_RADIUS_OF_EARTH * d_lon * cos(lat_now_rad));
362 }
363 
364 void add_vector_to_global_position(double lat_now, double lon_now, float v_n, float v_e, double *lat_res, double *lon_res)
365 {
366  double lat_now_rad = math::radians(lat_now);
367  double lon_now_rad = math::radians(lon_now);
368 
369  *lat_res = math::degrees(lat_now_rad + (double)v_n / CONSTANTS_RADIUS_OF_EARTH);
370  *lon_res = math::degrees(lon_now_rad + (double)v_e / (CONSTANTS_RADIUS_OF_EARTH * cos(lat_now_rad)));
371 }
372 
373 // Additional functions - @author Doug Weibel <douglas.weibel@colorado.edu>
374 
375 int get_distance_to_line(struct crosstrack_error_s *crosstrack_error, double lat_now, double lon_now,
376  double lat_start, double lon_start, double lat_end, double lon_end)
377 {
378  // This function returns the distance to the nearest point on the track line. Distance is positive if current
379  // position is right of the track and negative if left of the track as seen from a point on the track line
380  // headed towards the end point.
381 
382  int return_value = -1; // Set error flag, cleared when valid result calculated.
383  crosstrack_error->past_end = false;
384  crosstrack_error->distance = 0.0f;
385  crosstrack_error->bearing = 0.0f;
386 
387  float dist_to_end = get_distance_to_next_waypoint(lat_now, lon_now, lat_end, lon_end);
388 
389  // Return error if arguments are bad
390  if (dist_to_end < 0.1f) {
391  return -1;
392  }
393 
394  float bearing_end = get_bearing_to_next_waypoint(lat_now, lon_now, lat_end, lon_end);
395  float bearing_track = get_bearing_to_next_waypoint(lat_start, lon_start, lat_end, lon_end);
396  float bearing_diff = wrap_pi(bearing_track - bearing_end);
397 
398  // Return past_end = true if past end point of line
399  if (bearing_diff > M_PI_2_F || bearing_diff < -M_PI_2_F) {
400  crosstrack_error->past_end = true;
401  return_value = 0;
402  return return_value;
403  }
404 
405  crosstrack_error->distance = (dist_to_end) * sinf(bearing_diff);
406 
407  if (sinf(bearing_diff) >= 0) {
408  crosstrack_error->bearing = wrap_pi(bearing_track - M_PI_2_F);
409 
410  } else {
411  crosstrack_error->bearing = wrap_pi(bearing_track + M_PI_2_F);
412  }
413 
414  return_value = 0;
415 
416  return return_value;
417 }
418 
419 int get_distance_to_arc(struct crosstrack_error_s *crosstrack_error, double lat_now, double lon_now,
420  double lat_center, double lon_center,
421  float radius, float arc_start_bearing, float arc_sweep)
422 {
423  // This function returns the distance to the nearest point on the track arc. Distance is positive if current
424  // position is right of the arc and negative if left of the arc as seen from the closest point on the arc and
425  // headed towards the end point.
426 
427  // Determine if the current position is inside or outside the sector between the line from the center
428  // to the arc start and the line from the center to the arc end
429  float bearing_sector_start = 0.0f;
430  float bearing_sector_end = 0.0f;
431  float bearing_now = get_bearing_to_next_waypoint(lat_now, lon_now, lat_center, lon_center);
432 
433  int return_value = -1; // Set error flag, cleared when valid result calculated.
434  crosstrack_error->past_end = false;
435  crosstrack_error->distance = 0.0f;
436  crosstrack_error->bearing = 0.0f;
437 
438  // Return error if arguments are bad
439  if (radius < 0.1f) {
440  return return_value;
441  }
442 
443  if (arc_sweep >= 0.0f) {
444  bearing_sector_start = arc_start_bearing;
445  bearing_sector_end = arc_start_bearing + arc_sweep;
446 
447  if (bearing_sector_end > 2.0f * M_PI_F) { bearing_sector_end -= (2 * M_PI_F); }
448 
449  } else {
450  bearing_sector_end = arc_start_bearing;
451  bearing_sector_start = arc_start_bearing - arc_sweep;
452 
453  if (bearing_sector_start < 0.0f) { bearing_sector_start += (2 * M_PI_F); }
454  }
455 
456  bool in_sector = false;
457 
458  // Case where sector does not span zero
459  if (bearing_sector_end >= bearing_sector_start && bearing_now >= bearing_sector_start
460  && bearing_now <= bearing_sector_end) {
461 
462  in_sector = true;
463  }
464 
465  // Case where sector does span zero
466  if (bearing_sector_end < bearing_sector_start && (bearing_now > bearing_sector_start
467  || bearing_now < bearing_sector_end)) {
468 
469  in_sector = true;
470  }
471 
472  // If in the sector then calculate distance and bearing to closest point
473  if (in_sector) {
474  crosstrack_error->past_end = false;
475  float dist_to_center = get_distance_to_next_waypoint(lat_now, lon_now, lat_center, lon_center);
476 
477  if (dist_to_center <= radius) {
478  crosstrack_error->distance = radius - dist_to_center;
479  crosstrack_error->bearing = bearing_now + M_PI_F;
480 
481  } else {
482  crosstrack_error->distance = dist_to_center - radius;
483  crosstrack_error->bearing = bearing_now;
484  }
485 
486  // If out of the sector then calculate dist and bearing to start or end point
487 
488  } else {
489 
490  // Use the approximation that 111,111 meters in the y direction is 1 degree (of latitude)
491  // and 111,111 * cos(latitude) meters in the x direction is 1 degree (of longitude) to
492  // calculate the position of the start and end points. We should not be doing this often
493  // as this function generally will not be called repeatedly when we are out of the sector.
494 
495  double start_disp_x = (double)radius * sin((double)arc_start_bearing);
496  double start_disp_y = (double)radius * cos((double)arc_start_bearing);
497  double end_disp_x = (double)radius * sin((double)wrap_pi(arc_start_bearing + arc_sweep));
498  double end_disp_y = (double)radius * cos((double)wrap_pi(arc_start_bearing + arc_sweep));
499  double lon_start = lon_now + start_disp_x / 111111.0;
500  double lat_start = lat_now + start_disp_y * cos(lat_now) / 111111.0;
501  double lon_end = lon_now + end_disp_x / 111111.0;
502  double lat_end = lat_now + end_disp_y * cos(lat_now) / 111111.0;
503  float dist_to_start = get_distance_to_next_waypoint(lat_now, lon_now, lat_start, lon_start);
504  float dist_to_end = get_distance_to_next_waypoint(lat_now, lon_now, lat_end, lon_end);
505 
506  if (dist_to_start < dist_to_end) {
507  crosstrack_error->distance = dist_to_start;
508  crosstrack_error->bearing = get_bearing_to_next_waypoint(lat_now, lon_now, lat_start, lon_start);
509 
510  } else {
511  crosstrack_error->past_end = true;
512  crosstrack_error->distance = dist_to_end;
513  crosstrack_error->bearing = get_bearing_to_next_waypoint(lat_now, lon_now, lat_end, lon_end);
514  }
515  }
516 
517  crosstrack_error->bearing = wrap_pi(crosstrack_error->bearing);
518  return_value = 0;
519 
520  return return_value;
521 }
522 
523 float get_distance_to_point_global_wgs84(double lat_now, double lon_now, float alt_now,
524  double lat_next, double lon_next, float alt_next,
525  float *dist_xy, float *dist_z)
526 {
527  double current_x_rad = lat_next / 180.0 * M_PI;
528  double current_y_rad = lon_next / 180.0 * M_PI;
529  double x_rad = lat_now / 180.0 * M_PI;
530  double y_rad = lon_now / 180.0 * M_PI;
531 
532  double d_lat = x_rad - current_x_rad;
533  double d_lon = y_rad - current_y_rad;
534 
535  double a = sin(d_lat / 2.0) * sin(d_lat / 2.0) + sin(d_lon / 2.0) * sin(d_lon / 2.0) * cos(current_x_rad) * cos(x_rad);
536  double c = 2 * atan2(sqrt(a), sqrt(1 - a));
537 
538  const float dxy = static_cast<float>(CONSTANTS_RADIUS_OF_EARTH * c);
539  const float dz = static_cast<float>(alt_now - alt_next);
540 
541  *dist_xy = fabsf(dxy);
542  *dist_z = fabsf(dz);
543 
544  return sqrtf(dxy * dxy + dz * dz);
545 }
546 
547 float mavlink_wpm_distance_to_point_local(float x_now, float y_now, float z_now,
548  float x_next, float y_next, float z_next,
549  float *dist_xy, float *dist_z)
550 {
551  float dx = x_now - x_next;
552  float dy = y_now - y_next;
553  float dz = z_now - z_next;
554 
555  *dist_xy = sqrtf(dx * dx + dy * dy);
556  *dist_z = fabsf(dz);
557 
558  return sqrtf(dx * dx + dy * dy + dz * dz);
559 }
constexpr _Tp constrain(_Tp val, _Tp min_val, _Tp max_val)
Definition: Limits.hpp:66
Dual< Scalar, N > acos(const Dual< Scalar, N > &a)
Definition: Dual.hpp:309
float get_distance_to_point_global_wgs84(double lat_now, double lon_now, float alt_now, double lat_next, double lon_next, float alt_next, float *dist_xy, float *dist_z)
Definition: geo.cpp:523
int globallocalconverter_init(double lat_0, double lon_0, float alt_0, uint64_t timestamp)
Initialize the global mapping between global position (spherical) and local position (NED)...
Definition: geo.cpp:211
float mavlink_wpm_distance_to_point_local(float x_now, float y_now, float z_now, float x_next, float y_next, float z_next, float *dist_xy, float *dist_z)
Definition: geo.cpp:547
Adapter / shim layer for system calls needed by ECL.
int map_projection_global_reference(double *ref_lat_rad, double *ref_lon_rad)
Writes the reference values of the global projection to ref_lat and ref_lon.
Definition: geo.cpp:110
static constexpr double CONSTANTS_RADIUS_OF_EARTH
Definition: geo.h:61
Definition of geo / math functions to perform geodesic calculations.
bool map_projection_initialized(const struct map_projection_reference_s *ref)
Checks if projection given as argument was initialized.
Definition: geo.cpp:68
int globallocalconverter_getref(double *lat_0, double *lon_0, float *alt_0)
Get reference position of the global to local converter.
Definition: geo.cpp:253
void get_vector_to_next_waypoint(double lat_now, double lon_now, double lat_next, double lon_next, float *v_n, float *v_e)
Definition: geo.cpp:337
float get_distance_to_next_waypoint(double lat_now, double lon_now, double lat_next, double lon_next)
Returns the distance to the next waypoint in meters.
Definition: geo.cpp:270
int get_distance_to_arc(struct crosstrack_error_s *crosstrack_error, double lat_now, double lon_now, double lat_center, double lon_center, float radius, float arc_start_bearing, float arc_sweep)
Definition: geo.cpp:419
bool map_projection_global_initialized()
Checks if global projection was initialized.
Definition: geo.cpp:63
Dual< Scalar, N > asin(const Dual< Scalar, N > &a)
Definition: Dual.hpp:301
constexpr T degrees(T radians)
Definition: Limits.hpp:91
#define FLT_EPSILON
static struct map_projection_reference_s mp_ref
Definition: geo.cpp:60
int map_projection_init_timestamped(struct map_projection_reference_s *ref, double lat_0, double lon_0, uint64_t timestamp)
Initializes the map transformation given by the argument.
Definition: geo.cpp:90
uint64_t map_projection_timestamp(const struct map_projection_reference_s *ref)
Get the timestamp of the map projection given by the argument.
Definition: geo.cpp:78
Type wrap_2pi(Type x)
Wrap value in range [0, 2π)
#define ecl_absolute_time()
Definition: ecl.h:85
float bearing
Definition: geo.h:71
uint64_t timestamp
Definition: geo.h:76
Dual< Scalar, N > cos(const Dual< Scalar, N > &a)
Definition: Dual.hpp:286
int map_projection_reproject(const struct map_projection_reference_s *ref, float x, float y, double *lat, double *lon)
Transforms a point in the local azimuthal equidistant plane to the geographic coordinate system using...
Definition: geo.cpp:166
void waypoint_from_heading_and_distance(double lat_start, double lon_start, float bearing, float dist, double *lat_target, double *lon_target)
Creates a waypoint from given waypoint, distance and bearing see http://www.movable-type.co.uk/scripts/latlong.html.
Definition: geo.cpp:303
int map_projection_global_getref(double *lat_0, double *lon_0)
Get reference position of the global map projection.
Definition: geo.cpp:194
constexpr T radians(T degrees)
Definition: Limits.hpp:85
Vector< float, 6 > f(float t, const Matrix< float, 6, 1 > &, const Matrix< float, 3, 1 > &)
Definition: integration.cpp:8
void add_vector_to_global_position(double lat_now, double lon_now, float v_n, float v_e, double *lat_res, double *lon_res)
Definition: geo.cpp:364
float get_bearing_to_next_waypoint(double lat_now, double lon_now, double lat_next, double lon_next)
Returns the bearing to the next waypoint in radians.
Definition: geo.cpp:320
Type wrap_pi(Type x)
Wrap value in range [-π, π)
uint64_t map_projection_global_timestamp()
Get the timestamp of the global map projection.
Definition: geo.cpp:73
int map_projection_global_reproject(float x, float y, double *lat, double *lon)
Transforms a point in the local azimuthal equidistant plane to the geographic coordinate system using...
Definition: geo.cpp:161
void create_waypoint_from_line_and_dist(double lat_A, double lon_A, double lat_B, double lon_B, float dist, double *lat_target, double *lon_target)
Creates a new waypoint C on the line of two given waypoints (A, B) at certain distance from waypoint ...
Definition: geo.cpp:285
int globallocalconverter_toglobal(float x, float y, float z, double *lat, double *lon, float *alt)
Convert from local position coordinates to global position coordinates using the global reference...
Definition: geo.cpp:241
static struct globallocal_converter_reference_s gl_ref
Definition: geo.cpp:61
int map_projection_reference(const struct map_projection_reference_s *ref, double *ref_lat_rad, double *ref_lon_rad)
Writes the reference values of the projection given by the argument to ref_lat and ref_lon...
Definition: geo.cpp:115
int globallocalconverter_tolocal(double lat, double lon, float alt, float *x, float *y, float *z)
Convert from global position coordinates to local position coordinates using the global reference...
Definition: geo.cpp:229
int map_projection_project(const struct map_projection_reference_s *ref, double lat, double lon, float *x, float *y)
Definition: geo.cpp:132
#define M_PI
Definition: gps_helper.cpp:38
int map_projection_global_init(double lat_0, double lon_0, uint64_t timestamp)
Initializes the global map transformation.
Definition: geo.cpp:84
bool globallocalconverter_initialized()
Checks if globallocalconverter was initialized.
Definition: geo.cpp:224
float distance
Definition: geo.h:70
void get_vector_to_next_waypoint_fast(double lat_now, double lon_now, double lat_next, double lon_next, float *v_n, float *v_e)
Definition: geo.cpp:349
#define M_PI_F
Definition: ashtech.cpp:44
bool past_end
Definition: geo.h:69
int get_distance_to_line(struct crosstrack_error_s *crosstrack_error, double lat_now, double lon_now, double lat_start, double lon_start, double lat_end, double lon_end)
Definition: geo.cpp:375
int map_projection_global_project(double lat, double lon, float *x, float *y)
Transforms a point in the geographic coordinate system to the local azimuthal equidistant plane using...
Definition: geo.cpp:127
int map_projection_init(struct map_projection_reference_s *ref, double lat_0, double lon_0)
Initializes the map transformation given by the argument and sets the timestamp to now...
Definition: geo.cpp:105
Dual< Scalar, N > sin(const Dual< Scalar, N > &a)
Definition: Dual.hpp:279
Dual< Scalar, N > sqrt(const Dual< Scalar, N > &a)
Definition: Dual.hpp:188
Dual< Scalar, N > atan2(const Dual< Scalar, N > &a, const Dual< Scalar, N > &b)
Definition: Dual.hpp:325