summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Robert C. Helling <helling@atdotde.de>2014-04-26 17:29:40 +0200
committerGravatar Dirk Hohndel <dirk@hohndel.org>2014-05-08 12:28:09 -0700
commitc3a3c1a1e7d7eedc7aa09ba9842069e9933cb7b2 (patch)
tree0375e31c2e39e47944a2cf275f98e9a08493b611
parent00e7ef2cf88e1a96bf14317af79ab2c9b3468ed2 (diff)
downloadsubsurface-c3a3c1a1e7d7eedc7aa09ba9842069e9933cb7b2.tar.gz
Planner: Implement ascend rate according to GUE standard procedures
Signed-off-by: Robert C. Helling <helling@atdotde.de> Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
-rw-r--r--dive.c20
-rw-r--r--dive.h1
-rw-r--r--planner.c22
3 files changed, 38 insertions, 5 deletions
diff --git a/dive.c b/dive.c
index 4bae24526..019b1d0a4 100644
--- a/dive.c
+++ b/dive.c
@@ -2218,3 +2218,23 @@ void set_userid(char *rUserId)
strcpy(prefs.userid, rUserId);
}
#undef MAX_USERID_SIZE
+
+int average_depth(struct diveplan *dive)
+{
+ int integral = 0;
+ int last_time = 0;
+ int last_depth = 0;
+ struct divedatapoint *dp = dive->dp;
+
+ while (dp) {
+ if (dp->time) {
+ /* Ignore gas indication samples */
+ integral += (dp->depth + last_depth) * (dp->time - last_time) / 2;
+ last_time = dp->time;
+ last_depth = dp->depth;
+ }
+ dp = dp->next;
+ }
+
+ return integral / last_time;
+}
diff --git a/dive.h b/dive.h
index 13606f39e..b4e21a58a 100644
--- a/dive.h
+++ b/dive.h
@@ -915,6 +915,7 @@ extern depth_t string_to_depth(const char *str);
extern pressure_t string_to_pressure(const char *str);
extern volume_t string_to_volume(const char *str, pressure_t workp);
extern fraction_t string_to_fraction(const char *str);
+extern int average_depth(struct diveplan *dive);
#include "pref.h"
diff --git a/planner.c b/planner.c
index 5c0bbecbc..980b221b0 100644
--- a/planner.c
+++ b/planner.c
@@ -576,10 +576,20 @@ static void add_plan_to_notes(struct diveplan *diveplan, struct dive *dive)
}
#endif
-int ascend_velocity(int depth)
+int ascend_velocity(int depth, int avg_depth, int bottom_time)
{
/* We need to make this configurable */
- return 10000/60;
+
+ /* As an example (and possibly reasonable default) this is the Tech 1 provedure according
+ * to http://www.globalunderwaterexplorers.org/files/Standards_and_Procedures/SOP_Manual_Ver2.0.2.pdf */
+
+ if (depth <= 6000)
+ return 1000 / 60;
+
+ if (depth * 4 > avg_depth *3)
+ return 9000 / 60;
+ else
+ return 6000 / 60;
}
void plan(struct diveplan *diveplan, char **cached_datap, struct dive **divep, bool add_deco)
@@ -599,6 +609,7 @@ void plan(struct diveplan *diveplan, char **cached_datap, struct dive **divep, b
bool stopping = false;
bool clear_to_ascend;
int clock, previous_point_time;
+ int avg_depth, bottom_time;
set_gf(diveplan->gflow, diveplan->gfhigh, default_prefs.gf_low_at_maxdepth);
if (!diveplan->surface_pressure)
@@ -622,6 +633,7 @@ void plan(struct diveplan *diveplan, char **cached_datap, struct dive **divep, b
current_cylinder = 0;
}
depth = dive->dc.sample[dive->dc.samples - 1].depth.mm;
+ avg_depth = average_depth(diveplan);
/* if all we wanted was the dive just get us back to the surface */
if (!add_deco) {
@@ -655,7 +667,7 @@ void plan(struct diveplan *diveplan, char **cached_datap, struct dive **divep, b
stopidx += gaschangenr;
/* Keep time during the ascend */
- clock = previous_point_time = dive->dc.sample[dive->dc.samples - 1].time.seconds;
+ bottom_time = clock = previous_point_time = dive->dc.sample[dive->dc.samples - 1].time.seconds;
gi = gaschangenr - 1;
while (1) {
@@ -663,7 +675,7 @@ void plan(struct diveplan *diveplan, char **cached_datap, struct dive **divep, b
do {
/* Ascend to next stop depth */
assert(deco_allowed_depth(tissue_tolerance, diveplan->surface_pressure / 1000.0, dive, 1) < depth);
- int deltad = ascend_velocity(depth) * TIMESTEP;
+ int deltad = ascend_velocity(depth, avg_depth, bottom_time) * TIMESTEP;
if (depth - deltad < stoplevels[stopidx])
deltad = depth - stoplevels[stopidx];
@@ -702,7 +714,7 @@ void plan(struct diveplan *diveplan, char **cached_datap, struct dive **divep, b
/* Check if ascending to next stop is clear, go back and wait if we hit the ceiling on the way */
clear_to_ascend = true;
while (trial_depth > stoplevels[stopidx]) {
- int deltad = ascend_velocity(trial_depth) * TIMESTEP;
+ int deltad = ascend_velocity(trial_depth, avg_depth, bottom_time) * TIMESTEP;
tissue_tolerance = add_segment(depth_to_mbar(trial_depth, dive) / 1000.0, &dive->cylinder[current_cylinder].gasmix, TIMESTEP, po2, dive);
if (deco_allowed_depth(tissue_tolerance, diveplan->surface_pressure / 1000.0, dive, 1) > trial_depth - deltad){
/* We should have stopped */