Jump to content

[1.1.3] BackgroundProcessing


jamespicone

Recommended Posts

@jamespicone Hey, I digged harder into that vessel position problem and the more I dig the more spurious problems turns out! At first i trought KSP was doing some funny things with the vessel.GetWorldPos() function, then that either that or the planet positions were in what KSP call 'ScaledSpace', then I got random occlusions from GameObjects around the launchpad, dependent of camera position!, but only in some circumstances. Hell basically. Long story short, I just reached my patience limit and reimplemented raycasting myself. We just have to trace against a bunch of spheres after all. So now I got a solid, stable and fast function that return if a point is in direct sunlight! Yeah :) If you are interested let me know.

Link to comment
Share on other sites

@jamespicone James, I found another problem. When a vessel is orbiting the Sun, and the user switch from Flight to SpaceCenter scene, for a single tick, vessel.GetWorldPos3D() return the Sun position!!!

When this happen, the following events take place:

  • sun_dir vector became [0,0,0]
  • sun_dist became 0
  • normalizing sun_dir lead to NaN values
  • removing the sun radius from sun_dist generate a negative distance
  • solar flux calculations lead to NaN values
  • EC amount on the vessel became NaN
  • mass calculation for the vessel go wild and return -INF mass
  • loading the vessel destroy the universe!

The solution I found is to obtain unloaded vessel positions by resolving the orbit directly, eg: "vessel_pos = vessel.orbit.getPositionAtUT(Planetarium.GetUniversalTime())"

 

Link to comment
Share on other sites

  • 4 weeks later...

@jamespicone I got a more robust solution for the fact that PhysicsGlobal.SolarLuminosity is zero before loading a vessel, quite easy stuff actually:

// return sun luminosity
public static double SolarLuminosity()
{
  // note: it is 0 before loading first vessel in a game session, we compute it in that case
  if (PhysicsGlobals.SolarLuminosity <= double.Epsilon)
  {
    double A = FlightGlobals.GetHomeBody().orbit.semiMajorAxis;
    return A * A * 12.566370614359172 * PhysicsGlobals.SolarLuminosityAtHome;
  }
  return PhysicsGlobals.SolarLuminosity;
}

This doesn't assume anything about the sun, so it has no drawbacks in case the user is using some planet mods.
Posting it here in case you come out of hybernation for the 1.1 fanfare. :)

Edited by ShotgunNinja
Link to comment
Share on other sites

  • 2 weeks later...

I note @jamespicone has not been on the forum since Feb. @ShotgunNinja has your fork been updated for 1.1? Otherwise I can update my fork.
PS: I am not asking when this is being updated to 1.1 as that would break the new forum rule. I am trying to establish if shotgunninja has updated his fork, or I will update my fork as I need this mod for my mod to work.

Link to comment
Share on other sites

@JPLRepo I do not intend to update it for 1.1, that fork was just temporary as I through @jamespicone was going to update it himself. I stopped updating it some weeks ago, as I reimplemented the functionality from scratch for my project. In the process I found and fixed some problems here and there (you can see some in the posts above), and managed to replace the stock background simulation of ISRU modules with a proper one. Feel free to reuse what I did, if you want. The code is here, and call some functions related to physics from here.

Link to comment
Share on other sites

  • 2 weeks later...
On 20/04/2016 at 7:58 AM, ShotgunNinja said:

@JPLRepo I do not intend to update it for 1.1, that fork was just temporary as I through @jamespicone was going to update it himself. I stopped updating it some weeks ago, as I reimplemented the functionality from scratch for my project. In the process I found and fixed some problems here and there (you can see some in the posts above), and managed to replace the stock background simulation of ISRU modules with a proper one. Feel free to reuse what I did, if you want. The code is here, and call some functions related to physics from here.

@ShotgunNinja Is that a good idea? If you have re-implemented it as part of your Kerbalism mod, as it seems you have. So does Kerbalism do it's own background EC processing for all parts containing certain stock partmodules? or just your mod's own parts? Don't have time to look. But if it does more than your own parts, that disturbs me.

If it does:- then say another mod, like mine, wants background EC processing. I don't necessarily want a dependency on kerbalism (which has lots more than just background processing), if all I want is background processing. Users may choose not to install one mod, or another. I like this mod, because it served any and all mods that wanted this functionality but introduced nothing more than that.

If it doesn't:- then sorry. and each to his own.

Can you clarify.

 

Link to comment
Share on other sites

@JPLRepo Yes Kerbalism simulate all resource production/consumption of the following modules:

  • command pods
  • solar panels
  • generators
  • converters (fuel cells. ISRU)
  • drills & asteroid drills
  • all kerbalism modules
  • SCANsat sensors
  • curved solar panels from near futures electrical
  • reactors, fission & decaying generators
  • planetary base system converters

Note that some of this is not released to the public yet.

 

Im taking steps to modularize kerbalism, and from 0.9.9.5 its separed into an engine and one 'profile' that define the various mechanics. Without a profile, kerbalism will degenerate into a backround resource simulation with an EC monitor/planner ui.

 

I could disable the background sim if BackbroundProcessin is loaded too, if that is necessary.

Link to comment
Share on other sites

1 hour ago, ShotgunNinja said:

@JPLRepo Yes Kerbalism simulate all resource production/consumption of the following modules:

  • command pods
  • solar panels
  • generators
  • converters (fuel cells. ISRU)
  • drills & asteroid drills
  • all kerbalism modules
  • SCANsat sensors
  • curved solar panels from near futures electrical
  • reactors, fission & decaying generators
  • planetary base system converters

Note that some of this is not released to the public yet.

 

Im taking steps to modularize kerbalism, and from 0.9.9.5 its separed into an engine and one 'profile' that define the various mechanics. Without a profile, kerbalism will degenerate into a backround resource simulation with an EC monitor/planner ui.

 

I could disable the background sim if BackbroundProcessin is loaded too, if that is necessary.

So - you plan to split your mod? or just have various functionality active based on a'profile'? I think you are saying the later. How does a mod or user configure this profile?
So I can configure a profile to essentially do the same as this mod using your mod and not use any of its other functionality?

When will you be doing this? Roughly? As I am trying to figure out whether to revive this mod (as mine needs it) or not. Key question though is how your mod's profile is configured and maintained?
Also, will/does your mod allow callback hooks like this one so I can do my own background processing functions?

Link to comment
Share on other sites

@JPLRepo In next version, a few days (sunday, maybe). The user choose a profile  by renaming one from name.cfg-disabled to name.cfg. I'm not planning to split it in two now, but eventually it can happen with some time. No "backgroundUpdate()" hooks, however I can give you a minimalist self-contained class to call your modules in background if you want, to do the same from your code.

If you decide to revive this, then, let me know so I'll just scan for BackgroundProcessing.dll and disable the background resource simulation if present.

 

EDIT: A monobehaviour that call your own modules backgroundUpdate function:

Spoiler

[KSPAddon(KSPAddon.Startup.MainMenu, true)]
public class Background : MonoBehaviour
{
  Background() { DontDestroyOnLoad(this); }

  public void FixedUpdate()
  {
    foreach(Vessel vessel in FlightGlobals.Vessels)
    {
      if (vessel.loaded) continue;
      foreach(ProtoPartSnapshot part in vessel.protoVessel.protoPartSnapshots)
      {
        foreach(ProtoPartModuleSnapshot module in part.modules)
        {
          if (module.moduleName == "myModule")
          {
            myModule.BackgroundUpdate(vessel, part.flightID);
          }
          else if (module.moduleName == "myOtherModule")
          {
            myOtherModule.BackgroundUpdate(vessel, part.flightID);
          }
        }
      }
    }
  }
}

 

 

Edited by ShotgunNinja
added code
Link to comment
Share on other sites

  • 4 weeks later...
37 minutes ago, shoe7ess said:

I'm very interested in a mod like this for my realism series. Does anyone know of another mod or .dll that simulates background electrical resource usage like this one did?

I'm mid way through reviving it..

no, not aware of any other.

Link to comment
Share on other sites

@shoe7ess and anyone else.
I've updated this with a bunch of updates @ShotgunNinja had done previously and re-compiled against KSP 1.1.2.
Source code: https://github.com/JPLRepo/background-processing
Zip file: https://github.com/JPLRepo/background-processing/releases/tag/V0.4.2.0
Although I like Kerbalism, I don't really want a dependancy on it for my other mods. So I have updated this given @jamespicone has not returned to the forums since Feb.
As per the license should all be ok. If the original author returns he can take it back. (License is MIT).
I have not tested this properly yet myself. So If anyone is willing to test it that will be great. Otherwise, When I get around to updating my DeepFreeze mod again (which used to use this) I will do testing and think about a new Thread, Spacedock link etc.

Link to comment
Share on other sites

45 minutes ago, JPLRepo said:

@shoe7ess and anyone else.
I've updated this with a bunch of updates @ShotgunNinja had done previously and re-compiled against KSP 1.1.2.
Source code: https://github.com/JPLRepo/background-processing
Zip file: https://github.com/JPLRepo/background-processing/releases/tag/V0.4.2.0
Although I like Kerbalism, I don't really want a dependancy on it for my other mods. So I have updated this given @jamespicone has not returned to the forums since Feb.
As per the license should all be ok. If the original author returns he can take it back. (License is MIT).
I have not tested this properly yet myself. So If anyone is willing to test it that will be great. Otherwise, When I get around to updating my DeepFreeze mod again (which used to use this) I will do testing and think about a new Thread, Spacedock link etc.

Whoa, you are awesome! Thanks so much for taking the time to compile it for 1.1.2.  Funnily enough, I had forgotten that I used DeepFreeze back when it was just getting started (figured it'd be the easiest way of playing with KSPi and USI Life Support at the same time), and saw it in your signature. Gonna have a good day in my fun (non-RP-0) install tomorrow with it.

Link to comment
Share on other sites

1 hour ago, shoe7ess said:

Whoa, you are awesome! Thanks so much for taking the time to compile it for 1.1.2.  Funnily enough, I had forgotten that I used DeepFreeze back when it was just getting started (figured it'd be the easiest way of playing with KSPi and USI Life Support at the same time), and saw it in your signature. Gonna have a good day in my fun (non-RP-0) install tomorrow with it.

NP. I was sitting on all those changes anyway, was going to come back to it.

Link to comment
Share on other sites

Hi again

A lot of NAN exceptions in SpaceCenter

 

Spoiler
[EXC 17:22:15.553] ArithmeticException: NAN
 System.Math.Sign (Double value)
 BackgroundProcessing.BackgroundProcessing.RaytraceSphere (Vector3d origin, Vector3d direction, Vector3d center, Double radius)
 BackgroundProcessing.BackgroundProcessing.DirectSunlight (.Vessel vessel, .Vector3d& sun_dir, System.Double& sun_dist)
 BackgroundProcessing.BackgroundProcessing.HandleResources (.Vessel v)
 BackgroundProcessing.BackgroundProcessing.FixedUpdate ()
[EXC 17:22:15.581] ArithmeticException: NAN
 System.Math.Sign (Double value)
 BackgroundProcessing.BackgroundProcessing.RaytraceSphere (Vector3d origin, Vector3d direction, Vector3d center, Double radius)
 BackgroundProcessing.BackgroundProcessing.DirectSunlight (.Vessel vessel, .Vector3d& sun_dir, System.Double& sun_dist)
 BackgroundProcessing.BackgroundProcessing.HandleResources (.Vessel v)
 BackgroundProcessing.BackgroundProcessing.FixedUpdate ()
[EXC 17:22:15.647] ArithmeticException: NAN
 System.Math.Sign (Double value)
 BackgroundProcessing.BackgroundProcessing.RaytraceSphere (Vector3d origin, Vector3d direction, Vector3d center, Double radius)
 BackgroundProcessing.BackgroundProcessing.DirectSunlight (.Vessel vessel, .Vector3d& sun_dir, System.Double& sun_dist)
 BackgroundProcessing.BackgroundProcessing.HandleResources (.Vessel v)
 BackgroundProcessing.BackgroundProcessing.FixedUpdate ()
....
 

 

Link to comment
Share on other sites

3 hours ago, bice said:

Hi again

A lot of NAN exceptions in SpaceCenter

 

  Reveal hidden contents
[EXC 17:22:15.553] ArithmeticException: NAN
 System.Math.Sign (Double value)
 BackgroundProcessing.BackgroundProcessing.RaytraceSphere (Vector3d origin, Vector3d direction, Vector3d center, Double radius)
 BackgroundProcessing.BackgroundProcessing.DirectSunlight (.Vessel vessel, .Vector3d& sun_dir, System.Double& sun_dist)
 BackgroundProcessing.BackgroundProcessing.HandleResources (.Vessel v)
 BackgroundProcessing.BackgroundProcessing.FixedUpdate ()
[EXC 17:22:15.581] ArithmeticException: NAN
 System.Math.Sign (Double value)
 BackgroundProcessing.BackgroundProcessing.RaytraceSphere (Vector3d origin, Vector3d direction, Vector3d center, Double radius)
 BackgroundProcessing.BackgroundProcessing.DirectSunlight (.Vessel vessel, .Vector3d& sun_dir, System.Double& sun_dist)
 BackgroundProcessing.BackgroundProcessing.HandleResources (.Vessel v)
 BackgroundProcessing.BackgroundProcessing.FixedUpdate ()
[EXC 17:22:15.647] ArithmeticException: NAN
 System.Math.Sign (Double value)
 BackgroundProcessing.BackgroundProcessing.RaytraceSphere (Vector3d origin, Vector3d direction, Vector3d center, Double radius)
 BackgroundProcessing.BackgroundProcessing.DirectSunlight (.Vessel vessel, .Vector3d& sun_dir, System.Double& sun_dist)
 BackgroundProcessing.BackgroundProcessing.HandleResources (.Vessel v)
 BackgroundProcessing.BackgroundProcessing.FixedUpdate ()
....
 

 

Sorry about that. Just delete it for now. I'll take a look at it again after work.

Link to comment
Share on other sites

@JPLRepo I think the reason for that NaN exception is that you are resolving the orbit to obtain vessel position in a robust way (that is good), but landed vessels have an invalid orbit. I use this little wrapper function to get the position:

Spoiler

  // return true if landed somewhere
  public static bool Landed(Vessel vessel)
  {
    if (vessel.loaded) return vessel.Landed || vessel.Splashed;
    else return vessel.protoVessel.landed || vessel.protoVessel.splashed;
  }

  // return vessel position
  public static Vector3d VesselPosition(Vessel vessel)
  {
    if (vessel.loaded || Landed(vessel) || double.IsNaN(vessel.orbit.inclination))
    {
      return vessel.GetWorldPos3D();
    }
    else
    {
      return vessel.orbit.getPositionAtUT(Planetarium.GetUniversalTime());
    }
  }

 

 

Also I've improved the raycast function that was included in my 'interim' version, making it more robust in general. In case you want to use it, this is the updated one:

Spoiler

  public static double RaytraceSphere(Vector3d origin, Vector3d direction, Vector3d center, double radius)
  {
    // operate in sphere object space, so the origin is translated by -sphere_pos
    origin -= center;

    double A = Vector3d.Dot(direction, direction);
    double B = 2.0 * Vector3d.Dot(direction, origin);
    double C = Vector3d.Dot(origin, origin) - radius * radius;
    double discriminant = B * B - 4.0 * A * C;

    // ray missed the sphere (we consider single hits as misses)
    if (discriminant <= 0.0) return double.MaxValue;

    double q = (-B - Math.Sign(B) * Math.Sqrt(discriminant)) * 0.5;
    double t0 = q / A;
    double t1 = C / q;
    double dist = Math.Min(t0, t1);

    // if sphere is behind, return maxvalue, else it is visible and distance is returned
    return dist < 0.0 ? double.MaxValue : dist;
  }


  // return true if the body is visible from the vessel
  // - vessel: vessel to test
  // - dir: normalized vector from vessel to body
  // - dist: distance from vector to body surface
  // - return: true if visible, false otherwise
  public static bool RaytraceBody(Vessel vessel, CelestialBody body, out Vector3d dir, out double dist)
  {
    // shortcuts
    CelestialBody sun = Sun();
    CelestialBody mainbody = vessel.mainBody;
    CelestialBody refbody = vessel.mainBody.referenceBody;

    // generate ray parameters
    Vector3d vessel_pos = Lib.VesselPosition(vessel);
    dir = body.position - vessel_pos;
    dist = dir.magnitude;
    dir /= dist;
    dist -= body.Radius;

    // store list of occluders
    List<CelestialBody> occluders = new List<CelestialBody>();

    // do not trace against the mainbody if that is our target
    if (body != mainbody) occluders.Add(mainbody);

    // do not trace against the reference body if that is our target, or if there isn't one (eg: mainbody is the sun)
    if (body != refbody || refbody == null) occluders.Add(refbody);

    // trace against any satellites, but not when mainbody is the sun (eg: mainbody is a planet)
    // we avoid the mainbody=sun case because it has a lot of satellites and the chances of occlusion are very low
    // and they probably will occlude the sun only partially at best in that case
    if (mainbody != sun) occluders.AddRange(mainbody.orbitingBodies);

    // do the raytracing
    double min_dist = double.MaxValue;
    foreach(CelestialBody cb in occluders)
    {
      min_dist = Math.Min(min_dist, RaytraceSphere(vessel_pos, dir, cb.position, cb.Radius));
    }

    // return true if body is visible from vessel
    return dist < min_dist;
  }

 

 

Edited by ShotgunNinja
Link to comment
Share on other sites

25 minutes ago, ShotgunNinja said:

@JPLRepo I think the reason for that NaN exception is that you are resolving the orbit to obtain vessel position in a robust way (that is good), but landed vessels have an invalid orbit. I use this little wrapper function to get the position:

  Reveal hidden contents


  // return true if landed somewhere
  public static bool Landed(Vessel vessel)
  {
    if (vessel.loaded) return vessel.Landed || vessel.Splashed;
    else return vessel.protoVessel.landed || vessel.protoVessel.splashed;
  }

  // return vessel position
  public static Vector3d VesselPosition(Vessel vessel)
  {
    if (vessel.loaded || Landed(vessel) || double.IsNaN(vessel.orbit.inclination))
    {
      return vessel.GetWorldPos3D();
    }
    else
    {
      return vessel.orbit.getPositionAtUT(Planetarium.GetUniversalTime());
    }
  }

 

 

Also I've improved the raycast function that was included in my 'interim' version, making it more robust in general. In case you want to use it, this is the updated one:

  Reveal hidden contents


  public static double RaytraceSphere(Vector3d origin, Vector3d direction, Vector3d center, double radius)
  {
    // operate in sphere object space, so the origin is translated by -sphere_pos
    origin -= center;

    double A = Vector3d.Dot(direction, direction);
    double B = 2.0 * Vector3d.Dot(direction, origin);
    double C = Vector3d.Dot(origin, origin) - radius * radius;
    double discriminant = B * B - 4.0 * A * C;

    // ray missed the sphere (we consider single hits as misses)
    if (discriminant <= 0.0) return double.MaxValue;

    double q = (-B - Math.Sign(B) * Math.Sqrt(discriminant)) * 0.5;
    double t0 = q / A;
    double t1 = C / q;
    double dist = Math.Min(t0, t1);

    // if sphere is behind, return maxvalue, else it is visible and distance is returned
    return dist < 0.0 ? double.MaxValue : dist;
  }


  // return true if the body is visible from the vessel
  // - vessel: vessel to test
  // - dir: normalized vector from vessel to body
  // - dist: distance from vector to body surface
  // - return: true if visible, false otherwise
  public static bool RaytraceBody(Vessel vessel, CelestialBody body, out Vector3d dir, out double dist)
  {
    // shortcuts
    CelestialBody sun = Sun();
    CelestialBody mainbody = vessel.mainBody;
    CelestialBody refbody = vessel.mainBody.referenceBody;

    // generate ray parameters
    Vector3d vessel_pos = Lib.VesselPosition(vessel);
    dir = body.position - vessel_pos;
    dist = dir.magnitude;
    dir /= dist;
    dist -= body.Radius;

    // store list of occluders
    List<CelestialBody> occluders = new List<CelestialBody>();

    // do not trace against the mainbody if that is our target
    if (body != mainbody) occluders.Add(mainbody);

    // do not trace against the reference body if that is our target, or if there isn't one (eg: mainbody is the sun)
    if (body != refbody || refbody == null) occluders.Add(refbody);

    // trace against any satellites, but not when mainbody is the sun (eg: mainbody is a planet)
    // we avoid the mainbody=sun case because it has a lot of satellites and the chances of occlusion are very low
    // and they probably will occlude the sun only partially at best in that case
    if (mainbody != sun) occluders.AddRange(mainbody.orbitingBodies);

    // do the raytracing
    double min_dist = double.MaxValue;
    foreach(CelestialBody cb in occluders)
    {
      min_dist = Math.Min(min_dist, RaytraceSphere(vessel_pos, dir, cb.position, cb.Radius));
    }

    // return true if body is visible from vessel
    return dist < min_dist;
  }

 

 

Thanks! Yeah it's totally not tested, but I said that. I'll take a look at it tonight. Right now on my way to real work.

Link to comment
Share on other sites

20 hours ago, JPLRepo said:

Woop Woop. Thanks again JPL. I worked a long day today so I don't know that I'll be able to test these tonight. However, if I am able, I'll try and load it up for a bit to see if it throws any compatibility issue errors with the mods I'm currently using and post back here.

Link to comment
Share on other sites

Hi again @JPLRepo

First, thanks again for your work.

Now, I have a request. I use the mod:

That has a special type of solar panel to capture a resource called "Dust". But this kind of resource is not updated by BackgroundProcessing.

After go over the code I saw this:

Quote

public void Awake(){

...

interestingResources.Add("ElectricCharge");

...

 
 

could it be posible to add a new interesting resource called "Dust"?

Going further, could it be possible to have the "interesting resources" in a config file outside the dll?

 

Link to comment
Share on other sites

This thread is quite old. Please consider starting a new thread rather than reviving this one.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...