aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorGravatar Tim Segers <tsegers@pm.me>2022-10-19 16:48:08 +0200
committerGravatar Tim Segers <tsegers@pm.me>2022-10-19 16:48:08 +0200
commit16d1b52543f73d972d33feaa94316dbb67ab907d (patch)
tree03c1934a0f3d13e9d45e5ab86223919214500fb3
parentbc19593e867562f43f4c7ee0a367af3762eb22bd (diff)
downloadopendeco-16d1b52543f73d972d33feaa94316dbb67ab907d.tar.gz
Ascend along fixed stops instead of along rounded ceiling
-rw-r--r--src/deco.c20
-rw-r--r--src/deco.h1
-rw-r--r--src/schedule.c139
-rw-r--r--src/schedule.h1
4 files changed, 47 insertions, 114 deletions
diff --git a/src/deco.c b/src/deco.c
index 3f27a33..51cdf0e 100644
--- a/src/deco.c
+++ b/src/deco.c
@@ -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)
diff --git a/src/deco.h b/src/deco.h
index 11f6bc9..cef35d4 100644
--- a/src/deco.h
+++ b/src/deco.h
@@ -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);