gucoordinates
conversions.c
Go to the documentation of this file.
1/*
2 * conversions.c
3 * gunavigation
4 *
5 * Created by Callum McColl on 19/06/2020.
6 * Copyright © 2020 Callum McColl. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 *
15 * 2. Redistributions in binary form must reproduce the above
16 * copyright notice, this list of conditions and the following
17 * disclaimer in the documentation and/or other materials
18 * provided with the distribution.
19 *
20 * 3. All advertising materials mentioning features or use of this
21 * software must display the following acknowledgement:
22 *
23 * This product includes software developed by Callum McColl.
24 *
25 * 4. Neither the name of the author nor the names of contributors
26 * may be used to endorse or promote products derived from this
27 * software without specific prior written permission.
28 *
29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
33 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
34 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
35 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
36 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
37 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
38 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
39 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 *
41 * -----------------------------------------------------------------------
42 * This program is free software; you can redistribute it and/or
43 * modify it under the above terms or under the terms of the GNU
44 * General Public License as published by the Free Software Foundation;
45 * either version 2 of the License, or (at your option) any later version.
46 *
47 * This program is distributed in the hope that it will be useful,
48 * but WITHOUT ANY WARRANTY; without even the implied warranty of
49 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
50 * GNU General Public License for more details.
51 *
52 * You should have received a copy of the GNU General Public License
53 * along with this program; if not, see http://www.gnu.org/licenses/
54 * or write to the Free Software Foundation, Inc., 51 Franklin Street,
55 * Fifth Floor, Boston, MA 02110-1301, USA.
56 *
57 */
58
59#include "conversions.h"
60#include "hidden_conversions.h"
61#include <math.h>
62#include <float.h>
63
64#include <stdio.h>
65
66/*#ifndef M_PI
67 #define M_PI 3.14159265358979323846
68#endif*/
69#ifndef M_PI_2
70 #define M_PI_2 1.57079632679489661923
71#endif
72
73#define RELATIVE_COORD_MAX_DISTANCE f_to_mm_u(FLT_MAX)
74
76{
77 const pixels_u maxX = coord.res_width - 1;
78 const pixels_t x = px_u_to_px_t(coord.x) - d_to_px_t(floor(px_u_to_d(maxX) / 2.0));
79 const pixels_u maxY = coord.res_height - 1;
80 const pixels_t y = px_u_to_px_t(maxY - coord.y) - d_to_px_t(floor(px_u_to_d(maxY) / 2.0));
81 const gu_pixel_coordinate out = { x, y, coord.res_width, coord.res_height };
82 return out;
83}
84
86{
87 const pixels_u maxX = coord.res_width - 1;
88 const pixels_u x = px_t_to_px_u(coord.x + d_to_px_t(floor(px_u_to_d(maxX) / 2.0)));
89 const pixels_u maxY = coord.res_height - 1;
90 const pixels_u y = px_t_to_px_u(-coord.y - d_to_px_t(floor(px_u_to_d(maxY) / 2.0)) + px_u_to_px_t(maxY));
91 const gu_camera_coordinate out = { x, y, coord.res_width, coord.res_height };
92 return out;
93}
94
96{
97 const pixels_t maxX = px_u_to_px_t(coord.res_width) - 1;
98 const pixels_t maxY = px_u_to_px_t(coord.res_height) - 1;
99 const double x = px_t_to_d(2 * coord.x - (maxX % 2)) / px_t_to_d(maxX);
100 const double y = px_t_to_d(2 * coord.y - (maxY % 2)) / px_t_to_d(maxY);
101 const gu_percent_coordinate newCoord = { d_to_pct_d(x), d_to_pct_d(y) };
102 return newCoord;
103}
104
105gu_pixel_coordinate pct_coord_to_px_coord(const gu_percent_coordinate coord, const pixels_u res_width, const pixels_u res_height)
106{
107 const pixels_t maxX = px_u_to_px_t(res_width) - 1;
108 const pixels_t maxY = px_u_to_px_t(res_height) - 1;
109 const double pixelsX = (pct_d_to_d(coord.x) * px_t_to_d(maxX) + px_t_to_d(maxX % 2)) / 2.0;
110 const double pixelsY = (pct_d_to_d(coord.y) * px_t_to_d(maxY) + px_t_to_d(maxY % 2)) / 2.0;
111 const gu_pixel_coordinate newCoord = { d_to_px_t(pixelsX), d_to_px_t(pixelsY), res_width, res_height };
112 return newCoord;
113}
114
115gu_relative_coordinate pct_coord_to_rr_coord(const gu_percent_coordinate coord, const gu_camera_pivot camera_pivot, const int cameraOffset)
116{
117 const gu_camera camera = camera_pivot.cameras[cameraOffset];
118 const degrees_d pitchToObject = camera_pivot.pitch + camera.vDirection - d_to_deg_d(pct_d_to_d(coord.y)) * (camera.vFov / 2.0);
119 const degrees_d yaw = camera_pivot.yaw - d_to_deg_d(pct_d_to_d(coord.x)) * (camera.hFov / 2.0);
120 // If the object is below/behind the camera.
121 if (pitchToObject >= 90.0)
122 {
123 const gu_relative_coordinate out = { yaw, 0 };
124 return out;
125 }
126 const radians_d pitchRad = deg_d_to_rad_d(pitchToObject);
127 const radians_d yawRad = deg_d_to_rad_d(yaw);
128 const double cosYaw = cos(rad_d_to_d(yawRad));
129 // Is the pitch above the horizontal or are we going to have to devide by zero later on?
130 if (pitchToObject <= 0.0 || fabs(cosYaw) < 0.00001)
131 {
133 return out;
134 }
135 const centimetres_d actualCameraHeight = gu_camera_pivot_calculate_camera_height(camera_pivot, cameraOffset);
136 const double distance = cm_d_to_d(actualCameraHeight) * tan((M_PI_2) - rad_d_to_d(pitchRad)) / cosYaw;
137 const centimetres_d outDistance = d_to_cm_d(distance) - camera.centerOffset;
138 const gu_relative_coordinate out = { yaw, cm_d_to_mm_u(fabs(outDistance)) };
139 return out;
140}
141
142gu_percent_coordinate rr_coord_to_pct_coord(const gu_relative_coordinate coord, const gu_camera_pivot camera_pivot, const int cameraOffset)
143{
144 const gu_camera camera = camera_pivot.cameras[cameraOffset];
145 const degrees_d yaw = coord.direction - camera_pivot.yaw;
146 const percent_d x = d_to_pct_d(deg_d_to_d(-yaw / (camera.hFov / 2.0)));
147 const radians_d yawRad = deg_d_to_rad_d(coord.direction);
148 const double frontDistance = cm_d_to_d(mm_u_to_cm_d(coord.distance)) * cos(rad_d_to_d(yawRad)) + cm_d_to_d(camera.centerOffset);
149 const centimetres_d actualCameraHeight = gu_camera_pivot_calculate_camera_height(camera_pivot, cameraOffset);
150 const degrees_d totalPitch = 90.0 - rad_d_to_deg_d(d_to_rad_d(atan2(frontDistance, cm_d_to_d(actualCameraHeight))));
151 const degrees_d pitch = totalPitch - camera.vDirection - camera_pivot.pitch;
152 const percent_d y = d_to_pct_d(deg_d_to_d(-pitch / (camera.vFov / 2.0)));
153 const gu_percent_coordinate temp = { x, y };
154 return temp;
155}
156
158{
159 gu_percent_coordinate temp = rr_coord_to_pct_coord(coord, camera_pivot, cameraOffset);
160 if (temp.x < -1.0)
161 {
162 temp.x = -1.0;
163 }
164 else if (temp.x > 1.0) {
165 temp.x = 1.0;
166 }
167 if (temp.y < -1.0)
168 {
169 temp.y = -1.0;
170 }
171 else if (temp.y > 1.0) {
172 temp.y = 1.0;
173 }
174 return temp;
175}
176
178{
179 const double distance = mm_u_to_d(coord.distance);
180 const double rads = rad_d_to_d(deg_d_to_rad_d(coord.direction));
181 const gu_cartesian_coordinate out = {
182 d_to_mm_t(distance * cos(rads)),
183 d_to_mm_t(distance * sin(rads))
184 };
185 return out;
186}
187
189{
191 temp.x = source.x + temp.x;
192 temp.y = source.y + temp.y;
193 return temp;
194}
195
197{
198 const gu_relative_coordinate offset = { coord.direction + deg_t_to_deg_d(source.heading), coord.distance };
200}
201
203{
206 out.position = temp;
207 out.heading = heading;
208 return out;
209}
210
212{
213 gu_relative_coordinate temp = coord;
214 temp.direction = deg_t_to_deg_d(source.heading) + temp.direction;
216 const gu_field_coordinate out = { .position = position, .heading = heading };
217 return out;
218}
219
221{
222 const gu_cartesian_coordinate zero = { 0, 0 };
223 return cartesian_coord_to_rr_coord_from_source(zero, target);
224}
225
227{
228 const radians_d angle = angle_between_points(source, target);
229 const millimetres_d distance = distance_between_points(source, target);
230 const gu_relative_coordinate out = {
231 rad_d_to_deg_d(angle),
232 mm_d_to_mm_u(fabs(distance))
233 };
234 return out;
235}
236
238{
240 out.direction = normalise_deg_d(out.direction - deg_t_to_deg_d(source.heading));
241 return out;
242}
243
245{
246 const millimetres_t dx = p2.x - p1.x;
247 const millimetres_t dy = p2.y - p1.y;
248 if (0 == dx) {
249 if (0 == dy) {
250 return 0.0;
251 }
252 return dy > 0 ? d_to_rad_d(90.0) : d_to_rad_d(-90.0);
253 }
254 return d_to_rad_d(atan2(mm_t_to_d(dy), mm_t_to_d(dx)));
255}
256
258{
259 const gu_cartesian_coordinate dpoint = { point2.x - point1.x, point2.y - point1.y };
260 // Horizontal Lines
261 if (0 == dpoint.x) {
262 return fabs(mm_t_to_d(dpoint.y));
263 }
264 // Veritcal Lines
265 if (0 == dpoint.y) {
266 return fabs(mm_t_to_d(dpoint.x));
267 }
268 return d_to_mm_d(sqrt(mm_t_to_d(dpoint.x * dpoint.x) + mm_t_to_d(dpoint.y * dpoint.y)));
269}
270
271degrees_d normalise_deg_d(degrees_d angle) {
272 if (angle + 180.0 == 0.0)
273 {
274 return 180.0;
275 }
276 if (angle < 0) {
277 angle = fmod(angle, -360);
278 } else {
279 angle = fmod(angle, 360);
280 }
281 if (angle < -180) {
282 return angle + 360;
283 }
284 if (angle > 180) {
285 return angle - 360;
286 }
287 return angle;
288}
289
290degrees_t normalise_deg_t(degrees_t angle) {
291 return deg_d_to_deg_t(normalise_deg_d(deg_t_to_deg_d(angle)));
292}
293
294radians_d normalise_rad_d(radians_d angle) {
295 return deg_d_to_rad_d(normalise_deg_d(rad_d_to_deg_d(angle)));
296}
centimetres_d gu_camera_pivot_calculate_camera_height(const gu_camera_pivot camera_pivot, const int cameraOffset)
Definition: camera_pivot.c:83
gu_percent_coordinate px_coord_to_pct_coord(const gu_pixel_coordinate coord)
Definition: conversions.c:95
gu_cartesian_coordinate rr_coord_to_cartesian_coord(const gu_relative_coordinate coord)
Definition: conversions.c:177
gu_percent_coordinate clamped_rr_coord_to_pct_coord(const gu_relative_coordinate coord, const gu_camera_pivot camera_pivot, const int cameraOffset)
Definition: conversions.c:157
radians_d angle_between_points(const gu_cartesian_coordinate p1, const gu_cartesian_coordinate p2)
Definition: conversions.c:244
gu_relative_coordinate cartesian_coord_to_rr_coord_from_source(const gu_cartesian_coordinate source, const gu_cartesian_coordinate target)
Definition: conversions.c:226
degrees_t normalise_deg_t(degrees_t angle)
Definition: conversions.c:290
gu_cartesian_coordinate rr_coord_to_cartesian_coord_from_source(const gu_relative_coordinate coord, const gu_cartesian_coordinate source)
Definition: conversions.c:188
#define RELATIVE_COORD_MAX_DISTANCE
Definition: conversions.c:73
gu_field_coordinate rr_coord_to_field_coord_from_source(const gu_relative_coordinate coord, const gu_field_coordinate source, const degrees_t heading)
Definition: conversions.c:211
gu_camera_coordinate px_coord_to_cam_coord(const gu_pixel_coordinate coord)
Definition: conversions.c:85
gu_pixel_coordinate pct_coord_to_px_coord(const gu_percent_coordinate coord, const pixels_u res_width, const pixels_u res_height)
Definition: conversions.c:105
gu_cartesian_coordinate rr_coord_to_cartesian_coord_from_field(const gu_relative_coordinate coord, const gu_field_coordinate source)
Definition: conversions.c:196
#define M_PI_2
Definition: conversions.c:70
gu_relative_coordinate pct_coord_to_rr_coord(const gu_percent_coordinate coord, const gu_camera_pivot camera_pivot, const int cameraOffset)
Definition: conversions.c:115
millimetres_d distance_between_points(const gu_cartesian_coordinate point1, const gu_cartesian_coordinate point2)
Definition: conversions.c:257
gu_pixel_coordinate cam_coord_to_px_coord(const gu_camera_coordinate coord)
Definition: conversions.c:75
degrees_d normalise_deg_d(degrees_d angle)
Definition: conversions.c:271
gu_percent_coordinate rr_coord_to_pct_coord(const gu_relative_coordinate coord, const gu_camera_pivot camera_pivot, const int cameraOffset)
Definition: conversions.c:142
radians_d normalise_rad_d(radians_d angle)
Definition: conversions.c:294
gu_relative_coordinate cartesian_coord_to_rr_coord(const gu_cartesian_coordinate target)
Definition: conversions.c:220
gu_relative_coordinate field_coord_to_rr_coord_to_target(const gu_field_coordinate source, const gu_cartesian_coordinate target)
Definition: conversions.c:237
gu_field_coordinate rr_coord_to_field_coord(const gu_relative_coordinate coord, const degrees_t heading)
Definition: conversions.c:202
A gu_camera_coordinate represents the coordinate of a pixel within an image where the (0,...
pixels_u x
The x coordinate of the pixel within the image.
pixels_u res_height
The height of the resolution of the image.
pixels_u res_width
The width of the resolution of the image.
pixels_u y
The y coordinate of the pixel within the image.
A gu_camera_pivot represents the pivot point which a gu_camera is attached to.
Definition: camera_pivot.h:87
degrees_d pitch
The vertical orientation of the pivot point.
Definition: camera_pivot.h:92
degrees_d yaw
The horizontal orientation of the pivot point.
Definition: camera_pivot.h:97
gu_camera cameras[2]
The gu_cameras attached to this pivot point.
Definition: camera_pivot.h:107
centimetres_d centerOffset
The distance the camera is from the center point.
Definition: camera.h:92
degrees_d hFov
The horizontal field of view.
Definition: camera.h:110
degrees_d vFov
The vertical field of view.
Definition: camera.h:105
degrees_d vDirection
The degree in which the camera is facing in the vertical direction.
Definition: camera.h:100
A cartesian_coordinate is a general coordinate for representing positions on a tow dimensional plane.
millimetres_t y
The y coordinate of the position in centimetres.
millimetres_t x
The x coordinate of the position in centimetres.
A field_coordinate is a coordinate for an object that faces a certain direction (such as a robot) on ...
degrees_t heading
The direction where the object is facing.
gu_cartesian_coordinate position
The position of the object on the field.
A gu_percent_coordinate represents the coordinate of a pixel within an image.
percent_d y
The y coordinate of the pixel within the image as a percentage.
percent_d x
The x coordinate of the pixel within the image as a percentage.
A gu_pixel_coordinate represents the coordinate of a pixel within an image.
pixels_u res_height
The height of the resolution of the image.
pixels_t x
The x coordinate of the pixel within the image.
pixels_u res_width
The width of the resolution of the image.
pixels_t y
The y coordinate of the pixel within the image.
A coordinate that is relative to some other coordinate.
degrees_d direction
The heading towards the coordinate.
millimetres_u distance
The distance to the coordinate.