Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

produce / consume under large physics steps kills Kerbals #40

Closed
DBowmanUDA opened this issue Aug 30, 2016 · 4 comments
Closed

produce / consume under large physics steps kills Kerbals #40

DBowmanUDA opened this issue Aug 30, 2016 · 4 comments
Assignees

Comments

@DBowmanUDA
Copy link

I noticed this when making Soylent, just new intermediate resources and TACLS generators, the work around is big enough (i.e. way too big) buffer storage and excessive resources. I have a guess re the cause.

Imagine a Kerbal - CO2 - Purifier - O2 -Kerbal loop where the rates per second all balance. Under big time steps the Kerbal can need more O2 than is in storage, the CO2 can exceed storage and be dumped and then the Purifier cannot recover the original O2 amount. Also the order the generators are run in does not seem to be deterministic; so it can run the purifier when there is no CO2 => no O2 then run the Kerbil oops. I think you can see the same kind of thing with stock electricity, where you go up one warp and battery drops 30% and then stays there, up another and the battery drops to 0 even though your RTG produces more e than the craft needs.

Maybe having 'scratch' resource buffers during the time step and then only trying to put the results into physical storage at the end of the step would be enough? though that would still hit the 'starvation' issue :( maybe the computation can 'borrow resource' during the computation as long as it 'pays it back later'. Anyway I guess step one is confirming you all see the issue also.

@ShotgunNinja
Copy link

I had the same problem. In fact, the stock game has the same problem. It happen when the max amount produced or consumed by a component per-timewarp-step exceed capacity of that resource.

The buffer solution 'kind of work': the capacities need to be very large to tolerate the highest timewarp. I don't remember exactly, but should be 30 minutes of simulated time per-second. That put the buffer capcities in the thousands of units for a max consumer/producer of 0.5/s or above.

And then you find that order of execution is relevant to production/consumption. The 'simpler' solution is to allow resources to overflow/underflow during a simulation step, and clamp them at the end. But that has its own issues, among which figures things like being unable to determine if a resource is present or not, or if it is at full capacity or not. So dependant chains became non-coherent. And to solve that you'll need to introduce the concept that a simulation step only observe the situation from previous simulation step.

If you do that, then you'll get to the 'timewarp-blending' problem. This is subtle, but as long as timesteps are constant (more precisely, as long as time of step N is the same as time of step N-1) observing previous simulation step work. But during the time the user change timewarp speeds (and the game blend between them), all chains will became incoherent again leading to very subtle effects that are going to be discover at a great waste of time.

To solve all of this I had to develop a relatively elaborate 'resource cache'. You can find some of the code here.

@JPLRepo
Copy link

JPLRepo commented Aug 30, 2016

I'm waiting this one out until KSP 1.2 comes out as the dev notes have said the Resource system has had a complete overhaul.

@JPLRepo JPLRepo self-assigned this Aug 30, 2016
@DBowmanUDA
Copy link
Author

Oh warp blending ...

Two other solutions I thought a little about are:

  • 'on rails resource processing' - assume net effect is linear function of t, work out the resource deltas for a small t and substitute, back off t if anything went negative to find the time of exhaustion etc
  • 'sub steps' I assume that under warp 'rail physics' gets called with a t / t since last call (probably for each part independently?) Internally run smaller time steps, and run all the producers / consumers on the vessel when the first part is processed (update all the parts 'as at' time so they don't get run agin until next 'rails time step').

The second is probably the simplest and could be used for normal running also, it also provides a natural place to hang processor ordering.

If they are changing everything in 1.2 the waiting sure make sense - it's been this way for a while...

@JPLRepo
Copy link

JPLRepo commented Oct 27, 2016

I'm looking into 'on rails resource processing'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants