Jump to content

[1.3] kOS Scriptable Autopilot System v1.1.3.0


erendrake

Recommended Posts

Are there any obvious errors in my code that I missed? The rover is just saying that it's driving, but it "arrives" instantly, and never actually does anything.

Boot file:

// First, set the ship to a known configuration.

SET SHIP:CONTROL:PILOTMAINTHROTTLE TO 0.
LIGHTS OFF.
GEAR OFF.
IF SHIP:NAME = "Relay"
{
	SET SHIP:TYPE TO "rover".
}
IF SHIP:TYPE = "rover"
{
	BRAKES ON.
}
ELSE
{
	BRAKES OFF.
}
SAS OFF.
RCS OFF.

FUNCTION NOTIFY
{
	PARAMETER message, priority.
	IF priority = "NOMINAL"
	{
		SET col TO GREEN.
	}
	ELSE IF priority = "ALERT"
	{
		SET col TO RGB((251/255),(66/255),(0/255)). // Bright orange
	}
	ELSE IF priority = "WARNING"
	{
		SET col TO RED.
	}
	HUDTEXT("kOS: " + message, 2, 2, 30, col, FALSE).
}

FUNCTION ON_DRIVE
{
	PARAMETER n, vol.
	
	SWITCH TO vol. LIST FILES IN allFiles.
	FOR f IN allFiles
	{
		IF f:NAME = n
		{
			SWITCH TO 1. RETURN TRUE.
		}
	}
	SWITCH TO 1. RETURN FALSE.
}

FUNCTION DELAY
{
	SET ksc TO LATLNG(-0.131331503391266, -74.594841003418).
	SET dTime TO ksc:DISTANCE / 299792458.	// Total delay time
	SET accTime TO 0.						// Accumulated time

	UNTIL accTime >= dTime
	{
		SET start TO TIME:SECONDS.
		WAIT UNTIL (TIME:SECONDS - start) > (dTime - accTime) OR NOT ADDONS:RT:HASCONNECTION(SHIP).
		SET accTime TO accTime + TIME:SECONDS - start.
	}
}


// Get a file from KSC
FUNCTION DOWNLOAD {
  PARAMETER f.

  DELAY().
  IF ON_DRIVE(f, 1) {
    DELETE f.
  }
  IF ON_DRIVE(f, 0) {
    SWITCH TO 0.
	COPY f TO 1.
	SWITCH TO 1.
  }
}

// Put a file on KSC
FUNCTION UPLOAD {
  PARAMETER f.

  DELAY().
  IF ON_DRIVE(f, 0) {
    SWITCH TO 0. DELETE f. SWITCH TO 1.
  }
  IF ON_DRIVE(f, 1) {
    COPY f TO 0.
  }
}

// Run a library, downloading it from KSC if necessary
FUNCTION REQUIRE
{
	PARAMETER lib.
	IF NOT ON_DRIVE(lib, 1)
	{
		DOWNLOAD(lib).
	}
	RENAME lib TO "new_library.ks".
	RUN new_library.
	RENAME "new_library.ks" TO lib.
}

// THE ACTUAL BOOTUP PROCESS
SET updateScript TO SHIP:NAME + ".update.ks".

// If we have a connection, see if there are new instructions. If so, download 
// and run them.
IF ADDONS:RT:HASCONNECTION(SHIP)
{
	IF ON_DRIVE(updateScript, 0) // If the update script exists on the archive, download and run it.
	{
		IF ON_DRIVE("update.ks", 1) // If an old file exists on the archive
		{
			NOTIFY("An old update file already exists. Deleting old file...", "ALERT").
			WAIT 5.
			DELETE update.ks.
		}
		
		DOWNLOAD(updateScript).
		SWITCH TO 0. DELETE updateScript. SWITCH TO 1.
				
		// Whichever situation is true, we now have an up-to-date file
		NOTIFY("Update file found! Executing...", "NOMINAL").
		WAIT 5.
		RENAME updateScript TO "update.ks".
		RUN update.ks.
		DELETE update.ks.
	}
	ELSE // We don't have an update script, so do nothing.
	{
		NOTIFY("No update file found. Either you haven't created one or one is not necessary.", "ALERT").
	}
	// If a startup.ks file exists on the disk, run that.
	SET bootScript TO SHIP:NAME + ".startup.ks".
	IF ON_DRIVE(bootScript, 1)
	{
		SWITCH TO 1. DELETE bootScript. // If we already have an old startup file, delete it.
		IF ON_DRIVE(startup.ks, 1)
		{
			SWITCH TO 1.
			DELETE startup.ks.
		}
		IF ON_DRIVE(bootScript, 0)
		{
			DOWNLOAD(bootScript).
			RENAME bootScript TO "startup.ks".
			RUN startup.ks.
		}
		ELSE
		{
			NOTIFY("Startup failed! Instructions not found.", "WARNING"). WAIT 5. REBOOT.
		}
	}
	ELSE IF ON_DRIVE(bootScript, 0)
	{
		IF NOT ON_DRIVE(bootScript, 1)
		{
			DOWNLOAD(bootScript).
			RENAME bootScript TO "startup.ks".
			RUN startup.ks.
			DELETE startup.ks.
		}
		ELSE
		{
			DELETE bootScript.
			DOWNLOAD(bootScript).
			RENAME bootScript TO "startup.ks".
			RUN startup.ks.
			DELETE startup.ks.
		}
	}
}
ELSE
{
	WAIT UNTIL ADDONS:RT:HASCONNECTION(SHIP).
	WAIT 5. // Avoid thrashing the CPU (when no startup.ks, but we have a
			// persistent connection, it will continually reboot)
	REBOOT.
}

Startup file:

// Relay rover startup file
// Lists the number of active "relay" rovers
// and bases its navigation software on that.

// Download the appropriate libraries
DOWNLOAD(autoNav.ks).

// List the active relays
LIST TARGETS IN allVessels.
SET relays TO LIST().
FOR t IN allVessels
{
	IF t:NAME = "Relay"
	{
		relays:ADD(t).
	}
}
SET iterationNum TO relays:LENGTH + 1. // Because computers count from 0
IF iterationNum = 1
{
	RUN autoNav(0). // Go north
}
ELSE IF iterationNum = 2
{
	RUN autoNav(270). // Go west
}
ELSE IF iterationNum = 3
{
	RUN autoNav(180). // Go south, so we don't drive into the ocean
}
ELSE IF iterationNum = 4
{
	RUN autoNav(270).
}
ELSE IF iterationNum > 4 // Make it only 1, 2, 3, or 4
{
	SET iterationNum TO CEILING(MOD(iterationNum, 4)).
}
ELSE // If we get something weird, just give up.
{
	NOTIFY("Huh...something's gone wrong...", "WARNING").
	BRAKES ON.
}
DELETE startup.ks. // Do some garbage collection

Navigation file:

PARAMETER direct.
SWITCH TO 1.
DELETE startup.
// The loop... Functions are defined below
IF ADDONS:RT:HASCONNECTION(SHIP)
{
	UNTIL FALSE
	{
		POPULATE(direct).
		DECIDE_NEXT(options).
		NOTIFY("Selecting next waypoint.", "NOMINAL").
		WAIT 0.5.
		NOTIFY("Driving to next waypoint", "NOMINAL").
		DRIVE_TO(nextPoint).
		STOP().
		WAIT 5.
		
		IF NOT ADDONS:RT:HASCONNECTION(SHIP)
		{
			BREAK.
		}
	}
}
ELSE
{
	UNTIL FALSE
	{
		POPULATE(360 - direct).
		DECIDE_NEXT(options).
		NOTIFY("Selecting next waypoint", "NOMINAL").
		WAIT 0.5.
		NOTIFY("Driving to next waypoint", "NOMINAL").
		IF nextPoint:DISTANCE > 10
		{
			DRIVE_TO(nextPoint).
		}
		STOP().
		WAIT 5.
		
		IF ADDONS:RT:HASCONNECTION(SHIP)
		{
			BREAK.
		}
	}
}
PARK().

FUNCTION POPULATE
{
	PARAMETER hdg.
	
	SET offset_90 TO SIN(hdg) * ((360 * 1000) / (BODY:RADIUS * 2 * CONSTANT:PI)). // duh
	SET offset_675 TO offset_90 * SIN(67.5). // 67.5 deg.
	SET offset_45 TO offset_90 * SIN(45). // 45 deg.
	SET offset_225 TO offset_90 * SIN(22.5). // 22.5 deg.
	
	SET lat_here TO SHIP:GEOPOSITION:LAT.
	SET lon_here TO SHIP:GEOPOSITION:LNG.
	SET op_A TO LATLNG((lat_here + offset_225), (lon_here - offset_675)).
	SET op_B TO LATLNG((lat_here + offset_45), (lon_here - offset_45)).
	SET op_C TO LATLNG((lat_here + offset_90), lon_here).
	SET op_D TO LATLNG((lat_here + offset_45), (lon_here + offset_45)).
	SET op_E TO LATLNG((lat_here + offset_225), (lon_here + offset_675)).
	
	SET options TO LIST
	(
		op_A, op_B, op_C, op_D, op_E
	).
	
	RETURN options.
}

FUNCTION SLOPE_IS_SAFE
{
	PARAMETER option.
	SET here TO SHIP:GEOPOSITION.
	SET there TO option.
	SET slope TO ABS(ARCTAN2(there:TERRAINHEIGHT - here:TERRAINHEIGHT, 100)).
	IF slope < 15
	{
		RETURN TRUE.
	}
	ELSE
	{
		RETURN FALSE.
	}
}

FUNCTION DECIDE_NEXT
{
	PARAMETER options.
	SET startPos TO 0.
	UNTIL startPos > options:LENGTH - 1
	{
		SET o TO options[startPos].
		IF SLOPE_IS_SAFE(o)
		{
			SET nextPoint TO o.
			RETURN nextPoint.
			BREAK.
		}
		ELSE
		{
			SET startPos TO startPos + 1.
		}
	}
}

FUNCTION DRIVE_TO
{
	PARAMETER point.
	
	BRAKES OFF.
	SET spd TO 1. // Really stinkin' slow, but safe.

	// Throttle control variables
	SET throttlePID TO PIDLOOP(0.15, 0.05, 0.1, -1.0, 1.0).
	SET throttlePID:SETPOINT TO spd.

	// Steering control variables
	SET steerPID TO PIDLOOP(0.15, 0.05, 0.1, -1.0, 1.0).
	SET steerPID:SETPOINT TO point:HEADING.
	
	CLEARSCREEN.
	
	SET thrott TO 0.
	SET steerVal TO 0.
	UNTIL FALSE
	{
		IF point:DISTANCE > 10
		{
			SET thrott TO throttlePID:UPDATE(TIME:SECONDS, SHIP:GROUNDSPEED).
			SET steerVal TO steerPID:UPDATE(TIME:SECONDS, SHIP:HEADING).
			
			LOCK WHEELTHROTTLE TO thrott.
			LOCK WHEELSTEER TO steerVal.
			
			PRINT "Current Location: " + ROUND(SHIP:GEOPOSITION:LAT,3) + ", " + ROUND(SHIP:GEOPOSITION:LNG,3) at (0,3).
			PRINT "Next waypoint: " + ROUND(point:LAT,3) + ", " + ROUND(point:LNG, 3) AT (0,4).
			PRINT "Throttle: " + ROUND(thrott, 3) AT (0,9).
			PRINT "Steering:    " + ROUND(steerVal,3) AT (0,10).
			
			WAIT 0.01.
		}
		ELSE
		{
			STOP().
			BREAK.
		}
	}
}

FUNCTION STOP
{
	SET WHEELSTEER TO 0.
	UNLOCK WHEELTHROTTLE.
	IF NOT BRAKES
	{
		BRAKES ON.
	}
	UNLOCK WHEELSTEERING. NOTIFY("Arrived!", "NOMINAL").
}

FUNCTION PARK
{
	STOP().
	LIST PARTS.
	FOR p IN PARTS
	{
		p:GETMODULE("ModuleAnimateGeneric"):DOEVENT("Extend").
		p:GETMODULE("ModuleLight"):DOEVENT("Lights on").
	}
	SWITCH TO 1.
	DELETE autoNav.
}

 

Link to comment
Share on other sites

Hmmm... *more derps later...*

// First, set the ship to a known configuration.

SET SHIP:CONTROL:PILOTMAINTHROTTLE TO 0.
LIGHTS OFF.
GEAR OFF.
IF SHIP:NAME = "Relay"
{
	SET SHIP:TYPE TO "rover".
}
IF SHIP:TYPE = "rover"
{
	BRAKES ON.
}
ELSE
{
	BRAKES OFF.
}
SAS OFF.
RCS OFF.

FUNCTION NOTIFY
{
	PARAMETER message, priority.
	IF priority = "NOMINAL"
	{
		SET col TO GREEN.
	}
	ELSE IF priority = "ALERT"
	{
		SET col TO RGB(255, 79, 0). // International orange
	}
	ELSE IF priority = "WARNING"
	{
		SET col TO RED.
	}
	HUDTEXT("kOS: " + message, 2, 2, 30, col, FALSE).
}

FUNCTION ON_DRIVE
{
	PARAMETER n, vol.
	
	SWITCH TO vol. LIST FILES IN allFiles.
	FOR f IN allFiles
	{
		IF f:NAME = n
		{
			SWITCH TO 1. RETURN TRUE.
		}
	}
	SWITCH TO 1. RETURN FALSE.
}

FUNCTION DELAY
{
	SET ksc TO LATLNG(-0.131331503391266, -74.594841003418).
	SET dTime TO ksc:DISTANCE / 299792458.	// Total delay time
	SET accTime TO 0.						// Accumulated time

	UNTIL accTime >= dTime
	{
		SET start TO TIME:SECONDS.
		WAIT UNTIL (TIME:SECONDS - start) > (dTime - accTime) OR NOT ADDONS:RT:HASCONNECTION(SHIP).
		SET accTime TO accTime + TIME:SECONDS - start.
	}
}


// Get a file from KSC
FUNCTION DOWNLOAD {
  PARAMETER f.

  DELAY().
  IF ON_DRIVE(f, 1) {
    DELETE f.
  }
  IF ON_DRIVE(f, 0) {
    SWITCH TO 0.
	COPY f TO 1.
	SWITCH TO 1.
  }
}

// Put a file on KSC
FUNCTION UPLOAD {
  PARAMETER f.

  DELAY().
  IF ON_DRIVE(f, 0) {
    SWITCH TO 0. DELETE f. SWITCH TO 1.
  }
  IF ON_DRIVE(f, 1) {
    COPY f TO 0.
  }
}

// Run a library, downloading it from KSC if necessary
FUNCTION REQUIRE
{
	PARAMETER lib.
	IF NOT ON_DRIVE(lib, 1)
	{
		DOWNLOAD(lib).
	}
	RENAME lib TO "new_library.ks".
	RUN new_library.
	RENAME "new_library.ks" TO lib.
}

// THE ACTUAL BOOTUP PROCESS
SET updateScript TO SHIP:NAME + ".update.ks".

// If we have a connection, see if there are new instructions. If so, download 
// and run them.
IF ADDONS:RT:HASCONNECTION(SHIP)
{
	IF ON_DRIVE(updateScript, 0) // If the update script exists on the archive, download and run it.
	{
		IF ON_DRIVE("update.ks", 1) // If an old file exists on the archive
		{
			NOTIFY("An old update file already exists. Deleting old file...", "ALERT").
			WAIT 5.
			DELETE update.ks.
		}
		
		DOWNLOAD(updateScript).
		SWITCH TO 0. DELETE updateScript. SWITCH TO 1.
				
		// Whichever situation is true, we now have an up-to-date file
		NOTIFY("Update file found! Executing...", "NOMINAL").
		WAIT 5.
		RENAME updateScript TO "update.ks".
		RUN update.ks.
		DELETE update.ks.
	}
	ELSE // We don't have an update script, so do nothing.
	{
		NOTIFY("No update file found. Either you haven't created one or one is not necessary.", "ALERT").
	}
	// If a startup.ks file exists on the disk, run that.
	SET bootScript TO SHIP:NAME + ".startup.ks".
	IF ON_DRIVE(bootScript, 1)
	{
		SWITCH TO 1. DELETE bootScript. // If we already have an old startup file, delete it.
		IF ON_DRIVE(startup.ks, 1)
		{
			SWITCH TO 1.
			DELETE startup.ks.
		}
		IF ON_DRIVE(bootScript, 0)
		{
			DOWNLOAD(bootScript).
			RENAME bootScript TO "startup.ks".
			RUN startup.ks.
		}
		ELSE
		{
			NOTIFY("Startup failed! Instructions not found.", "WARNING"). WAIT 5. REBOOT.
		}
	}
	ELSE IF ON_DRIVE(bootScript, 0)
	{
		IF NOT ON_DRIVE(bootScript, 1)
		{
			DOWNLOAD(bootScript).
			RENAME bootScript TO "startup.ks".
			RUN startup.ks.
			DELETE startup.ks.
		}
		ELSE
		{
			DELETE bootScript.
			DOWNLOAD(bootScript).
			RENAME bootScript TO "startup.ks".
			RUN startup.ks.
			DELETE startup.ks.
		}
	}
}
ELSE
{
	WAIT UNTIL ADDONS:RT:HASCONNECTION(SHIP).
	WAIT 5. // Avoid thrashing the CPU (when no startup.ks, but we have a
			// persistent connection, it will continually reboot)
	REBOOT.
}

 

// Relay rover startup file
// Lists the number of active "relay" rovers
// and bases its navigation software on that.

// Download the appropriate libraries
DOWNLOAD(autoNav.ks).

// List the active relays
LIST TARGETS IN allVessels.
SET relays TO LIST().
FOR t IN allVessels
{
	IF t:NAME = "Relay"
	{
		relays:ADD(t).
	}
}
SET iterationNum TO relays:LENGTH + 1. // Because computers count from 0
IF relays:LENGTH = 0
{
	SET iterationNum TO 2.
}
IF iterationNum = 1
{
	RUN autoNav(0). // Go north
}
ELSE IF iterationNum = 2
{
	RUN autoNav(270). // Go west
}
ELSE IF iterationNum = 3
{
	RUN autoNav(180). // Go south
}

ELSE IF iterationNum > 3 // Make it only 1, 2, or 3
{
	SET iterationNum TO CEILING(MOD(iterationNum, 3)).
}
ELSE // If we get something weird, just give up.
{
	NOTIFY("Huh...something's gone wrong...", "WARNING").
	BRAKES ON.
}
PARAMETER direct.
SWITCH TO 1.
DELETE startup.ks. // Do some garbage collection

// The loop... Functions are defined below
IF ADDONS:RT:HASCONNECTION(SHIP)
{
	UNTIL FALSE
	{
		POPULATE(direct).
		DECIDE_NEXT(options).
		NOTIFY("Selecting next waypoint.", "NOMINAL").
		WAIT 0.5.
		NOTIFY("Driving to next waypoint", "NOMINAL").
		DRIVE_TO(nextPoint).
		STOP().
		WAIT 5.
		
		IF NOT ADDONS:RT:HASCONNECTION(SHIP)
		{
			BREAK.
		}
	}
}
ELSE
{
	UNTIL FALSE
	{
		POPULATE(360 - direct).
		DECIDE_NEXT(options).
		NOTIFY("Selecting next waypoint", "NOMINAL").
		WAIT 0.5.
		NOTIFY("Driving to next waypoint", "NOMINAL").
		IF nextPoint:DISTANCE > 10
		{
			DRIVE_TO(nextPoint).
		}
		STOP().
		WAIT 5.
		
		IF ADDONS:RT:HASCONNECTION(SHIP)
		{
			BREAK.
		}
	}
}
PARK(). SHUTDOWN.

FUNCTION POPULATE
{
	PARAMETER hdg.
	
	SET offset_90 TO SIN(hdg) * ((360 * 1000) / (BODY:RADIUS * 2 * CONSTANT:PI)). // duh
	SET offset_675 TO offset_90 * SIN(67.5). // 67.5 deg.
	SET offset_45 TO offset_90 * SIN(45). // 45 deg.
	SET offset_225 TO offset_90 * SIN(22.5). // 22.5 deg.
	
	SET lat_here TO SHIP:GEOPOSITION:LAT.
	SET lon_here TO SHIP:GEOPOSITION:LNG.
	SET op_A TO LATLNG((lat_here + offset_225), (lon_here - offset_675)). // 67.5 deg. left
	SET op_B TO LATLNG((lat_here + offset_45), (lon_here - offset_45)). // 45 deg. left
	SET op_C TO LATLNG((lat_here + offset_90), lon_here). // Straight at the heading
	SET op_D TO LATLNG((lat_here + offset_45), (lon_here + offset_45)). // 45 deg. right
	SET op_E TO LATLNG((lat_here + offset_225), (lon_here + offset_675)). // 67.5 deg. right
	
	SET options TO LIST
	(
		op_A, op_B, op_C, op_D, op_E
	).
	
	RETURN options.
}

FUNCTION SLOPE_IS_SAFE
{
	PARAMETER option.
	SET here TO SHIP:GEOPOSITION.
	SET there TO option.
	SET slope TO ABS(ARCTAN2(there:TERRAINHEIGHT - here:TERRAINHEIGHT, 100)).
	IF slope < 15
	{
		RETURN TRUE.
	}
	ELSE
	{
		RETURN FALSE.
	}
}

FUNCTION DECIDE_NEXT
{
	PARAMETER options.
	SET startPos TO 0.
	UNTIL startPos > options:LENGTH - 1
	{
		SET o TO options[startPos].
		IF SLOPE_IS_SAFE(o)
		{
			SET nextPoint TO o.
			RETURN nextPoint.
			BREAK.
		}
		ELSE
		{
			SET startPos TO startPos + 1.
		}
	}
}

FUNCTION DRIVE_TO
{
	PARAMETER point.
	
	BRAKES OFF.
	SET spd TO 5. // Really stinkin' slow, but safe.

	// Throttle control variables
	SET throttlePID TO PIDLOOP(0.5, 0.1, 0.1, -1.0, 1.0).
	SET throttlePID:SETPOINT TO spd.

	// Steering control variables
	SET steerPID TO PIDLOOP((1/360), 0.0001, 0.2, -1.0, 1.0).
	SET steerPID:SETPOINT TO point:HEADING.
	
	CLEARSCREEN.
	
	SET thrott TO 0. SET steer TO 0.
	UNTIL FALSE
	{
		IF point:DISTANCE > 10
		{
			SET thrott TO throttlePID:UPDATE(TIME:SECONDS, SHIP:GROUNDSPEED).
			SET steer TO steerPID:UPDATE(TIME:SECONDS, SHIP:BEARING).
			
			LOCK WHEELTHROTTLE TO thrott.
			SET SHIP:CONTROL:WHEELSTEER TO steer.
			
			PRINT "								" AT (0,3).
			PRINT "Current Location: " + ROUND(SHIP:GEOPOSITION:LAT,3) + ", " + ROUND(SHIP:GEOPOSITION:LNG,3) at (0,3).
			PRINT "								" AT (0,4).
			PRINT "Next waypoint: " + ROUND(point:LAT,3) + ", " + ROUND(point:LNG, 3) AT (0,4).
			
			PRINT "						" AT (0,9).
			PRINT "Throttle: " + ROUND(thrott, 3) AT (0,9).
			PRINT "						" AT (0,10).
			PRINT "Steering:    " + ROUND(steer,3) AT (0,10).
			
			WAIT 0.01.
		}
		ELSE
		{
			STOP().
			BREAK.
		}
	}
}

FUNCTION STOP
{
	SET WHEELSTEER TO 0.
	UNLOCK WHEELTHROTTLE.
	IF NOT BRAKES
	{
		BRAKES ON.
	}
	UNLOCK WHEELSTEERING. NOTIFY("Arrived!", "NOMINAL").
}

FUNCTION PARK
{
	STOP().
	LIST PARTS.
	FOR p IN PARTS
	{
		p:GETMODULE("ModuleAnimateGeneric"):DOEVENT("Extend").
		p:GETMODULE("ModuleLight"):DOEVENT("Lights on").
	}
}

 

Link to comment
Share on other sites

Release Candidate v1.0.0-pre-1

for KSP v1.1.3 Downloads this release

Download may be found here: https://github.com/KSP-KOS/KOS/releases/tag/v1.0.0-pre-1

This version will not be available on Curse, Spacedock, or CKAN.  Please be sure to report any issues you find on the github issue tracker.

Documentation of pending changes may be found here.

WARNING:

This is a testing released based on the current develop branch. The release definitely contains bugs that have not yet been fixed, and may have bugs we are not yet aware of.

There is a small risk of loosing data both in game and in the script archive.

Please make sure to backup your save file and script files before installing

Link to comment
Share on other sites

Oh hey, I missed the Release Candidate in the middle of putting together my own release notes.  I guess my dev build doesn't require someone to compile their own kOS build after all.

Link to comment
Share on other sites

Any idea why the prerelease would be trying to load a .dll from RoverDude's Survivability Pack? Log highlight:

kOS: Error while loading assembly: FloaterTools, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null, skipping assembly.
Full path: /Volumes/Elements/KSP1.1.3/GameData/UmbraSpaceIndustries/SrvPack/FloaterTools.dll
 
(Filename: /Users/builduser/buildslave/unity/build/artifacts/generated/common/runtime/UnityEngineDebugBindings.gen.cpp Line: 64)

kOS: Exception: Could not load type 'System.Runtime.CompilerServices.ExtensionAttribute' from assembly 'FloaterTools'.
Stack Trace:
  at (wrapper managed-to-native) System.MonoCustomAttrs:GetCustomAttributesInternal (System.Reflection.ICustomAttributeProvider,System.Type,bool)
  at System.MonoCustomAttrs.GetCustomAttributesBase (ICustomAttributeProvider obj, System.Type attributeType) [0x00000] in <filename unknown>:0 
  at System.MonoCustomAttrs.GetCustomAttributes (ICustomAttributeProvider obj, System.Type attributeType, Boolean inherit) [0x00000] in <filename unknown>:0 
  at System.MonoType.GetCustomAttributes (System.Type attributeType, Boolean inherit) [0x00000] in <filename unknown>:0 
  at kOS.Safe.Utilities.AssemblyWalkAttribute.WalkAssembly (System.Reflection.Assembly assembly) [0x00000] in <filename unknown>:0 
  at kOS.Safe.Utilities.AssemblyWalkAttribute.WalkAllAssemblies () [0x00000] in <filename unknown>:0 
 

Full log up to where I noticed the nag message on a terminal is at https://www.dropbox.com/s/ktm87kv8ksiggn7/Player.log?dl=0 .

Link to comment
Share on other sites

5 hours ago, undercoveryankee said:

Any idea why the prerelease would be trying to load a .dll from RoverDude's Survivability Pack? Log highlight:

As part of the new addon code, kOS scans all mod dlls for addon components.  The nag messages there mean that kOS was unable to load the dll due to errors.  When I enabled the feature, I wanted to make sure that addon authors were able to see when their mods mailed to load.  In my testing, I did not see any "current release" mods that caused the nag messages to appear.  What version of "SrvPack" are you using, and does it officially support KSP 1.1.3?  If it turns out to be an issue that "working" mods cause these nag messages, we may need another way to alert users to addon loading errors.  We may need to modify the alert anyways even if the errors are only with mods that don't load properly, to avoid issues surrounding a KSP update, or a mod that "mostly" work with the current version.

Edited by hvacengi
Link to comment
Share on other sites

2 hours ago, hvacengi said:

As part of the new addon code, kOS scans all mod dlls for addon components.  The nag messages there mean that kOS was unable to load the dll due to errors.  When I enabled the feature, I wanted to make sure that addon authors were able to see when their mods mailed to load.  In my testing, I did not see any "current release" mods that caused the nag messages to appear.  What version of "SrvPack" are you using, and does it officially support KSP 1.1.3?  If it turns out to be an issue that "working" mods cause these nag messages, we may need another way to alert users to addon loading errors.  We may need to modify the alert anyways even if the errors are only with mods that don't load properly, to avoid issues surrounding a KSP update, or a mod that "mostly" work with the current version.

@hvacengi It occured to me last night that there's one particular situation where this approach will fail: the case of a interoperability DLL that is designed to add capabilities to mod A if mod B is present.

That said, before I learned 1.0.0 had the communication system, mine was one of those: KIPC depended on kOS and KIPC-KRPC depended on KIPC and KRPC... and I don't recall seeing nag messages for the latter (though that might have been because I was using KSPAssemblyDependency rather than just letting it fail to load)

Maybe having the nags as an option and mentioning that in the documentation for addon developers might be a good way to go?  (And then not disabling the terminal, unless that was removed)

Link to comment
Share on other sites

1 minute ago, dewin said:

@hvacengi It occured to me last night that there's one particular situation where this approach will fail: the case of a interoperability DLL that is designed to add capabilities to mod A if mod B is present.

That said, before I learned 1.0.0 had the communication system, mine was one of those: KIPC depended on kOS and KIPC-KRPC depended on KIPC and KRPC... and I don't recall seeing nag messages for the latter (though that might have been because I was using KSPAssemblyDependency rather than just letting it fail to load)

Maybe having the nags as an option and mentioning that in the documentation for addon developers might be a good way to go?  (And then not disabling the terminal, unless that was removed)

I think I'd be inclined to essentially lock the nag message portion to the DEBUG build, and instruct addon developers that they should only use the DEBUG build to test their addon.  There is also an option to make the nag messages appear once and only once per KSP load, in which case a user may be annoyed by the error the first time but it would still allow them to use kOS by simply cycling the power.  I've also experimented with making a kOS specific debugging window that would allow us to display the messages to the user without necessarily breaking execution.  But either of the first two options shouldn't cause any delay in release, so I'd lean that way for the time being.

Link to comment
Share on other sites

@hvacengi I think preventing the terminal lockout but keeping the nag message would probably be enough, though a developer build would work as well (and kOS is really easy to build).

I was using baregrep/baretail/debug window most of the time anyways, and I'd like to assume that a mod developer is going to be looking at the log regardless.  

Link to comment
Share on other sites

4 hours ago, hvacengi said:

As part of the new addon code, kOS scans all mod dlls for addon components.  The nag messages there mean that kOS was unable to load the dll due to errors.  When I enabled the feature, I wanted to make sure that addon authors were able to see when their mods mailed to load.  In my testing, I did not see any "current release" mods that caused the nag messages to appear.  What version of "SrvPack" are you using, and does it officially support KSP 1.1.3?  If it turns out to be an issue that "working" mods cause these nag messages, we may need another way to alert users to addon loading errors.  We may need to modify the alert anyways even if the errors are only with mods that don't load properly, to avoid issues surrounding a KSP update, or a mod that "mostly" work with the current version.

It's SrvPack 0.5.4, which according to RoverDude's github is the current release.

Link to comment
Share on other sites

39 minutes ago, undercoveryankee said:

It's SrvPack 0.5.4, which according to RoverDude's github is the current release.

Did the release include FloaterTools?  I'm on mobile so can't inspect it, but I suspect it's leftover from a previous version and you didn't delete the old folder first, given this changelog item:

Conversion to stock buoyancy model for floaties

Link to comment
Share on other sites

20 minutes ago, dewin said:

Did the release include FloaterTools?  I'm on mobile so can't inspect it, but I suspect it's leftover from a previous version and you didn't delete the old folder first, given this changelog item:

Conversion to stock buoyancy model for floaties

Yes, FloaterTools.dll is in the download for SrvPack 0.5.4. I'll have to ask RoverDude whether it's safe to remove it.

Link to comment
Share on other sites

4 hours ago, undercoveryankee said:

Yes, FloaterTools.dll is in the download for SrvPack 0.5.4. I'll have to ask RoverDude whether it's safe to remove it.

I don't know that I'd bother RoverDude with that.  It looks like KSP is able to load the dll, I'm not really sure why kOS is not.  The dll appears to handle the part module to let the inflatables float in water, so there's a chance that simply deleting the dll won't have a significant effect on your own gameplay, but I should figure out what is causing the error.

Edited by hvacengi
Link to comment
Share on other sites

1 hour ago, hvacengi said:

I don't know that I'd bother RoverDude with that.  It looks like KSP is able to load the dll, I'm not really sure why kOS is not.  The dll appears to handle the part module to let the inflatables float in water, so there's a chance that simply deleting the dll won't have a significant effect on your own gameplay, but I should figure out what is causing the error.

I had only mentioned it since poking at RoverDude's repository suggested that particular part of the project hadn't been updated in ~4-6 months and the changelogs suggested he changed to stock's implementation of buoyancy -- so it was possibly an oversight that it was included with the release.  Easy enough to test though.

Link to comment
Share on other sites

15 hours ago, hvacengi said:

As part of the new addon code, kOS scans all mod dlls for addon components.  The nag messages there mean that kOS was unable to load the dll due to errors.  ...

I'm seeing similar messages for:

IndicatorLights
BetterBurnTime
ThrottleControlledAvionics

KSPAPIExtensions, Full path: C:\KSP\KSP_113\GameData\SimpleLife\Plugins\KSPAPIExtensions.dll
 

The relevant mods are all loaded by KSP and work fine.

Note that after these "nag" messages come up, the CPU seems to force itself to poweroff, making it non-functional.

Link to comment
Share on other sites

32 minutes ago, Waz said:

I'm seeing similar messages for:

IndicatorLights
BetterBurnTime
ThrottleControlledAvionics

KSPAPIExtensions, Full path: C:\KSP\KSP_113\GameData\SimpleLife\Plugins\KSPAPIExtensions.dll
 

The relevant mods are all loaded by KSP and work fine.

Note that after these "nag" messages come up, the CPU seems to force itself to poweroff, making it non-functional.

Do they all cite KSPAPIExtentions being the issue there?  Cause that dll should no longer be valid for KSP 1.1.x, the functionality was moved into KSP proper.  That one should be OK to delete the dll.

I'm aware that the nag messages make the cpu inoperable.  That was intentional design, with unexpected side effects if there are conflicts with out of date mods (or with working mods that give an error anyways as shown above).  We will be evaluating how to handle these errors.

Link to comment
Share on other sites

Tried to find the answer in the documentation but I'm not 100% certain... Is it still necessary to load the programs at launch time?

I love the mod idea and tried it a while ago but loading it every time at launch got so annoying. Would very much prefer to be able to define which program is run in VAB.

Link to comment
Share on other sites

38 minutes ago, OliverPA said:

Tried to find the answer in the documentation but I'm not 100% certain... Is it still necessary to load the programs at launch time?

I love the mod idea and tried it a while ago but loading it every time at launch got so annoying. Would very much prefer to be able to define which program is run in VAB.

If you save your script in a location that identifies it as bootable, you can set it in the VAB to be loaded and run at processor start. The specifics have changed between kOS versions; for 1.0, you can select any script in the "boot" folder of the archive ("Ships/Script/boot").

Link to comment
Share on other sites

7 hours ago, OliverPA said:

Tried to find the answer in the documentation but I'm not 100% certain... Is it still necessary to load the programs at launch time?

I love the mod idea and tried it a while ago but loading it every time at launch got so annoying. Would very much prefer to be able to define which program is run in VAB.

6 hours ago, undercoveryankee said:

If you save your script in a location that identifies it as bootable, you can set it in the VAB to be loaded and run at processor start. The specifics have changed between kOS versions; for 1.0, you can select any script in the "boot" folder of the archive ("Ships/Script/boot").

Here is the documentation for how boot files work in the current release: http://ksp-kos.github.io/KOS_DOC/commands/files.html#special-handling-of-files-starting-with-boot-example-boot-ks

And here is the pending documentation for how they will work when kOS v1.0.0 is release (or how they do work if you're using the release candidate): http://hvacengi.github.io/KOS/general/volumes.html#special-handling-of-files-in-the-boot-directory

Link to comment
Share on other sites

15 hours ago, dewin said:

I had only mentioned it since poking at RoverDude's repository suggested that particular part of the project hadn't been updated in ~4-6 months and the changelogs suggested he changed to stock's implementation of buoyancy -- so it was possibly an oversight that it was included with the release.  Easy enough to test though.

I didn't try to actually launch a vessel with that part module on it, I just loaded the game with the mod installed.  It could be that it's broken even though it loaded.  Or it could be that only the one attribute is broken, and kOS is the only thing that tries to access the attribute.  I'll try to look into it more tonight.  I'm not sure that the exact cause really matters all that much, the current system is obviously preventing users from using kOS with some other mods and that is more counter productive than ensuring that addon writers see errors in their loads.

I've created an issue on github to discuss how to proceed, I welcome further discussion there: https://github.com/KSP-KOS/KOS/issues/1718

(tagging @Waz and @undercoveryankee since they were involved in the related discussion as well)

Link to comment
Share on other sites

On 12/07/2016 at 1:53 PM, hvacengi said:

Do they all cite KSPAPIExtentions being the issue there?  Cause that dll should no longer be valid for KSP 1.1.x, the functionality was moved into KSP proper.  That one should be OK to delete the dll.

I'm aware that the nag messages make the cpu inoperable.  That was intentional design, with unexpected side effects if there are conflicts with out of date mods (or with working mods that give an error anyways as shown above).  We will be evaluating how to handle these errors.

 

No, there own DLL . Only SimpleLife mentioned KSPAPIExtentions.

A mod loading the dll of every other mod seems to violate the Golden Rule - it would be O(n²). You could argue that kOS is "special ", but couldn't you use config entries to determine what mod DLLs you need to load? That would be faster, more stable, and would allow ModuleManager magic.

Link to comment
Share on other sites

6 hours ago, Waz said:

A mod loading the dll of every other mod seems to violate the Golden Rule - it would be O(n²). You could argue that kOS is "special ", but couldn't you use config entries to determine what mod DLLs you need to load? That would be faster, more stable, and would allow ModuleManager magic.

Instead of using config files, I've elected for dependency based on the assembly name starting with "kOS." (only so that it scans kOS.dll and kOS.Safe.dll properly) and KSP's built in  KSPAssemblyDependency  attribute (which is used by KSP to determine the order in which mods are loaded).  That leaves the decision to support kOS exclusively in the hands of the developer.  I'm not sure that there's a need to use MM magic to configure support, since support needs to be hard coded into the dll anyways.

Link to comment
Share on other sites

8 hours ago, Waz said:

A mod loading the dll of every other mod seems to violate the Golden Rule - it would be O(n²). You could argue that kOS is "special ", but couldn't you use config entries to determine what mod DLLs you need to load? That would be faster, more stable, and would allow ModuleManager magic.

To clarify, having looked over what kOS does, it's not technically loading anything.  It's looking over a list of all DLLs that have been loaded and scanning them for classes that have a given attribute using something called Reflection.  This is a fairly common practice in the C# world, and KSP itself uses it extensively to do things like load addons/scenarios/part modules. Other addons use it too: kRPC uses it for pretty much the same reason kOS does, and my own mod also does it for its own startup.  It's pretty much the best way to track a list of implementations of something without having to hard-code that list.

What I don't understand is why kOS encounters the errors in the first place when none of the other implementations do, again this is with me having looked at the code involved.  But this is moot anyways, since as @hvacengi said it will be restricted to only scanning DLLs that declare KOS as a dependency or match the naming scheme.

Edited by dewin
I hate my phone sometimes
Link to comment
Share on other sites

2 hours ago, dewin said:

What I don't understand is why kOS encounters the errors in the first place when none of the other implementations do, again this is with me having looked at the code involved.  But this is moot anyways, since as @hvacengi said it will be restricted to only scanning DLLs that declare KOS as a dependency or match the naming scheme.

As far as we can tell, it's because kOS is on .NET 3.5 while the mods it's having trouble with are on .NET 4.x.  The methods you're supposed to use to do reflection changed their underlying implementation a bit between those .NET versions.  If you use the .NET 3.5 version of those methods to read through something made with .NET 4.x, it throws an exception.  Supposedly KSP mods aren't supposed to be using .NET 4.x yet, but something magic we don't understand is happening in the stock game that allows some mods to be getting away with it.

The fix is to not attempt to use reflection on the mods who's .NET version is > 4.0 and have the rule that if you want to use kOS"s ADDON system your mod must be using a version of .NET older than 4.0.  Everything else @hvacengi was talking about was about finding a good way to accomplish this.

Link to comment
Share on other sites

7 minutes ago, Steven Mading said:

As far as we can tell, it's because kOS is on .NET 3.5 while the mods it's having trouble with are on .NET 4.x.  The methods you're supposed to use to do reflection changed their underlying implementation a bit between those .NET versions.  If you use the .NET 3.5 version of those methods to read through something made with .NET 4.x, it throws an exception.  Supposedly KSP mods aren't supposed to be using .NET 4.x yet, but something magic we don't understand is happening in the stock game that allows some mods to be getting away with it.

The fix is to not attempt to use reflection on the mods who's .NET version is > 4.0 and have the rule that if you want to use kOS"s ADDON system your mod must be using a version of .NET older than 4.0.  Everything else @hvacengi was talking about was about finding a good way to accomplish this.

Except I could have swore that I had built my own mod a couple times using the .NET 4.5 profile and it registered with kOS just fine.  I ultimately dropped it down because I kept trying to use functionality that doesn't exist, but had no problems otherwise.

Is kOS built using the .NET 3.5 profile or the unity one?  I wonder if that's the difference.  (I also wonder if it's because you are checking parent classes for attributes).

Edited by dewin
Link to comment
Share on other sites

Guest
This topic is now closed to further replies.
×
×
  • Create New...