diff --git a/ovm/ovm.c b/ovm/ovm.c index aa6e314..d321c69 100644 --- a/ovm/ovm.c +++ b/ovm/ovm.c @@ -3,6 +3,7 @@ #include #undef CMPEPS +// #define CMPEPS void ovm_free(ovm_t *ovm) { if (!ovm) return; @@ -82,7 +83,7 @@ void ovm_print_c(ovm_t *ovm, const gchar *filename) { break; case SOP_CMPZ: switch (instr_sop_cmp(oi[i])) { -#if CMPEPS /* cmp with eps */ +#ifdef CMPEPS /* cmp with eps */ case CMP_LTZ: g_string_printf(str, "\tovm_status = (v%u.d < -eps);\n", USED(instr_sop_r1(oi[i]))); break; @@ -142,7 +143,7 @@ void ovm_print_c(ovm_t *ovm, const gchar *filename) { g_string_printf(str, "\tv%u.d = v%u.d * v%u.d;\n", USED(i), USED(instr_dop_r1(oi[i])), USED(instr_dop_r2(oi[i]))); break; case OP_DIV: -#if CMPEPS +#ifdef CMPEPS g_string_printf(str, "\tv%u.d = (fabs(v%u.d) < eps) ? 0.0 : v%u.d / v%u.d;\n", USED(i), USED(instr_dop_r2(oi[i])), USED(instr_dop_r1(oi[i])), instr_dop_r2(oi[i])); #else g_string_printf(str, "\tv%u.d = (v%u.d == 0) ? 0.0 : v%u.d / v%u.d;\n", USED(i), USED(instr_dop_r2(oi[i])), USED(instr_dop_r1(oi[i])), instr_dop_r2(oi[i])); @@ -173,7 +174,7 @@ void ovm_print_c(ovm_t *ovm, const gchar *filename) { "static gboolean ovm_status;\n" "\n" )); -#if CMPEPS +#ifdef CMPEPS write(f, CONST_STR_LEN( "static const gdouble eps = 1e-300;\n" "\n" diff --git a/ovm/physics.h b/ovm/physics.h index 8dfe8dc..1dfa664 100644 --- a/ovm/physics.h +++ b/ovm/physics.h @@ -9,5 +9,57 @@ #define Me 6.0e24 #define Re 6.357e6 +typedef struct { + gdouble x, y; +} vector_t; + +typedef struct { + vector_t g, v; + gdouble v_abs; +} move_data_t; + +typedef struct { + vector_t pos_old, pos; + gdouble rad2_old, rad_old, rad2, rad; + vector_t dv_old, dv; + + gboolean b_old, b; /* whether the following was calculated */ + move_data_t move_old, move; +} satellite_t; + +static inline void satellite_update_pos(satellite_t *s, gdouble x, gdouble y) { + s->pos_old = s->pos; + s->rad2_old = s->rad2; + s->rad_old = s->rad; + s->dv_old = s->dv; + s->b_old = s->b; + s->move_old = s->move; + + s->pos.x = x; s->pos.y = y; + s->rad2 = s->pos.x*s->pos.x + s->pos.y*s->pos.y; + s->rad = sqrt(s->rad2); + s->dv.x = 0.0; s->dv.y = 0.0; + + s->b = FALSE; +} + +static inline void satellite_update_move(satellite_t *s) { + if (!s->b_old) { + s->move_old.g.x = -(G*Me/(s->rad2_old*s->rad_old)) * s->pos_old.x; + s->move_old.g.y = -(G*Me/(s->rad2_old*s->rad_old)) * s->pos_old.y; + s->move_old.v.x = s->pos.x - s->pos_old.x - 0.5*(s->move_old.g.x + s->dv_old.x); + s->move_old.v.y = s->pos.y - s->pos_old.y - 0.5*(s->move_old.g.y + s->dv_old.y); + s->move_old.v_abs = sqrt(s->move_old.v.x*s->move_old.v.x+s->move_old.v.y*s->move_old.v.y); + s->b_old = TRUE; + } + if (!s->b) { + s->move.g.x = -(G*Me/(s->rad2*s->rad)) * s->pos.x; + s->move.g.y = -(G*Me/(s->rad2*s->rad)) * s->pos.y; + s->move.v.x = s->move_old.v.x + s->dv_old.x + 0.5*(s->move_old.g.x + s->move.g.x); + s->move.v.y = s->move_old.v.y + s->dv_old.y + 0.5*(s->move_old.g.y + s->move.g.y); + s->move.v_abs = sqrt(s->move.v.x*s->move.v.x+s->move.v.y*s->move.v.y); + s->b = TRUE; + } +} #endif diff --git a/ovm/task.h b/ovm/task.h index a220e3f..d241476 100644 --- a/ovm/task.h +++ b/ovm/task.h @@ -9,6 +9,7 @@ typedef struct { guint in_size, out_size; gdouble *in, *out, *in_old; int tracefd; + gboolean finished; } task_t; task_t* task_new(guint scenario); diff --git a/ovm/task1.c b/ovm/task1.c index 47fced1..145ef17 100644 --- a/ovm/task1.c +++ b/ovm/task1.c @@ -14,8 +14,8 @@ Address Sensor #define SCORE (task->out[0]) #define FUEL (task->out[1]) -#define S_X (task->out[2]) -#define S_Y (task->out[3]) +#define S_X (-task->out[2]) +#define S_Y (-task->out[3]) #define RADIUS (task->out[4]) #define DV_X (task->in[2]) @@ -30,44 +30,84 @@ static void debug(task_t * task) { task->timestamp, SCORE, FUEL, S_X, S_Y, RADIUS, rad); } -gdouble init_rad, last_x, last_y; -gboolean running = FALSE, started = FALSE; -gdouble dv, dv_tic; - static void run(task_t *task, gpointer userdata) { - gdouble cur_rad; + static satellite_t sat; + static gdouble init_rad, target_v; + static gdouble dv, dv_tic; + static gboolean reached = FALSE, outoffuel = TRUE; + static guint32 reached_ts = 0; UNUSED(userdata); - if (0 == task->timestamp) return; + if (task->finished) debug(task); + if (0 == task->timestamp || task->finished) return; + + satellite_update_pos(&sat, S_X, S_Y); - cur_rad = sqrt(S_X*S_X+S_Y*S_Y); DV_X = DV_Y = 0.0; - if (!running) { - running = TRUE; - started = TRUE; - init_rad = cur_rad; - dv = sqrt(mu/init_rad)*(sqrt(2*RADIUS/(init_rad + RADIUS))-1); - dv_tic = sqrt(mu/RADIUS)*(1-sqrt(2*init_rad/(init_rad + RADIUS))); - printf("Orbit: %f -> %f; dv = %f, dv' = %f\n", init_rad, RADIUS, dv, dv_tic); - } else if (started) { - gdouble vx = S_X - last_x, vy = S_Y - last_y, v = sqrt(vx*vx+vy*vy); - started = FALSE; - DV_X = -vx * (dv / v); - DV_Y = -vy * (dv / v); -// printf("v: %f / %f\n", vx, vy); - printf("Dv: %f / %f\n", DV_X, DV_Y); - } else if (fabs(cur_rad - RADIUS) < 1000.0) { - gdouble vx = S_X - last_x, vy = S_Y - last_y, v = sqrt(vx*vx+vy*vy); - running = FALSE; - printf("Reached target radius\n"); - DV_X = -vx * (dv_tic / v); - DV_Y = -vy * (dv_tic / v); - printf("Dv: %f / %f\n", DV_X, DV_Y); + if (!reached) { + if (1 == task->timestamp) { + debug(task); + init_rad = sat.rad; + + /* v^2/r == G*M_e/r^2 => v^2 = mu/r */ + target_v = sqrt(mu/RADIUS); + + dv = sqrt(mu/init_rad)*(sqrt(2*RADIUS/(init_rad + RADIUS))-1); + dv_tic = sqrt(mu/RADIUS)*(1-sqrt(2*init_rad/(init_rad + RADIUS))); + printf("-- Orbit: %f -> %f; dv = %f, dv' = %f\n", init_rad, RADIUS, dv, dv_tic); + } else if (2 == task->timestamp) { + debug(task); + satellite_update_move(&sat); + if (sat.move.v.x * S_Y > 0.0 && sat.move.v.y * S_X < 0.0) target_v = -target_v; + DV_X = sat.move.v.x * (dv / sat.move.v_abs); + DV_Y = sat.move.v.y * (dv / sat.move.v_abs); + printf("-- Leaving initial orbit at %u\n", (guint) task->timestamp); + debug(task); + printf("v: %f / %f\n", sat.move.v.x, sat.move.v.y); + printf("Dv: %f / %f\n", DV_X, DV_Y); + } else if (fabs(sat.rad - RADIUS) < 100.0) { + satellite_update_move(&sat); + debug(task); + reached = TRUE; + DV_X = sat.move.v.x * (dv_tic / sat.move.v_abs); + DV_Y = sat.move.v.y * (dv_tic / sat.move.v_abs); + printf("-- Reached target orbit at %u\n", (guint) task->timestamp); + printf("v: %f / %f\n", sat.move.v.x, sat.move.v.y); + printf("Dv: %f / %f\n", DV_X, DV_Y); + } + } else if (!outoffuel) { + /* target_v is clockwise (TODO) */ + gdouble tar_dv_x = -target_v * S_Y / sat.rad; + gdouble tar_dv_y = target_v * S_X / sat.rad; + satellite_update_move(&sat); + DV_X = tar_dv_x - sat.move.v.x; + if (fabs(DV_X) < 0.5) DV_X = 0.0; + DV_Y = tar_dv_y - sat.move.v.y; + if (fabs(DV_Y) < 0.5) DV_Y = 0.0; + if (DV_X*DV_X + DV_Y*DV_Y > FUEL*FUEL) { + printf("-- Out of fuel\n"); + printf("v: %f / %f\n", sat.move.v.x, sat.move.v.y); + printf("Dv: %f / %f\n", DV_X, DV_Y); + DV_X = 0.0; DV_Y = 0.0; + outoffuel = TRUE; + } } - last_x = S_X; - last_y = S_Y; + if (reached_ts > 0 && fabs(sat.rad - RADIUS) >= 1000.0) { +// debug(task); + printf("-- Left target radius at %u (duration: %u)\n", (guint) task->timestamp, (guint) task->timestamp - reached_ts); + reached_ts = 0; + } else if (reached_ts == 0 && fabs(sat.rad - RADIUS) < 1000.0) { +// debug(task); + reached_ts = (guint) task->timestamp; + printf("-- Reached target radius at %u\n", (guint) task->timestamp); + } + + if (fabs(DV_X) < 0.1) DV_X = 0.0; + if (fabs(DV_Y) < 0.1) DV_Y = 0.0; + + sat.dv.x = DV_X; sat.dv.y = DV_Y; } static void run_debug(task_t *task, gpointer userdata) { diff --git a/ovm/task_main.h b/ovm/task_main.h index b960ca9..ba60bd6 100644 --- a/ovm/task_main.h +++ b/ovm/task_main.h @@ -20,7 +20,8 @@ static inline void trace_simulate(task_t *task, gpointer userdata) { guint32 i; trace->pos++; for (i = 0; i < te->count; i++) { - task->in[te->data[i].addr] = te->data[i].value; + if (te->data[i].addr != 0x3e80) + task->in[te->data[i].addr] = te->data[i].value; } } } @@ -36,6 +37,8 @@ static inline gdouble task_run(task_t *task, task_app_t app, gpointer userdata, if (dotrace) task_trace_step(task); ovm_step(task->scenario, task->in, task->out); } + task->finished = TRUE; + app(task, userdata); if (dotrace) task_trace_end(task); return task->out[0]; } diff --git a/ovm/trace.h b/ovm/trace.h index 1b3fdcc..4494c07 100644 --- a/ovm/trace.h +++ b/ovm/trace.h @@ -3,13 +3,15 @@ #include "base.h" +typedef struct { + guint32 addr; + gdouble value __attribute__ ((__packed__)); +} trace_entry_point_t; + typedef struct { guint32 timestamp; guint32 count; - struct { - guint32 addr; - gdouble value; - } data[]; + trace_entry_point_t data[]; } trace_entry_t; typedef struct {