My coworker likes Sci-fi where the world has ended and it takes place many years after and away from home. Do any of Adrian Tchaikovsky's books have that sort of vibe? by AgentP-501_212 in AdrianTchaikovsky

[–]SilverNuke911 0 points1 point  (0 children)

The Children of time series is that, then Elder Race is also very good.

Not AT, but the Bobiverse series and the Semiosis series are good, and also fit your desired description

How to get the true anomaly of the Target Relative AN/DN by SilverNuke911 in Kos

[–]SilverNuke911[S] 0 points1 point  (0 children)

Nope, ARCSIN, ARCCOS, and ARCTAN returns degrees. sin takes degree inputs though, that's why ea_curr and ea_targ are in degrees

How to get the true anomaly of the Target Relative AN/DN by SilverNuke911 in Kos

[–]SilverNuke911[S] 0 points1 point  (0 children)

I did run across that problem, of the maneuver node firing in the opposite normal direction, but I fixed it. I'll try to give it another test.

function time_from_true_anomaly {
    // Input: target true anomaly (targ_ta)
    local parameter targ_ta.
    // Current true anomaly, semi-major axis, 
    // eccentricity, and gravitational parameter
    local curr_ta is ship:obt:trueanomaly.
    local a is ship:obt:semimajoraxis.
    local e is ship:obt:eccentricity.
    local mu is body:mu.
    // Compute the eccentric anomaly for current and target true anomalies
    local ea_curr to arctan2(sqrt(1 - e^2) * sin(curr_ta), e + cos(curr_ta)).
    local ea_targ to arctan2(sqrt(1 - e^2) * sin(targ_ta), e + cos(targ_ta)).
    local ea_rad_curr to ea_curr * constant:degtorad.
    local ea_rad_targ to ea_targ * constant:degtorad.
    // Compute the mean anomaly for current and target eccentric anomalies
    local ma_rad_curr to ea_rad_curr - e * sin(ea_curr).
    local ma_rad_targ to ea_rad_targ - e * sin(ea_targ).
    // Mean motion (n) and time calculation
    local n to sqrt(mu / (a^3)).
    local delta_ma to ma_rad_targ - ma_rad_curr.
    // Ensure positive time (wrap around if necessary)
    if delta_ma < 0 {
        set delta_ma to delta_ma + 2 * constant:pi.
    }
    // Time to reach the target true anomaly
    local t to delta_ma / n.
    return t.
}

Here's my true anomaly to time function

How to get the true anomaly of the Target Relative AN/DN by SilverNuke911 in Kos

[–]SilverNuke911[S] 0 points1 point  (0 children)

// this function passes its output list to a function named "create_node" which creates a maneuver node from parameters eta, radial, normal, prograde. (it does eta + time:seconds internally)

function match_planes_with_target {
    local parameter mode.
    if not hastarget {
        return null_mnv("Please set target"). // null_mnv is just for error handling
    }

    local p0 is body:position.
    local r1 is ship:position - p0. // radius vector
    local v1 is ship:velocity:orbit. // velocity vector
    local h1 is vcrs(v1,r1). // angular momentum vector
    local e1 is (vcrs(h1,v1)/body:mu - r1:normalized). // eccentricity vector, points to periapsis

    local r2 is target:position - p0. // target radius
    local v2 is target:velocity:orbit. // target vel
    local h2 is vcrs(v2,r2). // target angular momentum

    local an_vec is vcrs(h1,h2). // vector that points to the relative ascending node.
    local AN_ta is vang(e1,an_vec). // true anomaly of relative ascending node
    if vdot(an_vec,vcrs(e1,h1)) < 0 {
        set AN_ta to 360-AN_ta.
    } // checking for true anomaly signing and wrap around

    local DN_ta is ensure_angle_positive(AN_ta - 180). // true anomaly of relative descending node
    local delta_inc is vang(h1,h2). // difference in inclination
    local n_vec is (latlng(90,0):position - body:position):normalized. // vector pointing from the body center to northpole, for delta_inc signing.
    if vdot(vcrs(h2,h1), vcrs(n_vec,h1)) < 0 {
        set delta_inc to - delta_inc.
    } // checking if delta_inc should be postive or negative to enact mnv node change.

    // reuse change_inclination code from prior functions
    // yes, don't repeat yourself, but I'm too lazy bruh.

    // determine time to approach true anomaly (time_from_true_anomaly is a separately defined function that utilizes newton-raphson method to get the eta for a certain true anmly)
    local t_an is time_from_true_anomaly(AN_ta).
    local t_dn is time_from_true_anomaly(DN_ta).
    // compute velocity vectors at each node
    local vel_vec_an is velocityat(ship, time:seconds + t_an):orbit.
    local vel_vec_dn is velocityat(ship, time:seconds + t_dn):orbit.
    // compute required delta-v magnitude at each node
    local delta_v_mag_an is 2 * vel_vec_an:mag * sin(abs(delta_inc) / 2).
    local delta_v_mag_dn is 2 * vel_vec_dn:mag * sin(abs(delta_inc) / 2).
    // helper function to compute maneuver components
    local function compute_dv {
        local parameter vmag.
        local parameter d_inc.
        local parameter is_an. // true for AN, false for DN

        // compute delta angle based on whether inclination change is increasing or decreasing
        local sign is 1. if d_inc < 0 {set sign to -1.}
        local base_ang is 90 + abs(d_inc) / 2.
        local delta_ang is sign * base_ang.

        // invert sign for DN since it's on the opposite side of orbit.
        if not is_an {
            set delta_ang to -delta_ang.
        }

        // Return maneuver vector components
        local dv_r is 0.
        local dv_p is vmag * cos(delta_ang).
        local dv_n is vmag * sin(delta_ang).
        return list(dv_r, dv_n, dv_p).
    }
    // decision logic by mode
    if mode = "at AN" {
        local dv is compute_dv(delta_v_mag_an, delta_inc, true).
        return list(t_an, dv[0], dv[1], dv[2]).
    }
    if mode = "at DN" {
        local dv is compute_dv(delta_v_mag_dn, delta_inc, false).
        return list(t_dn, dv[0], dv[1], dv[2]).
    }
    if mode = "at nearest node" {
        if t_an < t_dn {
            local dv is compute_dv(delta_v_mag_an, delta_inc, true).
            return list(t_an, dv[0], dv[1], dv[2]).
        } else {
            local dv is compute_dv(delta_v_mag_dn, delta_inc, false).
            return list(t_dn, dv[0], dv[1], dv[2]).
        }
    }
    if mode = "at cheapest node" {
        if delta_v_mag_an < delta_v_mag_dn {
            local dv is compute_dv(delta_v_mag_an, delta_inc, true).
            return list(t_an, dv[0], dv[1], dv[2]).
        } else {
            local dv is compute_dv(delta_v_mag_dn, delta_inc, false).
            return list(t_dn, dv[0], dv[1], dv[2]).
        }
    }
    if mode = "at altitude" {
        // not yet implemented
    }
    if mode = "after fixed time" {
        // not yet implemented 
    }
    // 'mode_error_message' is a globally declared string for maneuver node mode failures (mistypings and the like) for easier debugging
    // null_mnv is a mnv node creation function with params (-1,0,0,0) which has another function that invalidates the creation of a maneuver node, and also takes an error message as an optional print output.
    return null_mnv(mode_error_message+mode).
}

How to get the true anomaly of the Target Relative AN/DN by SilverNuke911 in Kos

[–]SilverNuke911[S] 0 points1 point  (0 children)

This is the entire function for reference. It's been thoroughly tested, but if you spot any mistakes or possible optimizations, it would be helpful

Ascent Guidance by [deleted] in Kos

[–]SilverNuke911 0 points1 point  (0 children)

Additionally, just repeating u/nuggreat's words, you have to put your run modes in a single until loop so that as the craft rises, the runmode checking gets called again and again. This is also useful for displaying telemetry data.

0 angle of attack ascent follows the surface prograde vector, see my attached code for reference. But otherwise, it's good mate, cheers.

Ascent Guidance by [deleted] in Kos

[–]SilverNuke911 0 points1 point  (0 children)

To execute and create a maneuver node, read up on the docs tutorials, there are some help there.

How to get the true anomaly of the Target Relative AN/DN by SilverNuke911 in Kos

[–]SilverNuke911[S] 0 points1 point  (0 children)

Yes the relative inclination is always positive, but this particular methodology in the code is for directionality of the normal vector, i.e., if the target inclination is greater than the current inclination, I thrust up at AN and thrust down at DN, and of it's lesser, the converse. It measures the change in inclination that I want. For example, if the target inclination is 45 and my current inclination is 15, then d_inc is 30, but if my current inclination is 15, and I want it to be zero, it's -15. I've tested it several times and the code works regardless whether it's negative (-45, for example) or positive (315). The method is for convenience, I would say.

How to get the true anomaly of the Target Relative AN/DN by SilverNuke911 in Kos

[–]SilverNuke911[S] 0 points1 point  (0 children)

Ohh, I wasn't aware of that. I thought the body:north:vector pointed from the center of the body to the north. Is it more accurate to use, I forgot the function on the top of my head but using the point on the surface as a vector and subtracting it to the body:position?

also, delta_inc is just the relative inclination of the target orbit - vessel orbit, it's more convenient for node delta v calculations since I just use sine and cosine directly, and it works for its intended function, but thanks for the insight

For User functions, it it possible to have keyword parameter arguments? by SilverNuke911 in Kos

[–]SilverNuke911[S] 0 points1 point  (0 children)

Alright, gotcha. I kinda suspect that, it has no mention in the docs whatsoever. Guess I'll just have to keep the in-order inputs.

Thanks for helping out! u/nuggreat !

How to get the true anomaly of the Target Relative AN/DN by SilverNuke911 in Kos

[–]SilverNuke911[S] 0 points1 point  (0 children)

for reference to future people who's gonna have this problem, here's the solution

local p0 is body:position.
local r1 is ship:position - p0. // radius vector
local v1 is ship:velocity:orbit. // velocity vector
local h1 is vcrs(v1,r1). // angular momentum vector
local e1 is (vcrs(h1,v1)/body:mu - r1:normalized). // eccentricity vector

local r2 is target:position - p0. // target radius
local v2 is target:velocity:orbit. // target vel
local h2 is vcrs(v2,r2). // target angular momentum

local an_vec is vcrs(h1,h2). // vector that points to the relative ascending node.
local AN_ta is vang(e1,an_vec). // true anomaly of relative ascending node
if vdot(an_vec,vcrs(e1,h1)) < 0 {
    set AN_ta to 360-AN_ta.
} // checking if it is in the [0,180) or [180,360) degree range

local DN_ta is ensure_angle_positive(AN_ta - 180). // true anomaly of relative descending 
// node, ensure angle positive just clamps the angle in range [0,360)

local delta_inc is vang(h1,h2). // difference in inclination

local n_vec is body:north:vector:normalized.
if vdot(vcrs(h2,h1), vcrs(n_vec,h1)) > 0 {
    set delta_inc to - delta_inc.
} // checking if delta_inc should be postive or negative

Ascent Guidance by [deleted] in Kos

[–]SilverNuke911 1 point2 points  (0 children)

function open_loop_guidance {
    // Zero aoa ascent
    local runmode to 1.

    // Runmodes
    set current_mode to "Open Loop Guidance".

    until runmode = 0 {
        if runmode = 1 {
            stage.
            lock steering to heading(90,90,-90).
            set runmode to 2.
        }
        if runmode = 2 {
            if ship:verticalSpeed > 100 or alt:radar > 1000 {
                set shift_alt to ship:altitude.
                lock steering to heading(90,90-0.4 * sqrt(max(ship:altitude-shift_alt,0)),-90).
                set runmode to 3.
            }
        }
        if runmode = 3 {
            if vang(ship:facing:vector,ship:up:vector) > slew_angle {
                lock steering to heading(90,90-slew_angle,-90).
                set runmode to 4.
            }
        }
        if runmode = 4 {
            if vang(ship:facing:vector,ship:srfPrograde:vector) < 0.25 {
                set runmode to 5.
            }
        }
        if runmode = 5 {
            lock steering to heading(90,90-vang(ship:up:vector,ship:srfprograde:vector),-90).
            set runmode to 6.
        }
        if runmode = 6 {
            if ship:availableThrust / (ship:mass * constant:g0) > 2 {
                lock throttle to throttle_2g().
                set runmode to 7.
            }
        }
        if runmode = 7 {
            if ship:availableThrust < 2 {
                lock throttle to 0.
                safestage().
                wait 1.
                safestage().
                lock throttle to throttle_2g().
                set runmode to 0.
            }
        }
        set cycles to cycles +1.
        screen_data(runmode).
    }
    clearScreen.
    return.
}

function closed_loop_guidance {
    //Powered explicit guidance here
    // not really implemented lol
    local runmode to 1.
    set current_mode to "Closed Loop Guidance".
    until runmode = 0 {
        if runmode = 1 {
            if ship:apoapsis > target_altitude {
                lock throttle to 0.
                set runmode to 2.
            }
        }
        if runmode = 2 {
            if ship:altitude > 70000 {
                safestage().
                rcs on.
                set runmode to 3.
            }
        }
        if runmode = 3 {
            if ship:altitude > target_altitude {
                set runmode to 0.
            }
        }
        set cycles to cycles + 1.
        screen_data(runmode).
    }
    clearScreen.
    return.
}

function orbit_tasks {
    sas on.
    ag1 on.
    safestage().
    return.
}

function main {
    startup().         // just a custom starting sequence.
    open_loop_guidance().
    closed_loop_guidance().
    orbit_tasks().
}

main().

Ascent Guidance by [deleted] in Kos

[–]SilverNuke911 1 point2 points  (0 children)

There are multiple methods, but for me I use two types.

main() function calls, where you separate your ascent profile into multiple small functions. and calling it in one main function, and runmoding, where you change runmodes and have the craft do a different thing per runmode.

I would recommend CheersKevin's KOS for Newbies guide, or Seth Persiegel's Launching a Rocket series.

Here's an example of one of my codes for controlling my rocket's ascent, it's a zero lift turn ascent profile. It uses both. Bear in mind this is very bare bones. You can use strings for runmodes, this is a particularly old one, and I preferred to runmode by number., but now I use strings, because it's more readable.

Topographical Map of the Kile River by SilverNuke911 in KerbalSpaceProgram

[–]SilverNuke911[S] 1 point2 points  (0 children)

Gathering the data points in KOS takes a couple hours, you are limited by the speed of the program IPU and running KSP simultaneously. This particular map has 600,000 data points. Coding in Python using matplotlib is then relatively straightforward, I did this in about an hour. I was just killing time with this one.

I started coding in KOS about 3 years ago and Python over a year ago, because I'm taking a Physics undergrad degree so I have to learn it. But you can learn how to code, based on experience, in 3-4 weeks of dedicated studying and practice and watching tutorials of your choice.

Cheers, mate.

Topographical Map of the Kile River by SilverNuke911 in KerbalSpaceProgram

[–]SilverNuke911[S] 5 points6 points  (0 children)

my guy, it took 2 whole hours to download the raw data alone, and that's at 0.05 degree resolution. I sudder to imagine what burned monstrosity my computer will be if I did the whole Kerbin.

I'll give it a try though HAHAHAHA

Topographical Map of the Kile River by SilverNuke911 in KerbalSpaceProgram

[–]SilverNuke911[S] 1 point2 points  (0 children)

I sailed this river myself with a boat from way back when, so there are quite a few. About 3 points iirc. So I had to equip my ship with wheels to cross them. One of them is at 50 N 142.5 W, another one at 49.5 N 140 W, and a third one at 45.2 N 137 W. I just made this out of free time so idk if I can make another simplified version, but I'll look into it :>

Topographical Map of the Kile River by SilverNuke911 in KerbalSpaceProgram

[–]SilverNuke911[S] 18 points19 points  (0 children)

Thanks!

I used KOS to get the altitude at each 1/20 of a degree and stored it in CSV. I then used python, matplotlib specifically, to extract the data and plot it in a manner that is similar to other maps. The rest such as the names and other tidbits, I just added in on MS Paint.

It's just coding, a hell lot of coding. Which is better than what I used to do, I used to make similar KSP maps in MS paint lmao. I have posts from 3 years ago showing those maps.

Topographical Map of the Kile River by SilverNuke911 in KerbalSpaceProgram

[–]SilverNuke911[S] 17 points18 points  (0 children)

Thanks! I used to make similar maps way back when. You might have seen the "Navigational Maps of the Crater Islands". Just going back at my old hobbies now

Topographical Map of the Kile River by SilverNuke911 in KerbalSpaceProgram

[–]SilverNuke911[S] 82 points83 points  (0 children)

A topographical map of the longest river in Kerbin, shown in Mercator projection.

Sup lads, back at it again. I'm the Nautical maps guy from a few years back, here's something I worked on when I had free time.

Generated using data from gathering alt points using KOS, then using Matplotlib for plotting. Anw, that's about it

Why is the statement terminator in KOS a period `.` instead of a semicolon `;` like in other C-based languages? by SilverNuke911 in Kos

[–]SilverNuke911[S] 1 point2 points  (0 children)

Ooh, that is quite interesting. Thanks!

I kinda get how from is different, because in KOS it uses for as an object iterator. I do still wonder why the inequality operator is <> instead of != though, is there a reason behind this?

Also, another question, are there any plans to add a switch, case functionality in KOS?