00001
00002
00003
00004
00005
00006
00007
00008
00009 #include "soarkernel.h"
00010 #include <math.h>
00011 #include <time.h>
00012 #include <ctype.h>
00013 #include <string.h>
00014
00015 #include "rhsfun.h"
00016 #include "rhsfun_examples.h"
00017
00018
00019 #ifndef M_PI
00020 #define M_PI 3.14159265358979323846
00021 #endif
00022
00023
00024 long normalize_heading_int(long n)
00025 {
00026
00027
00028
00029
00030 while (n <= -180)
00031 n += 360;
00032 while (n > 180)
00033 n -= 360;
00034
00035 return n;
00036 }
00037
00038
00039 float normalize_heading_float(float n)
00040 {
00041
00042
00043
00044
00045 while (n <= -180.0)
00046 n += 360.0;
00047 while (n > 180.0)
00048 n -= 360.0;
00049
00050 return n;
00051 }
00052
00053 long round_off_heading_int(long n, long m)
00054 {
00055 long unbounded_rounded;
00056
00057
00058 if (n < 0)
00059 unbounded_rounded = m * (long) ((n - (long) (m / 2)) / m);
00060 else
00061 unbounded_rounded = m * (long) ((n + (long) (m / 2)) / m);
00062
00063 return unbounded_rounded;
00064 }
00065
00066 float round_off_heading_float(float n, float m)
00067 {
00068 float n_10, m_10, unbounded_rounded;
00069 double ip;
00070 double ip2;
00071
00072
00073
00074 modf((n * 10.0), &ip);
00075 n_10 = (float) ip;
00076 modf((m * 10.0), &ip);
00077 m_10 = (float) ip;
00078
00079 if (n_10 < 0.0) {
00080
00081 modf((m_10 / 2.0), &ip2);
00082 modf(((n_10 - ip2) / m_10), &ip);
00083 unbounded_rounded = (float) (m_10 * ip);
00084 } else {
00085
00086 modf((m_10 / 2.0), &ip2);
00087 modf(((n_10 + ip2) / m_10), &ip);
00088 unbounded_rounded = (float) (m_10 * ip);
00089 }
00090
00091
00092 return (float) (unbounded_rounded / 10.0);
00093 }
00094
00095 Symbol *round_off_heading_air_rhs_function_code(list * args)
00096 {
00097 Symbol *arg;
00098 float n = 0, f_m = 0;
00099 long i_m = 0;
00100 cons *c;
00101 bool float_found = FALSE;
00102
00103 if (!args) {
00104 print("Error: 'round_off_heading' function called with no arguments\n");
00105 return NIL;
00106 }
00107
00108 if (!args->rest) {
00109
00110 print("Error: 'round_off_heading' function called with only one argument.\n");
00111 return NIL;
00112 }
00113
00114
00115 arg = args->first;
00116 if (arg->common.symbol_type == INT_CONSTANT_SYMBOL_TYPE)
00117 n = (float) arg->ic.value;
00118 else if (arg->common.symbol_type == FLOAT_CONSTANT_SYMBOL_TYPE) {
00119 n = arg->fc.value;
00120 }
00121
00122 c = args->rest;
00123 if (c->rest) {
00124
00125 print("Error: 'round_off_heading' function called with more than two arguments.\n");
00126 return NIL;
00127 }
00128 arg = c->first;
00129 if (arg->common.symbol_type == INT_CONSTANT_SYMBOL_TYPE)
00130 i_m = (long) arg->ic.value;
00131 else if (arg->common.symbol_type == FLOAT_CONSTANT_SYMBOL_TYPE) {
00132 float_found = TRUE;
00133 f_m = arg->fc.value;
00134 }
00135
00136
00137 if (float_found)
00138 return make_float_constant(normalize_heading_float(round_off_heading_float(n, f_m)));
00139 else
00140 return make_int_constant(normalize_heading_int(round_off_heading_int((long) n, i_m)));
00141
00142 }
00143
00144
00145
00146
00147
00148
00149
00150
00151 Symbol *round_off_air_rhs_function_code(list * args)
00152 {
00153 Symbol *arg;
00154 float n = 0, f_m = 0;
00155 long i_m = 0;
00156 cons *c;
00157 bool float_found = FALSE;
00158
00159 if (!args) {
00160 print("Error: 'round_off' function called with no arguments\n");
00161 return NIL;
00162 }
00163
00164 if (!args->rest) {
00165
00166 print("Error: 'round_off' function called with only one argument.\n");
00167 return NIL;
00168 }
00169
00170
00171 arg = args->first;
00172 if (arg->common.symbol_type == INT_CONSTANT_SYMBOL_TYPE)
00173 n = (float) arg->ic.value;
00174 else if (arg->common.symbol_type == FLOAT_CONSTANT_SYMBOL_TYPE) {
00175 n = arg->fc.value;
00176 }
00177
00178 c = args->rest;
00179 if (c->rest) {
00180
00181 print("Error: 'round_off' function called with more than two arguments.\n");
00182 return NIL;
00183 }
00184 arg = c->first;
00185 if (arg->common.symbol_type == INT_CONSTANT_SYMBOL_TYPE)
00186 i_m = arg->ic.value;
00187 else if (arg->common.symbol_type == FLOAT_CONSTANT_SYMBOL_TYPE) {
00188 float_found = TRUE;
00189 f_m = arg->fc.value;
00190 }
00191
00192
00193 if (float_found)
00194 return make_float_constant(round_off_heading_float(n, f_m));
00195 else
00196 return make_int_constant(round_off_heading_int((long) n, i_m));
00197 }
00198
00199 typedef double float64;
00200 #define PI 3.141592653589
00201 #define PI_OVER_TWO (PI/2)
00202 #define TWO_PI (PI*2)
00203 #define RAD_TO_DEG(X) ((X*180)/PI)
00204 #define X 0
00205 #define Y 1
00206 #define Z 2
00207
00208 void vector_from_to_position(float64 pos1[3], float64 pos2[3], float64 vector[3])
00209 {
00210 vector[X] = pos2[X] - pos1[X];
00211 vector[Y] = pos2[Y] - pos1[Y];
00212 vector[Z] = pos2[Z] - pos1[Z];
00213 }
00214
00215 void vec2_norm(float64 v[3], float64 r[3], int abort)
00216 {
00217 float64 mag, mag2;
00218 mag2 = v[X] * v[X] + v[Y] * v[Y];
00219 mag = sqrt(mag2);
00220 if (!abort && (mag < 0.01)) {
00221 r[0] = 1.0;
00222 r[1] = 0.0;
00223 return;
00224 }
00225 r[0] = v[0] / mag;
00226 r[1] = v[1] / mag;
00227 }
00228
00229 float64 convert_to_soar_angle(float64 heading_in_rads)
00230 {
00231 double heading;
00232
00233
00234 heading = heading_in_rads - PI_OVER_TWO;
00235 if (heading < 0.0)
00236 heading += TWO_PI;
00237 heading = TWO_PI - heading;
00238 if (heading > PI)
00239 heading -= TWO_PI;
00240
00241 return heading;
00242 }
00243
00244 void hrl_xydof_to_heading(float64 xydof[3], float64 * output)
00245 {
00246 float64 heading_in_rads;
00247
00248 heading_in_rads = convert_to_soar_angle(atan2(xydof[Y], xydof[X]));
00249
00250 (*output) = heading_in_rads;
00251 }
00252
00253 long air_soar_round_off_angle(long n, long m)
00254 {
00255 long unbounded_rounded, bounded_rounded;
00256
00257
00258 if (n < 0)
00259 unbounded_rounded = m * (long) ((n - (long) (m / 2)) / m);
00260 else
00261 unbounded_rounded = m * (long) ((n + (long) (m / 2)) / m);
00262
00263
00264
00265 bounded_rounded = (unbounded_rounded % 360);
00266 if (bounded_rounded > 180)
00267 bounded_rounded -= 360;
00268 if (bounded_rounded <= -180)
00269 bounded_rounded += 360;
00270
00271 return bounded_rounded;
00272 }
00273
00274 float64 bracket_rad_to_deg(float64 var)
00275 {
00276 return (float64) air_soar_round_off_angle((long) RAD_TO_DEG(var), 1);
00277 }
00278
00279 long convert(float64 flo)
00280 {
00281 long tempx;
00282 tempx = (long) flo;
00283 return tempx;
00284 }
00285
00286 long heading_to_point(long current_x, long current_y, long x, long y)
00287 {
00288 float64 plane_pos[3], waypoint_pos[3], dir[3];
00289 float64 heading;
00290
00291 plane_pos[0] = (float64) current_x;
00292 plane_pos[1] = (float64) current_y;
00293 plane_pos[2] = 0;
00294
00295 waypoint_pos[0] = (float64) x;
00296 waypoint_pos[1] = (float64) y;
00297 waypoint_pos[2] = 0;
00298
00299 vector_from_to_position(plane_pos, waypoint_pos, dir);
00300 vec2_norm(dir, dir, FALSE);
00301 hrl_xydof_to_heading(dir, &heading);
00302
00303 return convert(bracket_rad_to_deg(heading));
00304 }
00305
00306
00307
00308
00309
00310
00311
00312 Symbol *compute_heading_rhs_function_code(list * args)
00313 {
00314 Symbol *arg;
00315 long current_x, current_y;
00316 long waypoint_x, waypoint_y;
00317 int count;
00318 cons *c;
00319
00320 if (!args) {
00321 print("Error: 'compute-heading' function called with no arguments\n");
00322 return NIL;
00323 }
00324
00325 for (c = args; c != NIL; c = c->rest) {
00326 arg = c->first;
00327 if ((arg->common.symbol_type != INT_CONSTANT_SYMBOL_TYPE) &&
00328 (arg->common.symbol_type != FLOAT_CONSTANT_SYMBOL_TYPE)) {
00329 print_with_symbols("Error: non-number (%y) passed to - compute-heading\n", arg);
00330 return NIL;
00331 }
00332 }
00333
00334 count = 1;
00335
00336 for (c = args->rest; c != NIL; c = c->rest) {
00337 arg = c->first;
00338 if ((arg->common.symbol_type != INT_CONSTANT_SYMBOL_TYPE) &&
00339 (arg->common.symbol_type != FLOAT_CONSTANT_SYMBOL_TYPE)) {
00340 print_with_symbols("Error: non-number (%y) passed to compute-heading function.\n", arg);
00341 return NIL;
00342 } else {
00343 count++;
00344 }
00345 }
00346
00347 if (count != 4) {
00348 print("Error: 'compute-heading' takes exactly 4 arguments.\n");
00349 return NIL;
00350 }
00351
00352 arg = args->first;
00353 current_x = (arg->common.symbol_type == INT_CONSTANT_SYMBOL_TYPE) ? arg->ic.value : (long) arg->fc.value;
00354
00355 arg = args->rest->first;
00356 current_y = (arg->common.symbol_type == INT_CONSTANT_SYMBOL_TYPE) ? arg->ic.value : (long) arg->fc.value;
00357
00358 arg = args->rest->rest->first;
00359 waypoint_x = (arg->common.symbol_type == INT_CONSTANT_SYMBOL_TYPE) ? arg->ic.value : (long) arg->fc.value;
00360
00361 arg = args->rest->rest->rest->first;
00362 waypoint_y = (arg->common.symbol_type == INT_CONSTANT_SYMBOL_TYPE) ? arg->ic.value : (long) arg->fc.value;
00363
00364 return make_int_constant(heading_to_point(current_x, current_y, waypoint_x, waypoint_y));
00365 }
00366
00367
00368
00369
00370
00371
00372
00373 Symbol *compute_range_rhs_function_code(list * args)
00374 {
00375 Symbol *arg;
00376 double current_x, current_y;
00377 double waypoint_x, waypoint_y;
00378 int count;
00379 cons *c;
00380
00381 if (!args) {
00382 print("Error: 'compute-range' function called with no arguments\n");
00383 return NIL;
00384 }
00385
00386 for (c = args; c != NIL; c = c->rest) {
00387 arg = c->first;
00388 if ((arg->common.symbol_type != INT_CONSTANT_SYMBOL_TYPE)
00389 && (arg->common.symbol_type != FLOAT_CONSTANT_SYMBOL_TYPE)) {
00390 print_with_symbols("Error: non-number (%y) passed to - compute-range\n", arg);
00391 return NIL;
00392 }
00393 }
00394
00395 count = 1;
00396
00397 for (c = args->rest; c != NIL; c = c->rest) {
00398 arg = c->first;
00399 if ((arg->common.symbol_type != INT_CONSTANT_SYMBOL_TYPE)
00400 && (arg->common.symbol_type != FLOAT_CONSTANT_SYMBOL_TYPE)) {
00401 print_with_symbols("Error: non-number (%y) passed to compute-range function.\n", arg);
00402 return NIL;
00403 } else {
00404 count++;
00405 }
00406 }
00407
00408 if (count != 4) {
00409 print("Error: 'compute-range' takes exactly 4 arguments.\n");
00410 return NIL;
00411 }
00412
00413 arg = args->first;
00414 current_x = (arg->common.symbol_type == INT_CONSTANT_SYMBOL_TYPE) ? (double) arg->ic.value : arg->fc.value;
00415
00416 arg = args->rest->first;
00417 current_y = (arg->common.symbol_type == INT_CONSTANT_SYMBOL_TYPE) ? (double) arg->ic.value : arg->fc.value;
00418
00419 arg = args->rest->rest->first;
00420 waypoint_x = (arg->common.symbol_type == INT_CONSTANT_SYMBOL_TYPE) ? (double) arg->ic.value : arg->fc.value;
00421
00422 arg = args->rest->rest->rest->first;
00423 waypoint_y = (arg->common.symbol_type == INT_CONSTANT_SYMBOL_TYPE) ? (double) arg->ic.value : arg->fc.value;
00424
00425 return make_int_constant((long int) sqrt((current_x - waypoint_x)
00426 * (current_x - waypoint_x)
00427 + (current_y - waypoint_y)
00428 * (current_y - waypoint_y)));
00429 }
00430
00431
00432
00433 void add_bot_rhs_functions()
00434 {
00435 add_rhs_function(make_sym_constant("round-off-heading"), round_off_heading_air_rhs_function_code, 2, TRUE, FALSE);
00436 add_rhs_function(make_sym_constant("round-off"), round_off_air_rhs_function_code, 2, TRUE, FALSE);
00437
00438 add_rhs_function(make_sym_constant("compute-heading"), compute_heading_rhs_function_code, 4, TRUE, FALSE);
00439
00440 add_rhs_function(make_sym_constant("compute-range"), compute_range_rhs_function_code, 4, TRUE, FALSE);
00441 }
00442
00443 void remove_bot_rhs_functions()
00444 {
00445 remove_rhs_function(make_sym_constant("round-off-heading"));
00446 remove_rhs_function(make_sym_constant("round-off"));
00447 remove_rhs_function(make_sym_constant("compute-heading"));
00448 remove_rhs_function(make_sym_constant("compute-range"));
00449 }