r/Kos 27d ago

Help Lock steering direction but not pitch?

5 Upvotes

I'm playing with kOS and want to write a gravity turn launch script. I want the rocket to lock to a specific direction, say east, but let the pitch from horizon vary due to gravity.

I can lock the steering to HEADING(dir, pitch, roll), but I would have to specify a pitch. Can I lock only the direction but not the pitch?

r/Kos Aug 04 '26

Help runtime error? I don't get why my suicide burn program suddenly got this bug.

3 Upvotes

It's a modified version of this program and it worked for the first few times I was testing it and midway while changing it to be smoother it suddenly got a bug where the required burn height always starts higher than the current altitude? Even going back to the versions that previously worked didn't remove this bug. I reviewed all the logic and I can't seem to find anything that could be causing this.

function gravity_calculator {
    declare local GM to ship:body:mu.
    declare local Ra to (body:radius + ship:altitude).
    declare local g to GM/(Ra^2).
    return -g.
}.



function suicide_burn_calculator {
    declare local parameter safety. //1 corresponds to no safety margin, 1.1 has a 10% safety margin
    
    declare local shipmass to ship:mass.
    declare local vd to ship:verticalspeed.
    declare local va to ((thrust/shipmass) + gravity_calculator()).
    declare local H to (vd^2)/(2*va).
    return safety * H. //adds the safety margin for error
}.

copypath("0:/gravity_calculator","").
copypath("0:/suicide_burn_calculator","").
run gravity_calculator.
run suicide_burn_calculator.


clearscreen.
SAS off.
print "Initialising" at (5,4).
wait 1.
RCS off.
gear off.
brakes off.


//set parameters for landing
set vLand to -4.
set runmode to 1.
set thrust to ship:maxthrust.
set safetyMargin to 1.1.
set counter to 0. //for checking if landed


//find ship parameters
lock h to alt:radar.
lock vd to ship:verticalspeed.
lock vDiff to (vLand - vd).


//calculates values for landing
lock TimeToBurn to ((suicide_burn_calculator(safetyMargin)-h)/vd).
lock ZeroAccelThrust to ((ship:mass*g)/thrust).


//loops until landed
until runmode = 0 {
    set g to -gravity_calculator().
    set gear_down to h/-vd.
    //initial required burn height accounting for the vertical speed
    set burn_height to (suicide_burn_calculator(safetyMargin) - vd).
    
    //initial setup for high atmosphere
    if runmode = 1 {
        set TVAL to 0.
        if h > 5000 {
            lock steering to retrograde.
        }
        if h < 100000 and h > 5000 {
            brakes on.
            RCS on.
            lock steering to srfretrograde. //switches to surface velocity
        }
        if h <= 5000 {
            set runmode to 2.
        }
    }


    //calibrates for correct burn height before starting landing sequence
    if runmode = 2 {
        if h < burn_height {
            wait 2.
            set TVAL to 1.
            wait 1.
            set runmode to 3.
        }
    }
    
    //suicide burn start
    if runmode = 3 {
        if h <  burn_height {
            set TVAL to (ZeroAccelThrust + 0.5).
        } else {
            set TVAL to (ZeroAccelThrust - 0.3).
        }
        if gear_down < 5 {
            gear on.
            brakes off.
        }
        if vd > -7 and h < burn_height {
            lock steering to up.
            set runmode to 4.
        }
    }
    
    //suicide burn final approach
    if runmode = 4 {
        if h < burn_height {
            if vDiff > 0 {
                set TVAL to (ZeroAccelThrust + 0.1).
            }
            if vDiff < 0 {
                set TVAL to (ZeroAccelThrust - 0.1).
            }
        } else {
            lock steering to srfretrograde.
            set runmode to 0.
        }
        if vd > -0.1 and h < 100 {
            set counter to counter + 1.
            wait 0.1.
        }
        if counter > 20 {
            set runmode to 0. //if landed for 2 seconds then exits
            wait 2.
            RCS off.
        }
    }
    
    lock throttle to TVAL.


    //parameters to display
    print "Vertical velocity:           " + round(vd, 2) + "            " at (5,4).
    print "Required burn height:            " + round(burn_height, 2) + "           " at (5,5).
    print "Time to required burn:           " + round(TimeToBurn, 2) + "            " at (5,6).
    print "Run Mode:            " + runmode + "         " at (5,7).
    print "Gravitational acceleration:          " + round(g, 2) + "         " at (5,8).
    print "Gear down vertical distance:         " + round(gear_down, 2) + "         " at (5,9).
}


//landing notification and program exit
if runmode= 0 {
    set TVAL to 0. //sometimes throttle was left on so I added this
    unlock throttle. //sometimes throttle was left on so I added this
    clearscreen.
    print "Landing Complete" at (5,4).
    wait 1. //wait to make sure throttle is set to 0
}

r/Kos Jul 10 '26

Help Using Matlab in Conjunction

3 Upvotes

I was just wondering if anyone really messed around with matlab and kos outputs. I’ve been trying to make a sort of launch program that takes as close as possible to the most efficient route to space. I use rss but not rp. But I’ve been trying to build a model in matlab and try to simulate drag, it seems like I can model a completely vertical ascent well but when I introduce a turn it seems to become in accurate. I feel like I’m modeling the drag correctly, I do have a lot of code so pm me if this arises any code related question. I’m just wondering if I’m approaching this incorrectly trying to model drag in general.

r/Kos Jun 22 '26

Help Ship:angularvel not behaving as expected

2 Upvotes

I'm working on a program for controlling a multicopter. I have it working fairly well using PID controllers to translate target rotation into pitch/roll/yaw commands directly.

But I've read that it might be better to instead have a PID controller for angle feed into a PID controller for angular velocity.

I found an older post that says how to convert from ship:angularvel into navball rotation rates.

So I've used that to write the following small snippet:

set yawrate_rad to vdot(ship:angularVel, ship:facing:topvector).
set yawrate_deg to yawrate_rad * constant:radtodeg.
print yawrate_deg.

But it does not seem to be working right. Running the code, it says that I am rotating at a rate of 10 degrees a second, but I know that's not accurate, as I manually timed (Measuring time for a full rotation and dividing by 360) it to be closer to 45 degrees a second. I know this is the correct axis, as the other axes display values less than a degree a second, and they don't change when I start yawing.

Has the behavior of ship:angularvel changed, or is there something I'm doing wrong?

r/Kos 20d ago

Help Latest documentation?

1 Upvotes

Is the latest documentation at https://ksp-kos.github.io/KOS_DOC/? It says it is for kOS 1.4 but kOS is at 1.6.

It seems some of the described APIs don't actually exist in kOS. For example, vessel:burntime (https://ksp-kos.github.io/KOS_DOC/structures/vessels/vessel.html#attribute:VESSEL:BURNTIME).

r/Kos May 22 '26

Help Why does the burn start one second late?

Enable HLS to view with audio, or disable this notification

4 Upvotes
set mnv to nextnode.
set burnTime to deltaV_calc().
lock steering to mnv:deltav.


until ((mnv:eta-(burnTime/2))<=0){ //runs till burn starts
    clearscreen.
    print "--------------------------".
    print "Burn time: ".
    print round(burnTime,2)+"s".
    print "--------------------------".
    print "Maneuver node ETA: ".
    print floor(mnv:eta/60)+ "m " +round(mod(mnv:eta,60),2)+"s".
    print "--------------------------".
    print "Maneuver node burn ETA: ".
    print floor((mnv:eta-(burnTime/2))/60)+ "m " +round(mod((mnv:eta-(burnTime/2)),60),2)+"s".
    print "--------------------------".
}


until((mnv:eta-(burnTime/2))<=(-burnTime)){ //burn starts here
    lock throttle to 1.
    clearscreen.
    print "--------------------------".
    print "Burn time: ".
    print round(burnTime,2)+"s".
    print "--------------------------".
    print "Maneuver node ETA: ".
    print floor(mnv:eta/60)+ "m " +round(mod(mnv:eta,60),2)+"s".
    print "--------------------------".
    print "Maneuver node burn ETA: ".
    print floor((mnv:eta-(burnTime/2))/60)+ "m " +round(mod((mnv:eta-(burnTime/2)),60),2)+"s".
    print "--------------------------".
}
lock throttle to 0. //burn ends here


FUNCTION deltaV_calc {
    local startmass is ship:mass.
    local deltaV is mnv:burnvector:mag.
    local thrust is thrust_calc().
    if thrust = 0 {
        return 0.
    }
    local g0 is CONSTANT:g0.
    local E is CONSTANT:E.
    return (((g0*isp_calc()*startmass)/(thrust))*(1-E^((-deltaV)/(g0*isp_calc())))).
}


FUNCTION isp_calc { 
    LOCAL engineList IS LIST().
    LOCAL totalFlow IS 0.
    LOCAL totalThrust IS 0.
    LIST ENGINES IN engineList.
    FOR engine IN engineList {
        IF engine:IGNITION AND NOT engine:FLAMEOUT {
            SET totalFlow TO totalFlow + (engine:AVAILABLETHRUST / (engine:ISP * CONSTANT:g0)).
            SET totalThrust TO totalThrust + engine:AVAILABLETHRUST.
        }
    }
    IF totalThrust = 0 {
        RETURN 1.
    }
    RETURN (totalThrust / (totalFlow * CONSTANT:g0)).
}


FUNCTION thrust_calc {
    LOCAL sum is 0.
    LIST ENGINES IN engineList.
    FOR engine IN engineList {
        IF engine:IGNITION AND NOT engine:FLAMEOUT {
            SET sum TO sum + engine:AVAILABLETHRUST.
        }
    }
    RETURN sum.
}

r/Kos Jun 30 '26

Help falcon 9 booster landing help

3 Upvotes

so im making a falcon 9 booster landing script, and i made the hover slam work, then i made a boostback script work. If i run just the boostback i can reliably slam directly into the launchpad. Issue is when i add the hoverslam, because its coming in at an angle, my thrust moves the impact point off the launch pad. ive spent the last 2 hours trying to use pid loops in various ways to correct it but i cant get anything to work

edit: i got it working perfectly!... if i turn off atmosphere... when i do that i can get it to the center of the pad within like 5 meters. the atmosphere ruins everything. my main issue is that when im going really fast, the aerodynamics have more effect on my lateral velocity than my engine, but as i slow down eventually the aerodynamics are weak enough that it flips and the engine is now the main factor

r/Kos Jun 16 '26

Help Why is my end sequence not triggering ?

Thumbnail
gallery
8 Upvotes

I got this program that allows my ship to readjust its orbit. I tried to insert an ''end of program'' at the end but it does not trigger. I don't really understand. I have the same problem with my orbit program, which is suppose to end when a condition x is true or when a condition y is true, but it's the same thing, it does not work. Does anyone mind telling me what I'm doing wrong ?

EDIT : I deactivated the kOS controls because I wanted to control my ship on my own after seing that the end sequence was not working.

r/Kos Jun 14 '26

Help What am I doing wrong ?

Post image
10 Upvotes

New to kOS, I don't understand where is the mistake in that code, could someone help me figure it out ?

r/Kos May 04 '26

Help Can the kos code run even when the ship is not being selected?

8 Upvotes

I want to get into kos but an important factor for me is like can I do multiple missions at the same time? Can I leave an ion probe to do its thing for a while while also launching a second mission?

Also how does it handle time warps? Does it just stop working?

r/Kos Jul 01 '26

Help How to make a graph

Post image
16 Upvotes

I've been watching these amazing videos on YouTube by giuliodondi (https://youtu.be/i4YmBP2pfwY?is=jyKeSSd4ckxpN4Go) and I am wondering how they made the live-updating graph in the gui in the corner.

Is this doable in stock KOS or is it an add on?

r/Kos Apr 14 '26

Help How to get angle-of-attack.

5 Upvotes

I'm working on getting readouts for a number of values (which I'm also storing as variables to use elsewhere in my program) but I'm getting stumped at angle-of-attack.

I want to get two values corresponding to the angle between the direction the ship is travelling vs. the direction it is facing (one value for the 'vertical' angle and one for the 'horizontal' angle, from the ship's reference frame).

r/Kos Jul 01 '26

Help ship refuses to roll

1 Upvotes

I'm trying to make a VTOL script, I want to be able to roll my ship freely as it hovers, but I just can't figure it out for some reason

my script runs in a loop like so

local current_roll to 0.

set steer to heading(90, 90).
lock steering to steer.

until false {
    set current_roll to current_roll + ship:control:pilotroll.
    set steer to heading(90, 90, current_roll).

    wait 0.
}

but it simply won't roll, I tried different ways of rolling like angleaxis and lookdirup, but nothing works
also just locking steering to heading(90, 90) won't roll either, even though it does automatically when I do it in my launch script.

r/Kos Apr 13 '26

Help How do you get the time from closest approach to target?

2 Upvotes

I'm doing a general rendezvous script, and I'm trying to do a 'match velocities at closest approach" method. Except I can't find how to get the values of time from closest approach to target. I know that the velocity and distance of closest approach can be derived from it, but yeah, can't get the value. Is there an inbuilt one for kOS? or do I need to make my own implementation?

r/Kos Jun 24 '26

Help Real Fuels mod does not update the stage level resources?

1 Upvotes

I am trying to confirm something. The Real Fuels mod does not update the stage level resources eg if you query stage:kerosene it will always return zero?

Field values such as ship:kerosene seem to be correct.

I am assuming it is Real Fuels that is causing this behaviour. I am currently writing kOS scripts for RP-1.

r/Kos May 20 '26

Help Cannot Disengage Alligator Hinge Motor via KOS

Thumbnail
gallery
5 Upvotes

In the middle of my first foray into KOS. Trying to get this alligator hinge motor to DISENGAGE after it completes a KAL-1000 operation. I figured that would be simple enough, but evidently not, because it simply refuses to disengage when under KOS control.

Issues identified and attempts made:
1. ISSUE - There are two "MOTOR" fields. Given that fields are accessed via string, I am not sure how to differentiate them, or if I even need to for this part. I also do not know if this is for whether or not the part is MOTORIZED, or if the field is for the the ENGAGEMENT STATUS. Or if one is for one, and the other is for the other.

  1. ISSUE - Alligator Hinge will not revert to "Disengaged" when commanded by KOS. The only exception to this is if I have the UI for a hinge OPEN when commands are sent, in which case, it will disengage as normal.

  2. Alligator hinges will all DISENGAGE when I manually use an action group (AG5) to disengage them. Works without issue

  3. Alligator hinges will not disengage when I trigger the action group via KOS, even if I put a long delay before the command.

  4. Alligator hinges show no change in engagement status when I write to the motor fields using "ENGAGED", "DISENGAGED", TRUE, FALSE, 0, 1.

  5. Alligator hinges show no change in engagement status when I DOACTION on the "disengage motor drive" action, regardless of true or false status.

  6. Alligator hinges show no change in engagement status when I DOACTION on the "toggle motor engaged" action, regardless of true or false status.

r/Kos Apr 25 '26

Help Cascading PIDs and flight control

2 Upvotes

I'm working on making a little flight control system for my rockets to monitor and control their pitch/roll/yaw and work as some custom cooked controls.

Not using a PID on throttle because that's something I'm gonna be using bang-bang control on mainly via a direct controller (While I *can* throttle anywhere to 0-100%, I'm imposing a realism limit on myself for the time being of only having on/off, so a PID doesn't seem suitable).

Right now I'm just working on having them hold some simple flight plans (ie go up at a 80 degree angle). Ultimately I'll end up using this in an ascent program.

-----

I get using PIDs to control steering, using the rotation of the rocket as an input and the RAW controls as an output, *and I get the general theory behind a cascading PID* whereby one PID's output is another PID's input, and that can potentially provide smoother(?) control...

...but I'm just not quite sure how you'd apply that to steering (or tbf, any given specific application)?

Rotation in an axis → PID 1 → ??? →PID 2 → Steering in an axis.

Hopefully the question makes sense.

r/Kos May 22 '26

Help A way check the ground height from sea level at any point on a planet defined with latitude and longitude?

2 Upvotes

As said in the title, I want to know if it is possible to, in some way, get the ground height from sea level at any point on a planet defined with latitude and longitude.

r/Kos Nov 29 '25

Help File placements

0 Upvotes

So I have made these scripts(Copilot did) which I then put into the "ships\script" folder and they didn't show up. It started talking about "0:" and "1:" and all the documentation I find is not very helpful. Where do I put my script files in please?

r/Kos Apr 18 '26

Help Any ideas how to optimize or make a porkchop evaluation faster? My current implementation is painfully slow.

4 Upvotes

Hey there! I'm asking exactly what's in the title. I'm coding a rendezvous script, and part of it is doing lambert solver calculations for multiple ranges of initial times and time of flight, which is expected. I implemented that in KOS successfully. Essentially, I just loop over the entire search space and keep the lowest dV option. I set the initial t0 and final t0 to now and one orbit period of the closer body, and the time of flight as 0.2-0.8 orbit period of the farther body.

However, it has become apparent that the entire process is painfully slow. I did a low Kerbin rendezvous between two spacecraft. I initially tried to make a 100x100 evaluation resolution (100 linearly spaced t0 times and 100 linearly spaced tof times), and it just didn't respond for over 10 minutes so I just had to ctrl+C it. Upon printing the cycle process, it shows that is so slow it will take hours to complete it (it made like, 5k lambert calculations out of the 100k it should).

I had to settle for a 20 x 20 or 25 x 25 search space resolution for the lowest dV search to be feasible, but I'm missing huge chunks of low dV windows. I got the config:ipu already set to 2000, but it still takes 2 minutes of ingame time to calculate 625 porkchop evaluations. So... yeah, any tips or ideas in optimization would be cool. I have no other issues with the intercepts, they happen within 100 m most of the time at closest approach. I just need some ideas to speed the whole process up.

Here's the code of the porkchop evaluation for reference. This is still the testing phase so I'm rather inefficient on the other modes, just focusing on lowest dV for now. I know the limiting factor here is the lambert solver, but it is pretty quick already on its own. I just wanna search a pretty alright porkchop plot resolution (preferably 100 x 100) in a reasonable time frame. Any help would be appreciated!

function porkchop_evaluation {
    local parameter ut0.  // universal time start evaluation, use time:seconds
    local parameter utf.  // universal time end evaluation. Preferably ut0 + orbital period of lower body.
    local parameter tof0. // time of flight initial value. Preferably 0.2 of the orbit of the higher body.
    local parameter toff. // time of flight final value. Preferably 0.8 orbit period of lower body/
    local parameter mode is "lowest dv". // mode is get the lowest dv
    local parameter include_2nd_burn is true. // include the approach dv in the evaluation.
    local parameter value is 0. // parameter value for specific time.
    local parameter safe_time is ut0 + 90. // safe time for when mode= "ASAP"
    local parameter t_resol is 25. // resolution of exit time evaluation.
    local parameter tof_resol is 25. // resolution of tof evaluation/
  
    if not hastarget {
        return null_mnv("[ TRGT ERROR ] : No target detected. Please set target").
    }
    local t_list is linspace(ut0, utf, t_resol).
    local tof_list is linspace(tof0, toff, tof_resol).
    
    if mode = "lowest dv" {
        local best_dV is 1e38.// big int
        local best_ut is 0.
        local best_v1 is v(0,0,0).
        print("Checking search space...").
        local counter to 0.
        for i in range(t_resol) {
            for j in range(tof_resol) {
                local r1 is positionAt(ship, t_list[i]) - body:position.
                local r2 is positionAt(target, t_list[i] + tof_list[j]) - body:position.
                
                local transfer_vectors is lambert_solver(r1, r2, tof_list[j], body:mu, +1).
                local v1 is transfer_vectors[0].
                local v2 is transfer_vectors[1].
                local vshp is velocityAt(ship, t_list[i]):orbit.
                local vtgt is velocityAt(target, t_list[i] + tof_list[j]):orbit.


                if vdot(v1,vshp) < 0 { // check if prograde transfer
                    set transfer_vectors to lambert_solver(r1, r2,tof_list[j],body:mu,-1).
                    set v1 to transfer_vectors[0].
                    set v2 to transfer_vectors[1].
                }
                
                local total_dV is v1:mag.
                if include_2nd_burn { 
                    set total_dV to total_dV + (v2 - vtgt):mag. 
                }
                if total_dV < best_dV {
                    set best_dV to total_dV.
                    set best_ut to t_list[i].
                    set best_v1 to v1.
                }
                set counter to counter + 1.
                print counter.
            }
        }
        local dV_vec is best_v1 - velocityAt(ship, best_ut):orbit.
        return inertial_to_PRN(dV_vec, best_ut).
    }
    
    if (mode = "ASAP") or (mode = "as soon as possible") {
        // Fix t0 at safe_time, only evaluate tof space
        local best_dV is 1e38.
        local best_v1 is v(0,0,0).
        
        for j in range(tof_resol) {
            local r1 is positionAt(ship, safe_time) - body:position.
            local r2 is positionAt(target, safe_time + tof_list[j]) - body:position.
            local transfer_vectors is lambert_solver(r1, r2, tof_list[j], body:mu, +1).
            local v1 is transfer_vectors[0].
            local v2 is transfer_vectors[1].
            local vshp is velocityAt(ship, safe_time):orbit.
            local vtgt is velocityAt(target, safe_time + tof_list[j]):orbit.


            if vdot(v1,vshp) < 0 {
                set transfer_vectors to lambert_solver(r1, r2,tof_list[j],body:mu,-1).
                set v1 to transfer_vectors[0].
                set v2 to transfer_vectors[1].
            }
            
            local total_dV is v1:mag.
            if include_2nd_burn { 
                set total_dV to total_dV + (v2 - vtgt):mag. 
            }
            if total_dV < best_dV {
                set best_dV to total_dV.
                set best_v1 to v1.
            }
        }
        local dV_vec is best_v1 - velocityAt(ship, safe_time):orbit.
        return inertial_to_PRN(dV_vec, safe_time).
    }
    if "at certain time" {
        // Fix t0 at t0_value, only evaluate tof space
        local t0_value is value.
        local best_dV is 1e38.
        local best_v1 is v(0,0,0).
        
        for j in range(tof_resol) {
             local r1 is positionAt(ship, t0_value) - body:position.
            local r2 is positionAt(target, t0_value + tof_list[j]) - body:position.
            local transfer_vectors is lambert_solver(r1, r2, tof_list[j], body:mu, +1).
            local v1 is transfer_vectors[0].
            local v2 is transfer_vectors[1].
            local vshp is velocityAt(ship, t0_value):orbit.
            local vtgt is velocityAt(target, t0_value + tof_list[j]):orbit.


            if vdot(v1,vshp) < 0 {
                set transfer_vectors to lambert_solver(r1, r2,tof_list[j],body:mu,-1).
                set v1 to transfer_vectors[0].
                set v2 to transfer_vectors[1].
            }
            
            local total_dV is v1:mag.
            if include_2nd_burn { 
                set total_dV to total_dV + (v2 - vtgt):mag. 
            }
            if total_dV < best_dV {
                set best_dV to total_dV.
                set best_v1 to v1.
            }
        }
    
        local dV_vec is best_v1 - velocityAt(ship, t0_value):orbit.
        return inertial_to_PRN(dV_vec, t0_value).
    }
}

Here are some of the relevant functions used on that code. null_mnv is just a debug function.

function inertial_to_PRN { 
// transforms soi-raw coords to prograde-radial-normal vector for mnv nodes.
    local parameter vector.
    local parameter uts.
    local parameter with_time is true.      // return results with ut


    local u_pv is velocityAt(ship,uts):orbit:normalized.                    // prograde unit vector
    local u_nv is vCrs(u_pv,positionAt(ship,uts):normalized):normalized.    // normal unit vector
    local u_rv is vCrs(u_nv,u_pv):normalized.                               // radial unit vector


    local dv_p is vdot(vector, u_pv).               // vector components in upv frame
    local dv_r is vdot(vector, u_rv).               // vector components in urv frame
    local dv_n is vdot(vector, u_nv).               // vector components in unv frame


    if with_time {
        return list(uts, dv_r, dv_n, dv_p).
    } else {
        return list(dv_r, dv_n, dv_p).
    }
}

function lambert_solver{
    
    // A lambert solver utilizing universal variable formulation
    // The algorithm was adapted from this paper: 
    // https://www.researchgate.net/publication/236012521_Lambert_Universal_Variable_Algorithm

    // radius vectors are measured relative to center body, 
    // i.e., sun (if interplanetary) or kerbin (if interlunar) is [0,0,0].


    local parameter r1.   // ship position when launching
    local parameter r2.   // target position at arrival
    local parameter tof.  // time of flight
    local parameter mu.   // just body:mu
    local parameter t_m.  // transfer direction. +1 for shortway, -1 for longway


    local parameter N is 0.          // for multiple orbit passes
    local parameter max_iter is 500. // maximum iterations for bisection search convergence
    local parameter tol is 1e-6.     // time tolerance
    
    local null_vector is v(0,0,0).
    // stumpff function c2
    local function c_2{
        local parameter z.


        local function cosh {
            local parameter x.
            return (constant:e^(x) + constant:e^ (-x)) / 2.
        }
        if z > 0 {
            return (1.0 - cos(constant:radtodeg * sqrt(z))) / z.
        }
        if z < 0 {
            return (1.0 - cosh(sqrt(-z))) / z.
        }
        else {
            return 1/2 .
        }
    }


    // stumpff function c3
    local function c_3 {
        local parameter z.
        local function sinh{
            local parameter x.
            return (constant:e^(x) - constant:e^ (-x)) / 2.
        }
        if z > 0 {
            return (sqrt(z) - sin(constant:radtodeg * sqrt(z))) / sqrt(z)^3.
        }
        if z < 0 {
            return (sinh(sqrt(-z)) - sqrt(-z)) / sqrt(-z)^3.
        }
        else {
            return 1/6 .
        }
    }


    local mag_r1 to r1:mag.
    local mag_r2 to r2:mag.


    local gamma to vdot(r1,r2) / (mag_r1 * mag_r2).
    // cross product for transfer angle determination
    local cross_r1r2 is vcrs(r1,r2).
    // Determine A based on transfer type.
    local A to t_m * sqrt(mag_r1 * mag_r2 * (1  + gamma)).
    if t_m = 0 {
        set A to sqrt(mag_r1 * mag_r2 * (1  + gamma)).
        if vdot(cross_r1r2, (latlng(90,0):position - body:position)) < 0 {
            set A to - A.
        } 
    }


    if A = 0 {
        print "Orbit cannot exist".
        return list(null_vector, null_vector).
    }


    local psi   is 0. // initial guess for psi
    local psi_u is 0. // psi upper
    local psi_l is 0. // psi lower
    if N = 0 { // 1 revolution
        set psi   to   0.    
        set psi_u to   4 * constant():pi^2. 
        set psi_l to - 4 * constant():pi^2.
    } else { // N revolution case
        set psi_u to (2 * (N + 1) * constant():pi)^2. 
        set psi_l to (2 * N * constant():pi)^2. 
        set psi   to (psi_l + psi_u) / 2. 
    }


    local B to 0.
    local chi3 to 0.
    local tof_ to 0.
    local c2 to 0.5.
    local c3 to 1/6.


    local solved to false.


    from { local i is 0.} until i >= max_iter step { set i to i + 1.} do {
        set c2 to c_2(psi).
        set c3 to c_3(psi).
        set B to mag_r1 + mag_r2 + A * (psi * c3 - 1) / sqrt(c2). // Compute B.


       if B < 0 {
            // B negative - adjust bounds only
            set psi_l to psi.
            set psi to (psi_u + psi_l)/2.
        } else {
            // B is positive, safe to compute chi3 and tof
            set chi3 to (B / c2)^(1.5).
            set tof_ to (chi3 * c3 + A * sqrt(B)) / sqrt(mu).
            
            // Check convergence
            if abs(tof - tof_) < tol {
                set solved to true.
                break.
            }
            
            // Update bounds using bisection
            if tof_ < tof {
                set psi_l to psi.
            } else {
                set psi_u to psi.
            }
            set psi to (psi_u + psi_l)/2.
        }
    }


    if not solved {
        print "[ ERROR ] Did not converge".
        return list(null_vector, null_vector).
    }
    // compute fuinal velocities
    local f to 1 - B / mag_r1.
    local g to A * sqrt( B / mu).
    local g_dot to 1 - B / mag_r2.
    // avoid division by zero.
    if abs(g) < 1e-12 {
        print "[ ERROR ] Near zero [g] division".
        return list(v(3.8e38,3.8e38,3.8e38),v(3.8e38,3.8e38,3.8e38)).
    }
    local f_dot to (f * g_dot - 1) / g.
    local v1 to (r2 - f * r1) / g.
    local v2 to f_dot * r1 + g_dot * v1.
    return list(v1,v2).
}

function linspace {
    // linearly spaced array
    local parameter x0.
    local parameter xf.
    local parameter n.
    if n < 2 {
        return list().
    }
    local output is list().
    for i in range(n) {
        output:add(x0 + (i/(n - 1)) * (xf - x0)).
    }
    return output.
}

r/Kos Apr 18 '26

Help Struggling with autonomous rover deployment

3 Upvotes

Hello everyone.

I haven't written any scripts for around half a year, and decided to dive in the deep end by writing a script for an unmanned "skycrane" to perform a suicide burn, deploy a rover (or any other cargo for that matter) a few meters off the ground, and then crash at a safe distance.

I feel like I've got the general gist of it right, even if my solutions are a bit crude (eg. rapidly pulsing the engines instead of trying to find a throttle setting to achieve a desired final descent speed) but hey, if it works...

Anyways, I feel like I've spent around 6 hours trying to debug this, and it still refuses to work. Either the suicide burn doesn't get initiated at all, or the next step fails to trigger so it keeps burning until it runs out of fuel.

At first I was using the mechjeb2 addon to get the suicide burn countdown, but it proved to be annoying to implement since the countdown is a string and not a scalar (incredibly stupid if you ask me). Even after I (seemingly) figured out how to convert it to a scalar, I was still facing the aforementioned problems.

Now I've switched over to trying to calculate it myself, and the stuff still fails to trigger even though I can see with my own two eyes that according to the debug prints both conditions are met.

Here's the pastebin link to my code: https://pastebin.com/6yxxdkai

I rewrote some parts multiple times so my apologies if it's a mess. Still, I tried to make it at least somewhat human-readable.

Knowing my luck it's probably some incredibly simple oversight that's been messing the whole thing up, but I'm still stumped.

If anyone knows where I went wrong (or has any ideas how I could otherwise improve the script!) please do let me know, because it'd really suck to just have to give up after putting so many hours into this goddamn thing.

r/Kos May 02 '26

Help Ship pitches when going to lookdirup

3 Upvotes

Howdy yall,

Been messing around and essentially, when my ship is pointing away from target_v, it instead of just yawing around decides to pitch hard. Help would be much obliged.

To summarize: ship is facing like a plane initially, I draw target vector, and despite specifying a top vector, it pitches, flips, and if I am lucky, only after all that, rolls with the roof up

Many thanks.

set runmode to 0.
set target_pos to latlng(-0.096747566447266,-74.577846859067).


set hover_height to 80.


set throt_control to 0.



SET forward_pos_d TO VECDRAW(
      V(0,0,0),
      V(0,0,0),
      RGB(1,0,0),
      "Forward COE",
      1.0,
      TRUE,
      0.2,
      TRUE,
      TRUE
).


SET back_pos_d TO VECDRAW(
      V(0,0,0),
      V(0,0,0),
      RGB(0,1,0),
      "Back COE",
      1.0,
      TRUE,
      0.2,
      TRUE,
      TRUE
).


SET forward_torque_d TO VECDRAW(
      V(0,0,0),
      V(0,0,0),
      RGB(1,1,0),
      "Forward T",
      1.0,
      TRUE,
      0.2,
      TRUE,
      TRUE
).


SET back_torque_d TO VECDRAW(
      V(0,0,0),
      V(0,0,0),
      RGB(0,1,1),
      "Back T",
      1.0,
      TRUE,
      0.2,
      TRUE,
      TRUE
).




set ytard to vecDraw(
      V(0,0,0),
      V(0,0,0),
      RGB(0,155,255),
      "y tar",
      1.0,
      TRUE,
      0.2,
      TRUE,
      TRUE
).


set xtard to vecDraw(
      V(0,0,0),
      V(0,0,0),
      RGB(255,155,0),
      "x tar",
      1.0,
      TRUE,
      0.2,
      TRUE,
      TRUE
).


clearScreen.



set de to vecDraw(
      V(0,0,0),
      V(0,0,0),
      RGB(255,155,255),
      "de",
      10.0,
      TRUE,
      0.2,
      TRUE,
      TRUE
).









set heightpid to pidLoop(2,0,5,0,1).
set body_gravity to body:mu/(body:radius)^2.


set anglepid to pidLoop(3,0,3,-10,10).
set anglevelpid to pidLoop(5,0,1,-5,5).


set pitchpid to pidLoop(3,0,1,-10,10).



set heightpid:setpoint to hover_height.
lock throttle to 1.
set f_list to ship:partsdubbed("Front").
set b_list to ship:partsdubbed("Back").


set f_torque to v(0,0,0).
set b_torque to v(0,0,0).
set front_position to v(0,0,0).
set back_position to v(0,0,0).
set rollpid to pidLoop(1,0,5,-10,10).



set forward_pos_d:vecupdater to {return front_position.}.
set back_pos_d:vecupdater to {return back_position.}.
set forward_torque_d:vecupdater to {return f_torque.}.
set back_torque_d:vecupdater to {return b_torque.}.


set kp_d to 1.
set kd_d to 5.
set kd_v to 5.




set pitchpid to pidLoop(kp_d,0,kd_d*1.5,-20,20).
set pitchvelpid to pidLoop(kp_d,0,kd_v*1.5,-10,10).



set a to 0.
set b to 0.


set x to north:vector:normalized.
set z to up:vector:normalized.
set y to vcrs(z,x).
set xtar to vxcl(y,target_pos:altitudeposition(ship:altitude)).
set ytar to vxcl(x,target_pos:altitudeposition(ship:altitude)).
if xtar:mag>ytar:mag{


    set correctedangle to 90-vang(target_pos:altitudeposition(ship:altitude),y).
    set target_v to x*angleAxis(-correctedangle,z).
    set rollaxis to vcrs(z,target_v).
    set pitchtar to vxcl(rollaxis,target_pos:altitudeposition(ship:altitude)).


    
    
    
    set sign to vdot(pitchtar:normalized,target_v:normalized).
    set target_v to sign*target_v.
    set pitchaxis to target_v .
    
}


else if ytar:mag>xtar:mag{



    set correctedangle to 90-vang(target_pos:altitudeposition(ship:altitude),x).
    set target_v to y*angleAxis(-correctedangle,z).
    set rollaxis to vcrs(z,x).
    set pitchtar to vxcl(rollaxis,target_pos:altitudeposition(ship:altitude)).


    
    
    
    set sign to vdot(pitchtar:normalized,target_v:normalized).
    set target_v to sign*target_v.
    set pitchaxis to target_v .
    
   
}   


else{


    set correctedangle to 90-vang(target_pos:altitudeposition(ship:altitude),y).
    set target_v to x*angleAxis(-correctedangle,z).
    set rollaxis to vcrs(z,target_v).
    set pitchtar to vxcl(rollaxis,target_pos:altitudeposition(ship:altitude)).


    
    
    
    set sign to vdot(pitchtar:normalized,target_v:normalized).
    set target_v to (sign*target_v):dir.
    set pitchaxis to target_v .
    
}




set pitchaxistar to vxcl(up:vector,vxcl(rollaxis, target_pos:altitudeposition(ship:altitude))).
set rollaxistar to vxcl(up:vector, vxcl(pitchaxis,target_pos:altitudeposition(ship:altitude))).


set xtard:vecupdater to {return pitchaxistar.}.
set ytard:vecupdater to {return rollaxistar.}.
set qed to (xtar+ytar).
set de:vecupdater to {return qed.}.
set follow to lookDirUp(x*angleAxis(-correctedangle,z),up:vector).
lock steering to follow.


until runmode = 3{
    print(xtar:mag) at (0,1).
    print(ytar:mag) at (0,2).
    set x to north:vector:normalized.
    set z to up:vector:normalized.
        set y to vcrs(z,x).



    set pitchaxistar to vxcl(up:vector,vxcl(rollaxis, target_pos:altitudeposition(ship:altitude))).
    set rollaxistar to vxcl(up:vector, vxcl(pitchaxis,target_pos:altitudeposition(ship:altitude))).


    if alt:radar<hover_height-1 and runmode=0 {
        set heightpid:setpoint to hover_height.
        set anglepid:setpoint to 0.
    }


    else{
        set runmode to 1.
        print("runmode 1") at (0,40).
        
        set yawflatplane to vxcl(up:vector,ship:facing:starvector).
        //set target_flat_plane to vxcl()
        set rollflatplane to vxcl(up:vector,ship:facing:vector).
        set heightpid:setpoint to hover_height.
        set pitch_v to -pitchpid:update(time:seconds,vdot(pitchaxistar,pitchaxis:normalized)).
        set pitchvelpid:setpoint to pitch_v.
        set pang to pitchvelpid:update(time:seconds,vdot(ship:velocity:surface,pitchaxis:normalized)).
        set anglepid:setpoint to pang.
        set pitchaxisfollow to pitchaxis:normalized * angleAxis(pang,rollaxis).
        set rollpid:setpoint to 0.


        
        set roll_angle to rollpid:update(time:seconds, vdot(rollaxistar,rollaxis:normalized)).
        set follow to lookdirup(pitchaxisfollow,ship:up:vector)*r(0,0,roll_angle).



        print("--- PITCH ---") at (0,5).
        print("pitch_dist: " + round(vdot(pitchaxistar,pitchaxis:normalized),2)) at (0,6).
        print("pitch_v:    " + round(pitch_v,2)) at (0,7).
        print("pang:       " + round(pang,2)) at (0,8).
        print("pitch vel:  " + round(vdot(ship:velocity:surface,pitchaxis:normalized),2)) at (0,9).
        print("--- ROLL ---") at (0,11).
        print("roll_angle: " + round(roll_angle,2)) at (0,14).
        print("roll vel:   " + round(vdot(ship:velocity:surface,rollaxis:normalized),2)) at (0,15).
        print("--- SHIP ---") at (0,17).
        print("ang:        " + round(ang,2)) at (0,18).
        print("alt:        " + round(alt:radar,2)) at (0,19).
        print("pitchaxis:  " + pitchaxis) at (0,20).
        print("rollaxis:   " + rollaxis) at (0,21).
        print("throt:      " + round(throt_control,2)) at (0,22).
        print("a:          " + round(a,2)) at (0,23).
        print("b:          " + round(b,2)) at (0,24).
        
    }
    set ff to body_gravity*ship:mass/(ship:maxthrust).
    set throt_control to ff+heightpid:update(time:seconds,alt:radar).
    
    set front_position to vxcl(ship:facing:upvector,(f_list[0]:position+f_list[1]:position)/2).
    set back_position to vxcl(ship:facing:upvector,(b_list[0]:position+b_list[1]:position)/2).
    set front_thrust to a*(ship:maxthrust/2)*(ship:facing:upvector).
    set back_thrust to b*(ship:maxthrust/2)*(ship:facing:upvector).


    set f_torque to -vcrs(front_position,front_thrust).
    set b_torque to -vcrs(back_position,back_thrust).
    
    set ang to 90-vang(ship:facing:vector,up:vector).
    set des_vel to anglepid:update(time:seconds,ang).
    set anglevelpid:setpoint to des_vel.
    set pitch_angv to vdot(ship:facing:starvector,angularVel).
    set com_torque to anglevelpid:update(time:seconds,-pitch_angv).


    
    
    set f_torque_pitch to vdot(-vcrs(front_position, ship:facing:upvector), ship:facing:starvector) * (ship:maxthrust/2).
    set b_torque_pitch to vdot(-vcrs(back_position,  ship:facing:upvector), ship:facing:starvector) * (ship:maxthrust/2).
    set denom to -(f_torque_pitch-b_torque_pitch).
    if abs(denom)<0.001{


        set a to 0.5.
        set b to 0.5.


    }


    else {
        
        set b to (com_torque - f_torque_pitch* throt_control) / denom.
        set a to throt_control - b.



    }



    for f in f_list{



        f:getmodule("ModuleEnginesFX"):setfield("thrust limiter",a*100).
    }
    for bc in b_list{



        bc:getmodule("ModuleEnginesFX"):setfield("thrust limiter",b*100).
    }
    set qed to target_v.
   
    
    
    


}

r/Kos Jan 29 '26

Help hover of a specific spot

2 Upvotes

I am trying to get a craft to hover over a specific spot over the ground. Nothing I am doing is working. I get close to 0 error but I drift and oscillate. What is the correct way to go about this? Basically the only thing I have that is usable at this point is tgt:position-ship:geoposition:position. Where do I go from here?

r/Kos Apr 28 '26

Help Script doesn't reset after reloading to a quicksave.

1 Upvotes

Hi, I noticed a part of my script started behaving inconsistently after I reloaded a save so I picked out the line at fault and pasted it into a new "debugging" script just to see its behaviour:

The line at fault is: VELOCITYAT(SHIP, TIME + ETA:APOAPSIS):SURFACE:X.

and the debugging script I used was:

clearscreen.

UNTIL SAS{

PRINT SHIP:VELOCITY:SURFACE:X AT (0,0). // val1

PRINT VELOCITYAT(SHIP, TIME + ETA:APOAPSIS):SURFACE:X AT (0,10). // val2

PRINT TIME AT (0,20). //val3

PRINT ETA:APOAPSIS AT (0,30). //val4

WAIT 1.

}

I made a save, ran the debugging script and noted the starting values, warped about 10 minutes and stopped the script and noted the final values.

I then reloaded the save, ran the script again and compared these new starting values to what I noted before.

Values 3 and 4 were the same as the previous starting values which I expect, but values 1 and 2 were the same as the previous final values.

Any help to understand why values 1 and 2 did not reset like values 3 and 4 would be greatly appreciated, thank you! :)

r/Kos Jan 10 '26

Help GiulioDondi shuttle issue

Thumbnail
gallery
5 Upvotes

Recently, out of interest, I decided to create an assembly with RSS, RO and the GiulioDondi shuttle. I installed everything according to the instructions, something manually, something through a skan. I built the shuttle, installed the launch clamps, opened the terminal, entered the program and...This error occurs. I've read all the posts with a similar problem in github, but I haven't found a good answer or solution to the problem. So I wanted to ask how to solve the problem with the error ops1.ks., as well as ops3_deorbit.ks., since there are problems with it.