TDW
Members-
Posts
77 -
Joined
-
Last visited
Content Type
Profiles
Forums
Developer Articles
KSP2 Release Notes
Everything posted by TDW
-
[1.3] kOS Scriptable Autopilot System v1.1.3.0
TDW replied to erendrake's topic in KSP1 Mod Releases
Yep that's what toggle means, but it's name is just a string and could be anything. The bit that's confusing me is that it is toggle power is turning up in both the event list and the action lists for the module. As I understood it form the docs events were just toggle-able (as you only specify a name) where as actions where settable as you had to specify a name and a state. What I am trying to do is turn other cores on and off from a master core. By adding a boot file to all volumes containing the command [log 1 to flag.ks.] then rebooting the cores 1 at a time to find the volume containing the flag. Write a file in it called my_name.ks that contains [set name to //the corresponding part tag//.]. Repeat this process with all cores so that all volumes contain a file that connects the volume with the part. The master core is selected by a random number race the losers all turn off. This was intended to allow the master to identify it's self as the only one still running. however unless i can find a way to read the power state of the cpu I will need to think of something else. -
[1.3] kOS Scriptable Autopilot System v1.1.3.0
TDW replied to erendrake's topic in KSP1 Mod Releases
With the new access to the right click menu is there a way of reading an actions current state? it can be set with module:doaction(name,bool) and i can read fields with module:getfield(name) but as far as I can tell there is no module:getaction(name) to return the current bool state of an action. eg. no way for 1 cpu to see if another cpu is powered on or off. Edit: Also actions that are also listed as events (eg. "toggle power" on "kosprocessor") for a part module seem to toggle no matter what is set: set cpuList to ship:modulesnamed("kospsocessor"). cpuList[0]:doaction("toggle power",false). //this will shut down the processor. cpuList[0]:doaction("toggle power",true). //this will also shut down the processor. -
[1.3] kOS Scriptable Autopilot System v1.1.3.0
TDW replied to erendrake's topic in KSP1 Mod Releases
@Reisdal Use wait until done as a direct replacement for wait until false. (I'm guessing at the end of your script) the set done to true needs to go above it inside whatever trigger you want to end the script. -
[1.3] kOS Scriptable Autopilot System v1.1.3.0
TDW replied to erendrake's topic in KSP1 Mod Releases
If at the start of the script you do [declare done to false.] Then you can use [wait until done.] and have the finish condition include the statement [set done to true.]. -
[1.3] kOS Scriptable Autopilot System v1.1.3.0
TDW replied to erendrake's topic in KSP1 Mod Releases
This looks like the same issue as here: https://github.com/KSP-KOS/KOS/issues/745 Remove the unset all. command from the script and it should work. From several pages back. -
[1.3] kOS Scriptable Autopilot System v1.1.3.0
TDW replied to erendrake's topic in KSP1 Mod Releases
@Wuwuk Ok so you are staging in the same physics tick as you lock the throttle to 0. If you add a "wait 0.1." between lock throttle to 0 and stage then it will work. The reason you cant shut it down is because it is no longer part of the ship. -
[1.3] kOS Scriptable Autopilot System v1.1.3.0
TDW replied to erendrake's topic in KSP1 Mod Releases
At work so can't test but is the issue is that the throttle hits 0 the jumps up to 50%? If so this is because when the program ends it sets the throttle back to whatever it was when you started the script. Since 0.24 (I think) ksp sets the throttle to 50% at lunch. You're options are to remember to manually throttle down before every launch or download the mod Default Throttle which let's you change the what throttle rockets start on the pad with. -
[1.3] kOS Scriptable Autopilot System v1.1.3.0
TDW replied to erendrake's topic in KSP1 Mod Releases
Ok there are 2 things going on here. 1st there is something odd going on with the way ksp has saved stage info for the parts. You can see this if you use list parts in foo. for part in foo {print part:name+" "+part:stage.}. Most of it doesn't matter too much for most of it but the 2 lower fuel tanks think they are in stage 4 and 6 respectively. This means that ksp is counting the middle tank towards the stage:liquidfuel of the stage below (can be seen in the resource panel). Note: this is a stock bug and there is probably not a lot the kOS devs can do about it. I have tried building an identical vessel to yours several times but cant seem to get the same stage number bug. Did you use something 'fancy' when making it (change root, copy and past parts etc.)? The second part of this is that the (when I built the rocket from scratch to fix the staging issue) is that the engine does not use the last little bit of fuel. This is probably because there is not enough to run the engine for a full physics tick. to fix this you can either increase the threshold or use IF stage:liquidfuel <= 0.01 { STAGE.}.. The other option is to use another means of deciding when to stage. A slight modification to your code LOCK STEERING TO R(0,0,-90) + HEADING(90,90). LOCK THROTTLE TO 1. SET maxT to 0. WHEN SHIP:ALTITUDE > 1000 THEN { LOCK STEERING TO R(0,0,-90) + HEADING(90,45). } UNTIL SHIP:ALTITUDE > 10000 { IF SHIP:MAXTHRUST < maxT or maxt = 0 { STAGE. } SET maxT TO SHIP:MAXTHRUST. WAIT 0.1. } LOCK THROTTLE TO 0. WAIT UNTIL FALSE. Is a far more versatile solution as it will quite happily stage solid or liquid stages, asparagus, cases where the activate engine icon is not in the same stage as the decouple icon and it shouldn't be interfered with by the stock game doing odd stuff to the stage numbering of parts. If you increase the altitude on the until loop it will also stage a Kerbal-X correctly (just need to stick a kOS core on the top and put the launch clamps in the same stage as the first set of engines). -
[1.3] kOS Scriptable Autopilot System v1.1.3.0
TDW replied to erendrake's topic in KSP1 Mod Releases
@Wuwuk You need to set the permissions on the file to allow sharing . Right click the file (on your google drive) and select share then advanced and change it from privet to either "anyone with the link" or "public on the web" -
Hi Is there a mod (or stock setting that I completely missed) that allows action groups and staging to be activated while in the map view?
-
[1.3] kOS Scriptable Autopilot System v1.1.3.0
TDW replied to erendrake's topic in KSP1 Mod Releases
I'm having trouble reproducing your error, even when copy and pasting from your posts. Any chance of the full script and craft files so I can try running it exactly as you have it? -
Scripts updated. [h=3]Added[/h] New scripts for slope & fine tuning geopositions (just encase you want to try and land on the flag pole). [h=3]Changed[/h] Reconfigured most of the great circle calcs to move repeat calculations to a variable. This means they use more variable names but should run faster. (all added variables are in the format result....)
-
[1.3] kOS Scriptable Autopilot System v1.1.3.0
TDW replied to erendrake's topic in KSP1 Mod Releases
Stick the when condition after the countdown loop. Works for me, what’s it doing for you? It will only work with linear rockets (engines set to fire one after the other). So wont work with boosters or asparagus staging as there is still liquid fuel in the stage. -
[1.3] kOS Scriptable Autopilot System v1.1.3.0
TDW replied to erendrake's topic in KSP1 Mod Releases
Depends what you mean. You can do ASCII art style graphs and GUIs in the terminal and vecdraw lets you create on screen arrows. But you have to write/ find a script that turns your numerical flight data into a graph. -
[1.3] kOS Scriptable Autopilot System v1.1.3.0
TDW replied to erendrake's topic in KSP1 Mod Releases
That's cool. I missed that in the change notes. Is it in the docs? -
[1.3] kOS Scriptable Autopilot System v1.1.3.0
TDW replied to erendrake's topic in KSP1 Mod Releases
Not that I have found. If it is so that you can view printed messages after they go off the screen you could use telnet. It keeps everything and has a scroll bar, at least it does in the Linux terminal. -
kOS Nav Tools Download from Github Licence UPDATE: These scripts are now being maintained as part of the KSLib. I thought I would release these, I may add to them as time goes on or I need others. Not only is this not a stand-alone mod, YOU NEED kOS TO RUN THESE,but they are not intended as stand-alone scripts either. They are intended as equations to be called from within other scripts to aid with more complex surface(or near surface) navigation. As this stands there are 4 scripts that use great circle equations to give a variety of results. What does this do? First off these scripts don't do a lot on their own. They are intended to be a tool/equation set for script writers to call from within their own scripts (although there is nothing stopping you just running them if you want). These scripts make use of Great Circle equations, which I am about to do a rubbish job of explaining. A Great Circle is the circle created by on the surface of a sphere by any plane that passes through it's centre. The equator is on example of this as are the lines of longitude around the earth. For more information google is your friend :-P This is useful because these circles are the most direct rout between any two points on the surface of a sphere (in this case a planet or moon). How to use All of these scripts need to be run with their arguments (commented in each script). They each return the variable `result` and the only other variables they use are declared parameters. This is done to minimise conflicts with other scripts. Tip: When flying a plane using body:radius+ship:altitude will give you a more accurate result for scripts that ask for a radius. Scripts Similar to an inclined orbit the bearing you are travelling on will change when using great circles. This equation will give you the initial bearing along the great circle path from point 1 to point 2. Not overly useful when run once but by repeatedly running this with your current position as point 1 you will get a continuously updating bearing along the shortest path to point 2. Declare p1 - point 1 p2 - point 2 Output result - the bearing. This will tell you the geo-position of a point along a great circle path given a starting position, distance and initial bearing. It can be used for checking the layout of terrain up ahead using: RUN gs_destination(ship:geoposition,(-1)*ship:bearing,1000,body:radius). to give you the latlng() position of a point 1km ahead of you and letting you query it for terrain height. So no more crashing into that cliff because you can only track changes in terrain as you pass over it. Declare P1 - starting point b - initial bearing d - distance travelled radius - radius of the sphere you are travelling over (either body:radius or body:radius+ship:altitude). Output result - the point you will end up at (by travelling in a strait line from p1 for d with an initial bearing of resultLat - the latitude of the point. resultLng - the longitude of the point. kOS lets you query the distance to a latlng() position at the moment but it gives you the separation of the points in 3d space so if you ask for the distance to a point directly opposite you on Kerbin it will give tell you the distance is Kerbins diameter. This will give you the surface distance between 2 points. So will tell you the distance is half Kerbins circumference. This is useful if you want to know how far you will actually have to go and how long it will take you at your current surface speed. It can also be used between a 2 arbitrary points not just your vessel's position and another so for lists of way-points you could use something like: SET current To ship:geoposition. SET distance TO 0. FOR point IN waypoints { RUN gs_distance(current,point,body:radius). SET distance TO distance + result. SET current TO point. }. PRINT distance. to give the distance total distance of your current rout. Declare p1 - point 1 p2 - point 2 radius - radius of the sphere you are travelling over (either body:radius or body:radius+ship:altitude). Output result - the distance (in meters) between point 1 and 2. Gives you the midpoint between point 1 and 2 along a great circle path. This is not as obviously useful as the others but I needed it for something I am working on so threw it in as well. Declare p1 - point 1 p2 - point 2 Output result - mid point (as a geoposition). This is for tweaking geopositions manually. It places an arrow at the declared latlng and then allows you to move it around using action groups. (The action groups are set up with the intention that they are mapped to the number pad). 0 - exits the script. 2 - moves the arrow south. 3 - multiplies the movement by 0.1 (eg m -> cm -> mm). 4 - moves west. 5 - logs the position to a file. 6 - moves east. 8 - moves north. 9 - multiplies the movement by 10 (eg mm -> cm -> m). NOTE: While changing to map view will increase the size of the arrows. Action groups don’t work so you cant move it. This gives the slope of a point and its bearing by sampling 4 points around it in a diamond shape. By declaring a bearing (otherwise just use 0) you can get the components of the slope along that bearing and at right angles to it. Also by declaring the incline as 1 it will give you a bearing up the slope and -1 will give you down the slope. By combining this with `gs_destination.ks` it is possible to have the script follow the slope up or down hill to find the flat landing location either at the top of the hill or at the bottom of a gully. (This is not necessarily the closest flat area but it is relatively easy to find by script). Declare p1 - point to sample. bearing - for specifying a direction of travel across point separation - the distance of the sample points from p1. incline - for specifying whether you want the bearing of the uphill(1) slope or the downhill(-1). Output resultSlope - the angle of the slope in degrees (eg 0 is flat 90 is vertical) resultBearing - the bearing up or down the slope (depending on declared incline) resultAproach - the slope in your direction of travel. resultTangent - the slope across your direction of travel (if high could cause you to roll over). This works the same way as `nav_slope_quad.ks` except that it speeds up the calculation by using 3 points. The one you declared and 2 others 45deg either side of the declared bearing. This if the other script lags too mutch try this one. It is faster but the centre of the sample area is not the point you gave it but just past it. Declare p1 - point to sample. bearing - for specifying a direction of travel across point separation - the distance of the sample points from p1. incline - for specifying whether you want the bearing of the uphill(1) slope or the downhill(-1). Output resultSlope - the angle of the slope in degrees (eg 0 is flat 90 is vertical) resultBearing - the bearing up or down the slope (depending on declared incline) resultAproach - the slope in your direction of travel. resultTangent - the slope across your direction of travel (if high could cause you to roll over). This was me playing around. It doesn’t do anything useful automation wise but. It shows the relative height of the terrain in front of you as you fly around. Creds Nivekk for creating kOS and Erendrake and Steve Mading for maintaining and advancing it to where it is today. I should also like to add that the equations are from this site: http://www.movable-type.co.uk/scripts/latlong.html Which contains implementations of these equations in various other languages, and although I haven’t copied any of the script itself it has been an invaluable resource for the base equations.
-
[1.3] kOS Scriptable Autopilot System v1.1.3.0
TDW replied to erendrake's topic in KSP1 Mod Releases
@Gaiiden Using reboot. instead will mean that you don’t have the irritation of having to turn the console back on, you still loss command history though. Just had an idea it's not exactly best practice though SET nonExistantList[1] to x. will cause an exception that will end your script and you will still have your command history and the terminal will still be open. -
[1.3] kOS Scriptable Autopilot System v1.1.3.0
TDW replied to erendrake's topic in KSP1 Mod Releases
if the code is running in a loop the break command might work for you. Ok spoke to soon on the pathfinder script working:(. I have a bug in my path-finding script that I only run into when it has been running for a long time. I don't know if this is a bug with my script or a kos bug but i am getting this: p2 (point 2) when printed appears to be a geo-position(as it should be) and the suffixes lat and lng give the correct behaviour but :terrainheight fails and I can't work out why as it has run lots(possibly thousands) of times already as part of this script without issue. I have included the code if anyone wants to try and reproduce this (it's a bit of a mess sorry). It "should" encountor the error if you leave it running over night (also set the IPU to 2000). Any help fixing this would be greratly apreciated, thanks. wip.ks clearscreen. Set startTime to Time. print "Started at: "+Time:Clock. set slat to ship:latitude. //start lat. set slng to ship:longitude. //start lng. if slng < 0 { set slng to (slng+360). }. set flat to -90. //finish lat. set flng to 0. //finish lng. if flng < 0 { set flng to (flng+360). }. if body = kerbin or body = eve or body = laythe { set water to 1. } else { set water to 0. }. Set dx to 1. set dy to 1. set samplerate to 100. set slopefactor to 800. set traversefactor to 1. //not yet used //=====Vertex info list======= // 0 - geolocation. // 1 - checked connections. // 2 - grid pos x // 3 - grid pos y // 4 - vertex cost. // 5 - x of previous vertex in shortest path. // 6 - y of previous vertex in shortest path. //====Set up grid sphere======= This will be replaced with a cube projection when i get round to it. set grid to list(). //x coordinate on grid set x to 0. set y to -90. until x = 360 { grid:add(list()). //y coordiante on grid until y >= 90-dy { set y to round(y+dy,1). //rounding to remove floating point error that creeps in (dont know how it gets there) grid[grid:length-1]:add(list()). //vertex info grid[grid:length-1][grid[grid:length-1]:length-1]:add(latlng(y,x)). grid[grid:length-1][grid[grid:length-1]:length-1]:add(0). grid[grid:length-1][grid[grid:length-1]:length-1]:add((grid:length-1)). grid[grid:length-1][grid[grid:length-1]:length-1]:add((grid[grid:length-1]:length-1)). }. set y to -90. set x to x + dx. }. set vertextotal to grid:length*grid[0]:length. Print "Grid setup complete.". run gs_distance(grid[0][round(grid[0]:length/2)][0],grid[1][round(grid[1]:length/2)][0],body:radius). set startlimit to 1.5*result. //============================== //=====Set up start/finish====== set start to list(). start:add(latlng(slat,slng)). start:add(0). start:add(-1). start:add(-1). set finish to list(). finish:add(latlng(flat,flng)). finish:add(0). finish:add(-2). finish:add(-2). finish:add(0). //============================== //==Set up neighbors / visited== set neighbors to list(). set visited to list(). visited:add(finish). if finish[0]:lat < (dy - 90) { set pos to 0. until pos >= grid:length-1 { neighbors:add(grid[pos][0]). set pos to pos +1. }. } else if finish[0]:lat > (90 - dy) { set pos to 0. until pos >= grid:length -1 { neighbors:add(grid[pos:index][grid[pos]:length - 1]). set pos to pos +1. }. } else { set x to floor(finish[0]:lng)/dx. set y to (floor(finish[0]:lat)+90) / dy. neighbors:add(grid[x][y]). neighbors:add(grid[x+1][y]). neighbors:add(grid[x+1][y+1]). neighbors:add(grid[x][y+1]). }. neighbors:add(start). //============================== //======Pathfinding============= set activeVertex to finish. set vertexcount to 0. until activeVertex = start { Print "Checking vertex at" +activeVertex[0]. //calculate weighting. for vertex in neighbors { if vertex[0]:terrainheight < 0 and water = 1 { set vertex[1] to 8. } else { set cost to 0. set swimming to false. run gs_distance(activevertex[0],vertex[0],body:radius). set gsdist to result. print "Distance to "+vertex[0]+" is "+gsdist. log "Distance to "+vertex[0]+" is "+gsdist to debug. set floorgsdist to floor(gsdist/samplerate). set count to 0. set p1 to activevertex[0]. until count >= floorgsdist or swimming = true { run gs_bearing(p1,vertex[0]). set gsbear to result. run gs_destination(p1,gsbear,samplerate,body:radius). set p2 to result. if p2:terrainheight < 0 { set swimming to true. print "Can't cross water at "+p2. } else { set cost to cost + samplerate + (slopefactor*abs(p1:terrainheight-p2:terrainheight)/samplerate). }. set p1 to p2. set count to count + 1. }. if swimming = false { run gs_distance(p1,vertex[0],body:radius). set gsdist to result. set cost to cost + gsdist + (slopefactor*abs(p1:terrainheight-vertex[0]:terrainheight)/gsdist). if vertex:length < 5 { set vertex[1] to vertex[1]+1. vertex:add(activevertex[4]+cost). vertex:add(activevertex[2]). vertex:add(activevertex[3]). Set listmax to visited:length-1. set listmin to 0. until listmin > listmax { set listmid to floor((listmax+listmin)/2). if vertex[4] > visited [listmid][4] { set listmin to listmid+1. } else if vertex[4] < visited [listmid][4] { set listmax to listmid-1. } else { set listmin to listmid. set listmax to listmid-1. }. }. if listmin = visited:length { visited:add(vertex). } else { visited:insert(listmin,vertex). }. } else if activevertex[4]+cost < vertex[4] { set listmax to visited:length-1. set listmin to 0. until listmin > listmax { set listmid to floor((listmax+listmin)/2). if vertex[4] > visited [listmid][4] { set listmin to listmid+1. } else if vertex[4] < visited [listmid][4] { set listmax to listmid-1. } else { set listmin to listmid. set listmax to listmid-1. }. }. if vertex[0] = visited [listmin][0]{ visited:remove(listmin). }. set vertex[1] to vertex[1]+1. set vertex[4] to activevertex[4]+cost. set vertex[5] to activevertex[2]. set vertex[6] to activevertex[3]. Set listdmax to visited:length-1. set listmin to 0. until listmin > listmax { set listmid to floor((listmax+listmin)/2). if vertex[4] > visited [listmid][4] { set listmin to listmid+1. } else if vertex[4] < visited [listmid][4] { set listmax to listmid-1. } else { set listmin to listmid. set listmax to listmid-1. }. }. if listmin = visited:length { visited:add(vertex). } else { visited:insert(listmin,vertex). }. } else { set vertex[1] to vertex[1]+1. }. } else { set vertex[1] to vertex[1]+1. }. if vertex[2] = -1 { set start to vertex. } else { set x to vertex[2]. set y to vertex[3]. set grid[x][y] to vertex. }. }. }. print "remove active vertex from visited list". visited:remove(0). print "select new active vertex". set activevertex to visited[0]. // set vertexcount to vertexcount+1. // set timetaken to time-starttime. // Print "Time taken: " +Timetaken:clock +" " at (0,1). // print "Vertecies Checked: "+vertexcount+" of "+vertextotal+" " at (0,2). if activevertex = start {} else { print "create new neighbors list". set neighbors to list(). run gs_distance(start[0],activevertex[0],body:radius). if result < startlimit { neighbors:add(start). }. set nx to -1. until nx > 1 { if nx = 0 { set z to 2. } else { set z to 1. }. set ny to -1. until ny > 1 { set vx to activevertex[2]+nx. if vx < 0 { set vx to grid:length-1. } else if vx > grid:length-1 { set vx to 0. }. set vy to activevertex[3]+ny. if vy < 0 or vy > grid[activevertex[2]]:length-1 { set vy to activevertex[3]. if vx < grid:length / 2 { set vx to vx + (grid:length / 2). } else { set vx to vx - (grid:length / 2). }. }. if grid[vx][vy][1] < 8 { neighbors:add(grid[vx][vy]). }. set ny to ny + z. }. set nx to nx + 1. }. // print "remove active vertex from neighbors". // set pos to 0. // until pos = neighbors:length { // print "checking neighbors["+pos+"]". // if neighbors[pos] = activevertex { // neighbors:remove(pos). // set pos to neighbors:length-1. // }. // set pos to pos+1. // }. }. }. print "rout calculated". //============================== //=====Save waypoint list======= set rout to list(). set activevertex to start. Until activevertex = finish { if activevertex[5] = -2 { set activevertex to finish. } else { set activevertex to grid[activevertex[5]][activevertex[6]]. }. rout:add(activevertex[0]). }. Log rout to waypoints. //any angle smoothing pass //============================== //====Driving=================== gs_bearing.ks declare parameter p1,p2. set result to arctan2(sin(p2:lng-p1:lng)*cos(p2:lat),cos(p1:lat)*sin(p2:lat)-sin(p1:lat)*cos(p2:lat)*cos(p2:lng-p1:lng)). gs_destination.ks declare parameter p1, b, d, radius. //(start point,bearing,distance,radius(planet/moon)). set resultA to (d*180)/(radius*constant():pi). set resultB to arcsin(sin(p1:lat)*cos(resultA)+cos(p1:lat)*sin(resultA)*cos(). set resultC to p1:lng+arctan2(sin(*sin(resultA)*cos(p1:lat),cos(resultA)-sin(p1:lat)*sin(resultB)). set result to latlng(resultB,resultC). gs_distance.ks declare parameter p1, p2, radius. //(point1,point2,radius(planet/moon)). set resultA to sin((p1:lat-p2:lat)/2)^2 + cos(p1:lat)*cos(p2:lat)*sin((p1:lng-p2:lng)/2)^2. set result to radius*constant():PI*arctan2(sqrt(resultA),sqrt(1-resultA))/90. -
[1.7.3] Exploration Rover System by A.S.E.T. v0.3 (04.08.19)
TDW replied to alexustas's topic in KSP1 Mod Development
Don't know if you solved this in the mean time (it has been a while) but the OP hasn’t been updated since October; the firespitter plug-in there is out of date. The firespitter OP also hasn’t been updated for 0.90 so your best bet it to extract the .dll from a mod that is kept up to date. My go to mod for the firespitter.dll at the moment is RoverDude's MKS/OKS mod found here: http://forum.kerbalspaceprogram.com/threads/79588 -
[1.3] kOS Scriptable Autopilot System v1.1.3.0
TDW replied to erendrake's topic in KSP1 Mod Releases
The algorithm "works" at the moment it's just not very efficient. The cubed sphere should cut down the number of vertices by 1/3 and speed up route calculation around the poles. The weighting is already calculated based on the great circle distance between the two points along with a terrain modifier calculated by sampling along that path. Couple of other optimisations that I intend to try are changing the visited list to a sorted list and adding an A* weighting. But I have those sorted (at least in my head). A way of converting between lat-long possitions and cubed sphere positions is what I'm having trouble working out. It was mostly just a vague hope that someone here had created one before and could supply / suggest a pseudocode algorithm I could use as a starting point. -
[1.3] kOS Scriptable Autopilot System v1.1.3.0
TDW replied to erendrake's topic in KSP1 Mod Releases
Edit: the algorithm as it stands does not create a hight map for the entire planet at the start that is calculated on the fly as you suggest, what it does need though is a list of all valid positions on the globe as setting them up on the fly without overlap is trickier. at the moment the algorithm only pre-stores a list of each vertex containing: [0] - its latlng() position [1] - the number of checked connections (initially set to 0) [2]/[3] - its x/y position on the grid (used for moving it in and out of working lists) Initially the pre-storing of the data was to overcome the issues with having to backfill the array when going round an obstacle eg. not being able to add data at grid[5][7] when grid[5][4] had not added to the grid. The reason behind arranging the points on a grid this way was that it made finding neighbouring vertices quick as they were the ones surrounding you on the grid, instead of having the program search the entire list to find veracities within a set range. Also if the veracities are created on the fly extra checking needs to be done to avoid adding new ones within a set distance of pre-existing ones. The future plan for the script is to have it split up into 2 parts with the initial part creating an array/list containing all the vertices and the cost between them and their neighbours (possibly with some any-angle edges thrown in), it would then export this to a file that could be run in the future to load the whole thing back up, without doing any calculation, and then do path-finding on that without ever having to do the cost calculations for that body again. One advantage of the cubed sphere(other than more uniform distribution) is that it would be that it is fairly simple to set up so it only loads the other faces when they are needed. -
[1.3] kOS Scriptable Autopilot System v1.1.3.0
TDW replied to erendrake's topic in KSP1 Mod Releases
Hi Does anyone have a kOS script / can think of a method to create (using kOS) a cubed sphere array in ksp? for those that haven't seen one before a cubed sphere looks like this: The intention would be to have an array for each face containing the lat-long of each vertex (point where the lines cross) for use in a pathfinding script. -
[1.3] kOS Scriptable Autopilot System v1.1.3.0
TDW replied to erendrake's topic in KSP1 Mod Releases
Ok... so... I may have accidentally broken kOS. I think the 3600x1800 array may be partially responsible:blush:. (just a quick note to Steve and Erendrake I am not asking for a fix it's just a horrifyingly inefficient script & thank-you for the awesome mod). I don't know if this works yet (the script is still running) and there is still some bits that need adding. Also I have already started working on a re-write of it. Anyway here it is: A kOS version of Dijkstra's path-finding algorithm:). It is intended to produce a way-point list that will take a rover to its target destination avoiding water and rough terrain. Note: if you try to run this i suggest wacking the IPU up to 2000 and leaving it running over night. It is a very brute force approach and the current settings have the equatorial vertices spaced around 1km(they get denser nearer the polls) and samples the terrain every 5m along its projected route. EDIT: changed settings after leaving it running over night ksp was using ~20Gb or Ram and had slowed down masively as it was running in swap. EDIT2: This now runs!!! The sample rate is low(ish) and the cost for change in terrain height needs balancing but it runs:D. The main script. clearscreen. set slat to ship:latitude. //start lat. set slng to ship:longitude. //start lng. if slng < 0 { set slng to (slng+360). }. set flat to -90. //finish lat. set flng to 0. //finish lng. if flng < 0 { set flng to (flng+360). }. if body = kerbin or body = eve or body = laythe { set water to 1. } else { set water to 0. }. Set dx to 1. set dy to 1. set samplerate to 100. set slopefactor to 1. set traversefactor to 1. //not yet used //=====Vertex info list======= // 0 - geolocation. // 1 - checked connections. // 2 - grid pos x // 3 - grid pos y // 4 - vertex cost. // 5 - x of previous vertex in shortest path. // 6 - y of previous vertex in shortest path. //====Set up grid sphere======= This will be replaced with a cube projection when i get round to it. set grid to list(). //x coordinate on grid set x to 0. set y to -90. until x = 360 { grid:add(list()). //y coordiante on grid until y > 90-dy { set y to round(y+dy,1). //rounding to remove floating point error that creeps in (dont know how it gets there) grid[grid:length-1]:add(list()). //vertex info grid[grid:length-1][grid[grid:length-1]:length-1]:add(latlng(y,x)). grid[grid:length-1][grid[grid:length-1]:length-1]:add(0). grid[grid:length-1][grid[grid:length-1]:length-1]:add((grid:length-1)). grid[grid:length-1][grid[grid:length-1]:length-1]:add((grid[grid:length-1]:length-1)). }. set y to -90. set x to x + dx. }. Print "Grid setup complete.". //============================== //=====Set up start/finish====== set start to list(). start:add(latlng(slat,slng)). start:add(0). start:add(-1). start:add(-1). set finish to list(). finish:add(latlng(flat,flng)). finish:add(0). finish:add(-2). finish:add(-2). finish:add(0). //============================== //==Set up neighbors / visited== set neighbors to list(). set visited to list(). //visited:add(start). visited:add(finish). if finish[0]:lat < (dy - 90) { set pos to 0. until pos >= grid:length-1 { neighbors:add(grid[pos][0]). set pos to pos +1. }. } else if finish[0]:lat > (90 - dy) { set pos to 0. until pos >= grid:length -1 { neighbors:add(grid[pos:index][grid[pos]:length - 1]). set pos to pos +1. }. } else { set x to floor(finish[0]:lng)/dx. set y to (floor(finish[0]:lat)+90) / dy. neighbors:add(grid[x][y]). neighbors:add(grid[x+1][y]). neighbors:add(grid[x+1][y+1]). neighbors:add(grid[x][y+1]). }. neighbors:add(start). //============================== //======Pathfinding============= set activeVertex to finish. until activeVertex = start { Print "Checking vertex at" +activeVertex[0]. //calculate weighting. for vertex in neighbors { if vertex[0]:terrainheight < 0 and water = 1 { set vertex[1] to 8. } else { set cost to 0. set swimming to false. run gs_distance(activevertex[0],vertex[0],body:radius). set gsdist to result. print "Distance to "+vertex[0]+" is "+gsdist. // log "Distance to "+vertex[0]+" is "+gsdist to debug. set floorgsdist to floor(gsdist/samplerate). set count to 0. set p1 to activevertex[0]. until count >= floorgsdist or swimming = true { run gs_bearing(p1,vertex[0]). set gsbear to result. run gs_destination(p1,gsbear,samplerate,body:radius). set p2 to result. if p2:terrainheight < 0 { set swimming to true. print "Can't cross water at "+p2. } else { set cost to cost + samplerate + (slopefactor*abs(p1:terrainheight-p2:terrainheight)/samplerate). }. set p1 to p2. set count to count + 1. }. if swimming = false { run gs_distance(p1,vertex[0],body:radius). set gsdist to result. set cost to cost + gsdist + (slopefactor*abs(p1:terrainheight-vertex[0]:terrainheight)/gsdist). if vertex:length < 5 { set vertex[1] to vertex[1]+1. vertex:add(activevertex[4]+cost). vertex:add(activevertex[2]). vertex:add(activevertex[3]). visited:add(vertex). } else if activevertex[4]+cost < vertex[4] { set vertex[1] to vertex[1]+1. set vertex[4] to activevertex[4]+cost. set vertex[5] to activevertex[2]. set vertex[6] to activevertex[3]. } else { set vertex[1] to vertex[1]+1. }. } else { set vertex[1] to vertex[1]+1. }. if vertex[2] = -1 { set start to vertex. } else { set x to vertex[2]. set y to vertex[3]. set grid[x][y] to vertex. }. }. }. print "remove active vertex from visited list". set pos to 0. until pos = visited:length { // print "checking visited["+pos+"]". if visited[pos] = activevertex { visited:remove(pos). set pos to visited:length-1. }. set pos to pos+1. }. print "select new active vertex". set activevertex to visited[0]. for vertex in visited { if vertex[4] < activevertex[4] { set activevertex to vertex. }. }. if activevertex = start {} else { print "create new neighbors list". set neighbors to list(). neighbors:add(start). set nx to -1. until nx > 1 { set ny to -1. until ny > 1 { set vx to activevertex[2]+nx. if vx < 0 { set vx to grid:length-1. } else if vx > grid:length-1 { set vx to 0. }. set vy to activevertex[3]+ny. if vy < 0 or vy > grid[activevertex[2]]:length-1 { set vy to activevertex[3]. if vx < grid:length / 2 { set vx to vx + (grid:length / 2). } else { set vx to vx - (grid:length / 2). }. }. if grid[vx][vy][1] < 8 { neighbors:add(grid[vx][vy]). }. set ny to ny + 1. }. set nx to nx + 1. }. print "remove active vertex from neighbors". set pos to 0. until pos = neighbors:length { // print "checking neighbors["+pos+"]". if neighbors[pos] = activevertex { neighbors:remove(pos). set pos to neighbors:length-1. }. set pos to pos+1. }. }. }. print "rout calculated". //============================== //=====Save waypoint list======= set rout to list(). set activevertex to start. Until activevertex = finish { if activevertex[5] = -2 { set activevertex to finish. } else { set activevertex to grid[activevertex[5]][activevertex[6]]. }. rout:add(activevertex[0]). }. Log rout to waypoints. //any angle smoothing pass //============================== //====Driving=================== Dependancys - these are useful for other stuff too. // Name this "gs_bearing.ks" // This will give you the bearing (at point 1) for the great circle path from point 1 to point 2. declare parameter p1,p2. set result to arctan2(sin(p2:lng-p1:lng)*cos(p2:lat),cos(p1:lat)*sin(p2:lat)-sin(p1:lat)*cos(p2:lat)*cos(p2:lng-p1:lng)). // Name this "gs_distance.ks" // This will give you the great circle distance between point 1 and 2. declare parameter p1, p2, radius. //(point1,point2,radius(planet/moon)). set resultA to sin((p1:lat-p2:lat)/2)^2 + cos(p1:lat)*cos(p2:lat)*sin((p1:lng-p2:lng)/2)^2. set result to radius*constant():PI*arctan2(sqrt(resultA),sqrt(1-resultA))/90. // Name this "gs_destination.ks" // This will give you a destination given a start point, the distance you travel and the initial bearing (assuming you are traveling along a great circle path) declare parameter p1, b, d, radius. //(start point,bearing,distance,radius(planet/moon)). set resultA to (d*180)/(radius*constant():pi). set resultB to arcsin(sin(p1:lat)*cos(resultA)+cos(p1:lat)*sin(resultA)*cos(). set resultC to p1:lng+arctan2(sin(*sin(resultA)*cos(p1:lat),cos(resultA)-sin(p1:lat)*sin(resultB)). set result to latlng(resultB,resultC). -
Would it work to approach this as a resource transfer rate mod instead of a pure electrical systems mod? That way you could limit the discharge rate of an electrical component to f(max charge), you wouldn’t have a fuse that broke though you would just get complainants from parts saying there was insufficient electrical charge. However it would let you apply the same principle to any other resource so for example sticking a mainsail on the smallest fuel tank would prevent the mainsail from firing at max thrust because it simply could not drain the tank fast enough.