Commit c92e4535a6de "Prevent time travel in planner dive edit" almost got
it right but had a stupid think-o. This commit should fix it the right
way. If the duration that is passed in is before the previous timestamp,
then this is most likely intended to be a relative time.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
While one might argue that multiple samples with the same time are 'odd'
that still shouldn't be an excuse to incorrectly reset the ceiling value
for them back to 0.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Not sure about the future of the current planner.c as we have new
approaches now but as this annoyed me for some days now I just decided
to come up with this trivial stuff to make my life easier.
More a cosmetic fix than a patch, but actually it fixes a bug one might
face planing a dive using low oxygen mixes and where stop levels at just
90m, 60m, 30m and nothing in between will not allow subsurface to finish
a deco ceiling which ends before the universe collapses. Allows to plan
20min@130m using a 10/70 now (f.i.).
Signed-off-by: Jan Schubert / Jan.Schubert@GMX.li
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
In commit a7902f279a57 "Rewrite of the deco code" Robert kept the old code
that he replaced around; I removed all that as it's in the git history if
we ever need to look at it again but doesn't really help us in the file as
it is.
I also removed constants, variables and config parameters that aren't used
in the new implementation and did some coding style / formatting changes
to make deco.c more consistent with the rest of Subsurface. I also updated
the comments at the top of the file to reflect reality.
I did one change that actually affects the code. In the explanation of his
changes Robert said that gf_low_pressure_this_dive is initialized to the
exquivalent of 20m, yet his code added the surface pressure twice. I
decided to change the default config value from 3 (bar) to 2 so that this
indeed reflects (about) 20m (as in the code below surface_pressure is
added to this value).
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
o) Instead of using gradient factors as means of comparison, I now use
pressure (as in: maximal ambient pressure).
o) tissue_tolerance_calc() now computes the maximal ambient pressure now
respecting gradient factors. For this, it needs to know about the
surface pressure (as refernce for GF_high), thus gets *dive as an
argument. It is called from add_segment() which this also needs *dive
as an additional argument.
o) This implies deco_allowed_depth is now mainly a ambient-pressure to
depth conversion with decorations to avoid negative depth (i.e. no deco
obliation), implementation of quantization (!smooth => multiples of 3m)
and explicit setting of last deco depth (e.g. 6m for O2 deco).
o) gf_low_pressure_this_dive (slight change of name), the max depth in
pressure units is updated in add_segment. I set the minimal value in
buehlmann_config to the equivalent of 20m as otherwise good values of
GF_low add a lot of deco to shallow dives which do not need deep stops
in the first place.
o) The bogus loop is gone as well as actual_gradient_limit() and
gradient_factor_calculation() and large parts of deco_allowed_depth()
although I did not delete the code but put it in comments.
o) The meat is in the formula in lines 147-154 of deco.c. Here is the
rationale:
Without gradient factors, the M-value (i.e the maximal tissue pressure)
at a given depth is given by ambient_pressure / buehlmann_b + a.
According to "Clearing Up The Confusion About "Deep Stops" by Erik C.
Baker (as found via google) the effect of the gradient factors is no
replace this by a reduced affine relation (i.e. another line) such that
at the surface the difference between M-value and ambient pressure is
reduced by a factor GF_high and at the maximal depth by a factor
GF_low.
That is, we are looking for parameters alpha and beta such that
alpha surface + beta = surface + gf_high * (surface/b + a - surface)
and
alpha max_p + beta = max_p + gf_low * (max_p/b + a - max_p)
This can be solved for alpha and beta and then inverted to obtain the
max ambient pressure given tissue loadings. The result is the above
mentioned formula.
Signed-off-by: Robert C. Helling <helling@atdotde.de>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
The dive will start with gas 0. If things change during the planned part
of the dive, this will be represented by an event. Use the last gas for
the ascent.
Obviously this still doesn't handle deco gases, but at least we now no
longer switch back to the first gas after the planned part of the dive.
This also adds quite a bit of debugging code to be able to trace what's
happening in the planner.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Stupid Gtk. Seriously. So in order to get a notification if the user
selects the drop down for the gas with the mouse I need to connect to the
"changed" signal for the combobox. But that also fires whenever the user
types something into the GtkEntry. Which means we once again get called
for all kinds of silly partial names.
Instead we want to handle the manual entry in the "focus-out" callback
(the user has hit tab or something else to move away from the GtkEntry -
let's assume that this is the text he wants us to use) and only respond to
the changed signal on the combobox if the user selected something from the
dropdown.
The easiest way to do that (I think) is to check the text with the strings
stored in the model. If this indeed matches a string stored in the model
then most likely this is something the user selected from the dropdown.
But more importantly if it isn't in the model, then we KNOW that this is
just a partial string that was typed in. And we can ignore that one.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
If the user enters an absolute time that is before the previous waypoint,
silently assume that this is a relative time.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
A strange and buggy dive where time goes backwards (right now easy to
create with the dive plan editor) can cause us to run out of plot info
elements.
This prevents that from causing memory corruption by refusing to go back
in time.
Reported-by: Dirk Hohndel <dirk@hohndel.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
We do want to compare "loose" dives too, but we need to be a bit
careful, and always use the trip date as the primary sort key for any
dives that are not in the same trip.
Reported-and-tested-by: Miika Turkia <miika.turkia@gmail.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Good night.
Here is the corrected patch. It would need to be tested in other
languages because of the size of the units string in imperial.
It performs well in spanish and (I supose) in english, but if a language
make grow the string it could easily be wrapped and make a mess.
On Mon, Jan 07, 2013 at 10:50:31AM -0800, Dirk Hohndel wrote:
>
> Thanks. I appreciate your patience with this. I'm very happy for every
> contibutor we have and I am especially happy to have someone working on
> the print layout code.
>
Thaks to all of you, Dirk, for all your efforts in the gui, the deco, the
planner ... That's the real hard work.
Regards.
Salva.
From 51dace93a1dae68960fee2229d4f274e8e4543fd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Salvador=20Cu=C3=B1at?= <salvador.cunat@gmail.com>
Date: Mon, 7 Jan 2013 22:58:09 +0100
Subject: [PATCH] Add SAC to the printout
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- Add the SAC to the printout, displacing the less utils OTUs.
- Substitute repetitive math operations with variables.
- Correct bad translations (correct with *0.90 scaling).
Signed-off-by: Salvador Cuñat <salvador.cunat@gmail.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This simplifies the dive planning code by:
- allowing empty gas mixes (which means "pick previous gas")
- avoiding unnecessary strdup/free calls (this requires us to handle
"const char *" in the parsers, but that was already true from a code
standpoint, just not a type one)
- re-use the "plan()" function for a successful dive plan, rather than
open-coding the dive plan segment handling.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This appears to happen if we have impossible dive sequences in the
dive_list (i.e., merging XML files from two different divers with
overlapping trips).
We need to fix the underlying cause for this issue (i.e., only pick the
'right' dives to calculate the residual tissue saturation), but at least
this code prevents the hang in an infinite loop.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
First, I forgot to pass in the idx into the gas callback function - this
way for the dynamically created dives we always used air for anything but
the first segment.
Second, when selecting a gas from the drop down (with the mouse or by
typing), the GtkEntry doesn't receive that text and therfore we never
picked up those gases.
We now also track the 'changed' event for the GtkComboBox, but never add
the text we get their to the completions (as by definition they are
already there).
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
There should be NO other changes in this commit - just moving the code and
adjusting the includes (and adding the entry point to display-gtk.h).
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This was just a crutch to get something out there for people to play with.
With the ability to input a plan in place this is now obsolete.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
When incrementally building dives with gas changes there are still some
serious issues and inconsistencies. But at least now the gases in the dive
we create appear to be correct.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Now that the pressure_time calculations are done in our "native"
integer units (millibar and seconds), we might as well keep using
integer variables.
We still do floating point calculations at various stages for the
conversions (including turning a depth in mm into a pressure in mbar),
so it's not like this avoids floating point per se. And the final
approximation is still done as a fraction of the pressure-time values,
using floating point. So floating point is very much involved, but
it's used for conversions, not (for example) to sum up lots of small
values.
With floating point, I had to think about the dynamic range in order
to convince myself that summing up small values will not subtly lose
precision.
With integers, those kinds of issues do not exist. The "lost
precision" case is not subtle, it would be a very obvious overflow,
and it's easy to think about. It turns out that for the pressure-time
integral to overflow in "just" 31 bits, we'd have to have pressures
and times that aren't even close to the range of scuba cylinder air
use (eg "spend more than a day at a depth of 200+ m").
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
I fixed the pressure-time calculations to use "proper" units, but
thinking about it some more, it turns out that units don't really
matter. As long as we use the *same* unit for calculating the
integral, and then re-calculating the step-wise entries, the units
will cancel out.
So we can simplify the "pressure_time()" function a bit, and use
whatever units are most natural for our internal representation. So
instead of using atm, use "mbar".
Now, since the units don't matter, this patch doesn't really make much
of a difference conceptually. Sure, it's a slightly simpler function,
but maybe using more "natural" units for it would be worth it. But it
turns out that using milli-bar and seconds has an advantage: we could
do all the pressure_time integral using 32-bit integers, and we'd
still be able to represent values that would be equivalent to staying
at 24 bar for a whole day.
This patch doesn't actually change the code to use integers, but with
this unit choice, we at least have that possibility.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This splits up the function to create the estimated pressures for
missing tank pressure information.
The code now has a separate pass to create the beginning and ending
pressures for segments that lack them, and fill them in to match the
overall SAC-rate for that cylinder.
In the process, it also fixes the calculation of the interpolated gas
pressure: you can see this in test-dive 13, where we switch back to the
first tank at the end of the dive. It used to be that the latter
segment of that cylinder showed in a different color from the first
segment, showing that we had a different SAC-rate. But that makes no
sense, since our interpolation is supposed to use a constant SAC-rate
for each cylinder.
The bug was that the "magic" calculation (which is just the pressure
change rate over pressure-time) was incorrect, and used the current
cylinder pressure for start-pressure calculation. But that's wrong,
since we update the current cylinder pressure as we go along, but we
didn't update the total pressure_time.
With the separate phase to calculate the segment beginning/ending
pressures, the code got simplified and the bug stood out more.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
The code was using bar, not atm to calculate the pressure_time
multiplier. But SAC-rate is relative to atm.
We could do the correction at the end (and keep the pressure_time in
"bar-seconds"), but let's just use the expected units during the
integration. Especially since this also makes a helper function to do
the calculations (with variables to keep the units obvious) instead of
having multi-line expressions that have the wrong units.
This fixes what I thought were rounding errors for the pressure graphs.
They were just unit confusion.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This splits up the (very complex) function that calculates all the plot
info data, so that the gas pressure logic is in several helper
functions, and the deco and partial pressure calculations are in a
function of their own.
That makes the code almost readable.
This also changes the cylinder pressure calculations so that if you have
manually set the beginning and end pressures, those are the ones we will
show (by making them fake "sensor pressures"). We used to shopw some
random pressure that was related to the manually entered ones only
distantly (through various rounding phases and the SAC-rate calculations).
That does make the rounding errors more obvious in the graph, but we can
fix that separately.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
As the user enters data into the entry fields, that data is validated and
as soon as there is enough data we start constructing a dive profile,
including the final ascent to the surface, including required deco stops,
etc.
This commit still has some serious issues.
- when data is input that doesn't validate, we just print a warning to
stdout - instead we need to change the backgroundcolor of the input
field or something.
- when we switch to the last dive in order to show the profile we don't
actually search for the last dive - we just show the first one in the
tree. This works for the default sort order but is of course wrong
otherwise
I'm sure there are many other bugs, but I want to push it out where it is
right now for others to be able to take a look.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This was added in commit 594da00612ab "Do a minimal hook-up of the dive
plan tree view to the actual planning" and has been replaced by a
different UI in subsequent commits. No point in keeping it around.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This simplifies - and improves - the code to generate the plot info
entries from the samples.
We used to generate exactly one plot info entry per sample, and then -
because the result doesn't have high enough granularity - we'd
generate additional plot info entries at gas change events etc.
Which resulted in all kinds of ugly special case logic. Not only for
the gas switch, btw: you can see the effects of this in the deco graph
(done at plot entry boundaries) and in the gas pressure curves.
So this throws that "do special plot entries for gas switch events"
code away entirely, and replaces it with a much more straightforward
model: we generate plot entries at a minimum of ten-second intervals.
If you have samples more often than that, you'll get more frequent
plot entries, but you'll never get less than that "every ten seconds".
As a result, the code is smaller and simpler (99 insertions, 161
deletions), and actually does a better job too.
You can see the difference especially in the test dives that only have
a few entries (or if you create a new dive without a dive computer,
using the "Add Dive" menu entry). Look at the deco graph of test-dive
20 before and after, for example. You can also see it very subtly in
the cylinder pressure curves going from line segments to curves on
that same dive.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
We kept reduing all the deco calculations, including the previous dives
(if any) for each segment we add to the dive plan. This simply remembers
the last stage and then just adds to that.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
GTK's logic might be a bit flawed (or complicated) in terms of
"focus-out-event" and GtkComboBoxEntry objects as it does not work
by attaching said signal type directly to the GtkComboBoxEntry.
Perhaps it only makes sense for text input.
Since "focus-out-event" works for GtkEntry, we can retrieve the child
GtkEntry from the combo using gtk_bin_get_child(GTK_BIN(combo)
and attach the event handler to that.
This change should make it possible to update gas_model (GtkListStore)
when changing the widget focus with both the keyboard and mouse clicks.
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Once again Gtk does everything it can to make our lives miserable. It
requires major hackery to be able to add new gases to the drop down lists
"on the fly". Right now this only works if you edit the gas and then use
Tab to move to the next field.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Just after pushing out the last set of changes I had one more idea what I
could try. And of course that was it. Don't queue up a redraw. Simply run
gtk_widget_show_all on the dialog! That does the trick.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Linus' treeview for the plan input is just too ugly for words. And doesn't
work, either.
So let's go with plan C: a table of waypoint entries. Depth, duration (or
absolute time), and gas used. The gas is a combobox that does completion.
I am reusing Linus' validation functions / parsers.
This works if you can fit your dive into the four waypoints that are there
by default. The add waypoint button is hooked up but even though it does
what I think should modify the dialog that is currently displayed that
clearly doesn't work.
But at least it "mostly" works and isn't as horrifyingly uggly as the
first two attempts.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
actual planning
Yes, you can actually enter your segments now.
No, it's not wonderfully user-friendly. If you don't enter enough
segments to create a dive plan, it will just silently fail, for example.
And the <tab> key that should get you to the next editable segment
doesn't. And so on. But it kind of works.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This doesn't actually do the real work yet, but it creates all the
infrastructure to edit a tree model, and verify the contents for time,
depth and gas mix.
Now we just need the ability to add entries to the tree model (this adds
one fake one, just to test the editing), and then read out the final end
result and turn it into a plan.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This is not doing anything (which is why there are so many unused variable
warnings). It's just a couple of entries lined up to give a visual
impression how some of this could look.
I am not a UI designer. And there are good reasons for that...
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
The ceiling calculations for the gradient factors still had a 3m increment
hardcoded. This is now also conditional on the smooth parameter.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
For dives with no samples, we crate a fake dive computer with a set of
made-up samples and use those to display the profile.
However, the actual calculations to do the maximum duration and depth
etc were always done with the "real" dive information, which is empty.
As a result, the scale of the plot ended up being bogus, and part of
the dive would be missing.
Trivially fix by just passing the same dive computer information to
calculate_max_limits() that we use for everything else.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This comes with absolutely no gui - so the plan literally needs to be
compiled into Subsurface. Not exactly a feature, but this allowed me to
focus on the planning part instead of spending time on tedious UI work.
A new menu "Planner" with entry "Test Planner" calls into the hard-coded
function in planner.c. There a simple dive plan can be constructed with
calls to plan_add_segment(&diveplan, duration, depth at the end, fO2, pO2)
Calling plan(&diveplan) does the deco calculations and creates deco stops
that keep us below the ceiling (with the GFlow/high values currently
configured). The stop levels used are defined at the top of planner.c in
the stoplevels array - there is no need to do the traditional multiples of
3m or anything like that.
The dive including the ascents and deco stops all the way to the surface
is completed and then added as simulated dive to the end of the divelist
(I guess we could automatically select it later) and can be viewed.
This is crude but shows the direction we can go with this. Envision a nice
UI that allows you to simply enter the segments and pick the desired
stops.
What is missing is the ability to give the algorithm additional gases that
it can use during the deco phase - right now it simply keeps using the
last gas used in the diveplan.
All that said, there are clear bugs here - and sadly they seem to be in
the deco calculations, as with the example given the ceiling that is
calculated makes no sense. When displayed in smooth mode it has very
strange jumps up and down that I wouldn't expect. For example with GF
35/75 (the default) the deco ceiling when looking at the simulated dive
jumps from 16m back up to 13m around 14:10 into the dive. That seems very
odd.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Without this the cairo_close_path call could do silly looking things
(intersecting polygons...).
Reported-by: "Robert C. Helling" <helling@atdotde.de>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
The old implementation was broken in several ways.
For one thing the GF values are percentages, so they should normally be
0 < GF < 1 (well, some crazy people like to go above that).
With this most of the Bühlmann config constants were wrong.
Furthermore, after we adjust the pressure tolerance based on the gradient
factors, we need to convert this back into a depth (instead of passing
back the unmodified depth - oops).
Finally, this commit adds closed circuit support to the deco calculations.
Major progress and much more useful at this stage.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This seems like a strange way to capture the FOCUS_CHANGE event, but
manually trying to register a callback for it fails. Yet registering a
callback for every event and then filtering for FOCUS_CHANGE in the
callback works. Go figure.
But with this commit you can actually change the GF settings in the
preferences dialog and once you tab out of the entry field the change gets
immediately applied - nice to play with the effects of changing GF values.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
There were some minor problems when moving the selection
cursor around:
1) If the selection was larger than 1, it was possible
for the selection to get "stuck" in the middle of the list.
This patch approaches this by always calling
gtk_tree_selection_unselect_all() before
gtk_tree_selection_select_iter(), or simply always making
sure we have one selected iterator when navigating with the keys.
2) When there was a single top level dive before the first trip
it wasn't possible to navigate trough the child dives of said
trip in both directions.
The patch attempts to fix this by having the hunks/checks:
if (idx < 0) {
(idx is of a trip) performed regardless of other conditions.
*** Note: testing was done by importing all test*.xml
dives with auto-group on.
[Dirk Hohndel: adjusted the patch to also fix on_key_press to only grab
the key if no modifier key is pressed; otherwise this
breaks shift-cursor-keys for selecting multiple dives.]
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
If we print out the pressure difference (because we do not have a cylinder
size), we didn't initialize the precision. We should print out pressures
without decimals.
The attached patch fixes that, and also avoids a NULL pointer printout
(which on Linux will just print out "(null)") if there is no cylinder
type descriptor string. It also cleans things up a bit and uses the
"cyl" pointer instead of repeating the "dive->cylinder[n]" thing.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
There are a couple of issues with this commit:
GtkEntry should emit the 'changed' signal when it is modified (so that
changes in the preferences get applied right away) - but that doesn't
appear to be working consistently.
Also, this doesn't appear to affect the deco of any dives that I try it
with. So my guess is something is wrong with the underlying deco
algorithm. That's diappointing.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>