diff options
author | Tim Segers <tsegers@pm.me> | 2022-10-19 16:48:08 +0200 |
---|---|---|
committer | Tim Segers <tsegers@pm.me> | 2022-10-19 16:48:08 +0200 |
commit | 16d1b52543f73d972d33feaa94316dbb67ab907d (patch) | |
tree | 03c1934a0f3d13e9d45e5ab86223919214500fb3 | |
parent | bc19593e867562f43f4c7ee0a367af3762eb22bd (diff) | |
download | opendeco-16d1b52543f73d972d33feaa94316dbb67ab907d.tar.gz |
Ascend along fixed stops instead of along rounded ceiling
-rw-r--r-- | src/deco.c | 20 | ||||
-rw-r--r-- | src/deco.h | 1 | ||||
-rw-r--r-- | src/schedule.c | 139 | ||||
-rw-r--r-- | src/schedule.h | 1 |
4 files changed, 47 insertions, 114 deletions
@@ -197,31 +197,17 @@ double get_gf(const decostate_t *ds, const double depth) const unsigned char lo = ds->gflo; const unsigned char hi = ds->gfhi; - const double last_stop_gauge = LAST_STOP_AT_SIX ? msw_to_bar(6) : ds->ceil_multiple; - if (ds->firststop == -1) return lo; - if (depth <= SURFACE_PRESSURE + last_stop_gauge) + if (depth <= SURFACE_PRESSURE) return hi; if (depth >= ds->firststop) return lo; /* interpolate lo and hi between first stop and last stop */ - return hi - (hi - lo) * gauge_depth(depth - ds->ceil_multiple) / gauge_depth(ds->firststop - ds->ceil_multiple); -} - -double round_ceiling(const decostate_t *ds, const double c) -{ - assert(ds->ceil_multiple != 0); - - double ceil_gauge = ds->ceil_multiple * ceil(RND(gauge_depth(c) / ds->ceil_multiple)); - - if (LAST_STOP_AT_SIX && ceil_gauge < msw_to_bar(6) && ceil_gauge > 0) - return abs_depth(msw_to_bar(6)); - else - return abs_depth(ceil_gauge); + return hi - (hi - lo) * gauge_depth(depth) / gauge_depth(ds->firststop); } double ceiling(const decostate_t *ds, double gf) @@ -249,7 +235,7 @@ double ceiling(const decostate_t *ds, double gf) c = max(c, ((pn2 + phe) - (a * gf)) / (gf / b + 1 - gf)); } - return round_ceiling(ds, c); + return c; } double gf99(const decostate_t *ds, double depth) @@ -75,7 +75,6 @@ double add_segment_ascdec(decostate_t *ds, const double dstart, const double den const gas_t *gas); double add_segment_const(decostate_t *ds, const double depth, const double time, const gas_t *gas); double get_gf(const decostate_t *ds, const double depth); -double round_ceiling(const decostate_t *ds, const double c); double ceiling(const decostate_t *ds, double gf); double gf99(const decostate_t *ds, double depth); diff --git a/src/schedule.c b/src/schedule.c index bf5a8ec..00a2b13 100644 --- a/src/schedule.c +++ b/src/schedule.c @@ -18,7 +18,7 @@ const gas_t *best_gas(const double depth, const gas_t *gasses, const int nof_gas for (int i = 0; i < nof_gasses; i++) { double mod = gas_mod(&gasses[i]); - if (depth <= mod && (mod_best == -1 || mod < mod_best)) { + if (depth - mod < 1E-2 && (mod_best == -1 || mod < mod_best)) { best = &gasses[i]; mod_best = mod; } @@ -27,23 +27,6 @@ const gas_t *best_gas(const double depth, const gas_t *gasses, const int nof_gas return best; } -const gas_t *next_gas(const double depth, const gas_t *gasses, const int nof_gasses) -{ - const gas_t *next = NULL; - double mod_best = 0; - - for (int i = 0; i < nof_gasses; i++) { - double mod = gas_mod(&gasses[i]); - - if (depth > mod && mod > mod_best) { - next = &gasses[i]; - mod_best = mod; - } - } - - return next; -} - int direct_ascent(const decostate_t *ds, const double depth, const double time, const gas_t *gas) { decostate_t ds_ = *ds; @@ -109,7 +92,8 @@ double calc_ndl(decostate_t *ds, const double depth, const double ascrate, const return ndl; } -double deco_stop(decostate_t *ds, const double depth, const double current_gf, const gas_t *gas) +double deco_stop(decostate_t *ds, const double depth, const double next_stop, const double current_gf, + const gas_t *gas) { double stoplen = 0; @@ -119,7 +103,7 @@ double deco_stop(decostate_t *ds, const double depth, const double current_gf, c for (;;) { double tmp = add_segment_const(&ds_, depth, STOPLEN_ROUGH, gas); - if (ceiling(&ds_, current_gf) != depth) + if (ceiling(&ds_, current_gf) <= next_stop) break; stoplen += tmp; @@ -129,33 +113,15 @@ double deco_stop(decostate_t *ds, const double depth, const double current_gf, c add_segment_const(ds, depth, stoplen, gas); /* fine steps */ - while (ceiling(ds, current_gf) == depth) + while (ceiling(ds, current_gf) > next_stop) stoplen += add_segment_const(ds, depth, STOPLEN_FINE, gas); return stoplen; } -int should_switch(const gas_t **next, double *switch_depth, const decostate_t *ds, const double depth, - const double next_stop, const gas_t *deco_gasses, const int nof_gasses) +static int surfaced(const double depth) { - /* check if we switch at MOD or just at stops */ - if (!SWITCH_INTERMEDIATE) - return 0; - - /* check if there is a gas to switch to */ - *next = next_gas(depth, deco_gasses, nof_gasses); - - if (*next == NULL) - return 0; - - /* check if the switch happens before the current ceiling */ - *switch_depth = round_ceiling(ds, (*next)->mod) - ds->ceil_multiple; - assert(*switch_depth <= (*next)->mod); - - if (*switch_depth <= next_stop) - return 0; - - return 1; + return fabs(depth - SURFACE_PRESSURE) < 1E-2; } decoinfo_t calc_deco(decostate_t *ds, const double start_depth, const gas_t *start_gas, const gas_t *deco_gasses, @@ -175,44 +141,20 @@ decoinfo_t calc_deco(decostate_t *ds, const double start_depth, const gas_t *sta return ret; } - /* determine first stop */ - double current_gf = get_gf(ds, depth); + double next_stop = abs_depth(ds->ceil_multiple * (ceil(gauge_depth(depth) / ds->ceil_multiple) - 1)); + double current_gf = get_gf(ds, next_stop); - if (ds->firststop == -1) - ds->firststop = ceiling(ds, current_gf); - - /* switch to best deco gas if there is one available */ - const gas_t *best = best_gas(depth, deco_gasses, nof_gasses); - - if (best) - gas = best; - - /* alternate between ascending and stopping */ for (;;) { /* extra bookkeeping because waypoints and segments do not match 1:1 */ double last_waypoint_depth = depth; double waypoint_time; - /* ascend */ - for (;;) { - /* determine next stop */ - double next_stop = ceiling(ds, current_gf); - - /* find out if we need to switch gas on the way */ - const gas_t *next; - double switch_depth; - - if (should_switch(&next, &switch_depth, ds, depth, next_stop, deco_gasses, nof_gasses)) { - /* ascend to gas switch */ - ret.tts += add_segment_ascdec(ds, depth, switch_depth, fabs(depth - switch_depth) / asc_per_min, gas); - depth = switch_depth; - current_gf = get_gf(ds, depth); - - /* - * since we're stopping for a switch next, this is the last of - * any number of consecutive travel segments and the waypoint - * callback should be called. - */ + while (ceiling(ds, current_gf) < next_stop && !surfaced(depth)) { + /* switch to better gas if available */ + const gas_t *best = best_gas(depth, deco_gasses, nof_gasses); + + if (SWITCH_INTERMEDIATE && best && best != gas) { + /* emit waypoint */ waypoint_time = fabs(last_waypoint_depth - depth) / asc_per_min; if (wp_cb) @@ -221,9 +163,9 @@ decoinfo_t calc_deco(decostate_t *ds, const double start_depth, const gas_t *sta last_waypoint_depth = depth; /* switch gas */ - gas = next; + gas = best; - ret.tts += add_segment_const(ds, switch_depth, 1, gas); + ret.tts += add_segment_const(ds, depth, 1, gas); if (wp_cb) wp_cb(ds, (waypoint_t){.depth = depth, .time = 1, .gas = gas}, SEG_GAS_SWITCH); @@ -231,32 +173,40 @@ decoinfo_t calc_deco(decostate_t *ds, const double start_depth, const gas_t *sta continue; } - /* ascend to current ceiling */ + /* ascend to next stop */ ret.tts += add_segment_ascdec(ds, depth, next_stop, fabs(depth - next_stop) / asc_per_min, gas); depth = next_stop; - current_gf = get_gf(ds, depth); - /* if the ceiling moved while we ascended, keep ascending */ - if (depth > ceiling(ds, current_gf)) - continue; + /* make next stop shallower */ + next_stop -= ds->ceil_multiple; + + if (LAST_STOP_AT_SIX && next_stop < abs_depth(msw_to_bar(6))) + next_stop = SURFACE_PRESSURE; + + /* recalculate gf */ + current_gf = get_gf(ds, next_stop); + } + + if (ds->firststop == -1) { + ds->firststop = depth; /* - * since we've actually reached the ceiling, this is the last of - * any number of consecutive travel segments and the waypoint - * callback should be called. + * if the first stop wasn't know yet during the previous call to + * get_gf, the result was inaccurate and needs to be recalculated */ - waypoint_time = fabs(last_waypoint_depth - depth) / asc_per_min; - enum segtype_t segtype = depth <= abs_depth(0) ? SEG_SURFACE : SEG_TRAVEL; + current_gf = get_gf(ds, next_stop); + } - if (wp_cb) - wp_cb(ds, (waypoint_t){.depth = depth, .time = waypoint_time, .gas = gas}, segtype); + /* emit waypoint */ + waypoint_time = fabs(last_waypoint_depth - depth) / asc_per_min; + enum segtype_t segtype = surfaced(depth) ? SEG_SURFACE : SEG_TRAVEL; - break; - } + if (wp_cb && waypoint_time) + wp_cb(ds, (waypoint_t){.depth = depth, .time = waypoint_time, .gas = gas}, segtype); /* terminate if we surfaced */ - if (depth <= abs_depth(0)) - break; + if (surfaced(depth)) + return ret; /* switch to better gas if available */ const gas_t *best = best_gas(depth, deco_gasses, nof_gasses); @@ -264,13 +214,12 @@ decoinfo_t calc_deco(decostate_t *ds, const double start_depth, const gas_t *sta if (best) gas = best; - /* stop */ - double stoplen = deco_stop(ds, depth, current_gf, gas); + /* stop until ceiling rises above next stop */ + double stoplen = deco_stop(ds, depth, next_stop, current_gf, gas); + ret.tts += stoplen; if (wp_cb) wp_cb(ds, (waypoint_t){.depth = depth, .time = stoplen, .gas = gas}, SEG_DECO_STOP); } - - return ret; } diff --git a/src/schedule.h b/src/schedule.h index 2af6481..e3b69ec 100644 --- a/src/schedule.h +++ b/src/schedule.h @@ -36,7 +36,6 @@ extern int SWITCH_INTERMEDIATE; typedef void (*waypoint_callback_t)(const decostate_t *ds, const waypoint_t, const segtype_t); const gas_t *best_gas(const double depth, const gas_t *gasses, const int nof_gasses); -const gas_t *next_gas(const double depth, const gas_t *gasses, const int nof_gasses); int direct_ascent(const decostate_t *ds, const double depth, const double time, const gas_t *gas); double calc_ndl(decostate_t *ds, const double depth, const double ascrate, const gas_t *gas); |