Jump to content

[It's Back!] Another Voyage Ares Mission, and A KSP'ers Crash Course in Realism Overhaul.


Nittany Tiger

Recommended Posts

Looks like the problem with the kOS cooked steering was having SAS on while commanding the roll, so I guess I need to redo the tuning without SAS now.

Two days of fighting a bad setting in kOS and never knowing it. :/

Edited by Nittany Tiger
Link to comment
Share on other sites

Update time.

Autopilot code is coming along, and after some trial and error, I have a gravity turn programmed in.  I found that an initial pitchover of 10 degrees seems to give me the best gravity turn.  I thought of finding the perfect pitch angle analytically, but it would mean solving this differential equation (provided I set it up properly):

Xb7P65y.png

This is the equation for the accelerations on the rocket on ascent.  I could probably solve in numerically, but I think it's a bit much for this project.  Maybe another day.

Anyway, the code so far.  There is a lot of junk commenting and temporary code commented out, but I'll clean that up in the final version:

//Saturn VB Autopilot program
//Ctrl + C to kill?

RUNPATH("AresLaunchDisplay.ks").

SET ddyn to 0.
SET dynzero to 0.

//If variables are lists, can I accees each element in loops below and make code more efficient?
SET Inboard to SHIP:PARTSTAGGED("F1AInboard")[0].
SET Outboard to SHIP:PARTSTAGGED("F1AOutboard1")[0].
SET SRB to SHIP:PARTSTAGGED("SRB1")[0].
SET MSIC to SHIP:PARTSTAGGED("MS-IC")[0].

CLEARSCREEN. //in case we need this

//Display event, throttle setting, F-1A thrust %, and SRB thrust %.
//Lock steering to a variable to make it less intensive to run?
LOCK STEERING to Autopilot.
LOCK Autopilot to "Kill".
LOCK THROTTLE to 1.0.

//Temp - steering debug - delete after use
//SET STEERINGMANAGER:SHOWSTEERINGSTATS to TRUE.
//SET STEERINGMANAGER:SHOWFACINGVECTORS to TRUE.
//SET STEERINGMANAGER:SHOWANGULARVECTORS to TRUE.
STAGE. //F-1A ignition

//Ultimate goal of steering program is to set rocket into pre-programmed circular orbit of 200 km - 250 km.
//Pitch by x degrees, then follow prograde until rocket reaches certain altitude.
//Finally, manage pitch to put Ares in circular orbit.
//In launches using manual steering, Ares ends gravity turn between SRB sep and MS-IC burnout.

//Adjust heading to meet propulsion stack inclination (or desired inclination).  Could have this able to be set as input prior to launch.

//At v(sfc) = 50 m/s, pitch over a bit to initiate gravity turn.
//then hold prograde for gravity turn. (angle between v and a zero.)

//Pitch and roll manuever.  Correct initial pitch is trial and error right now.
//Could the gravity turn be better programmed as a diff eq (predictive equation)?

//Print that gravity turn is in progress - Integrate with LaunchDisplay function?

WHEN SHIP:VELOCITY:SURFACE:MAG >= 50 THEN {
  //Pitch then roll for inclination (90 degrees for now). - smooth out move to pitch?
  LOCK Autopilot to HEADING(90,80). //175 km AP at SRB sep.  SRB sep at 70 km. -  Last setting, 78 degrees pitch, then 83
  //Follow prograde next.
  WHEN SHIP:FACING:VECTOR:NORMALIZED:Z - SHIP:VELOCITY:SURFACE:NORMALIZED:Z <= 0 THEN {
   LOCK Autopilot to SHIP:VELOCITY:SURFACE. //SHIP:VELOCITY:SURFACE or SHIP:SRFPROGRADE?
   PRINT "Begin Gravity Turn" at (0,10).   
   //Start PID loop for hitting set apoapsis - lasts until SECO.
   //Output pitch (or yaw) based on set final apoapsis.
   WHEN SHIP:ALTITUDE > 75000 THEN {
     //Lock Autopilot to HEADING(90,0). //turns way too sharply, also readjusts heading
   }  
  }
}

//Countdown here?

UNTIL (Outboard:THRUST/Outboard:MAXTHRUST) > 0.88 {
  IF(Outboard:MAXTHRUST > 0) {  //Prevent NAN
    LaunchDisplay(0,2,Outboard:THRUST/Outboard:MAXTHRUST,0).
  }
  
  //WAIT 0.01.
}

STAGE.  //SRB ignition and liftoff
CLEARSCREEN.

//Maybe countdown and abort mode display.

//WAIT 0.01.

//Display loop could continue on with a PRESERVE command after throttleback?
UNTIL MISSIONTIME > 25 {
  IF(SRB:MAXTHRUST > 0 AND SRB:THRUST > 0) { //Prevent NAN
    //PRINT "Facing-vel srf Angle: " + VANG(SHIP:FACING:VECTOR, SHIP:VELOCITY:SURFACE) + "  " at (0,4).
	//PRINT "Facing Z - Vel Srf Z (Normalized): " + (SHIP:FACING:VECTOR:NORMALIZED:Z - SHIP:VELOCITY:SURFACE:NORMALIZED:Z) at (0,5).
	//PRINT "Facing-target Angle: " + VANG(SHIP:FACING:VECTOR, STEERINGMANAGER:TARGET:VECTOR) + "  " at (0,6).
    //PRINT "Facing - Target: " + (SHIP:FACING:VECTOR:Z - STEERINGMANAGER:TARGET:VECTOR:Z) + "  " at (0,7).
    //PRINT "Facing Z: " + SHIP:FACING:VECTOR:Z + "  "at (0,8).
    //PRINT "Vel Srf Z: " + SHIP:VELOCITY:SURFACE:Z + "  "at (0,9).
    LaunchDisplay(1,2,Outboard:THRUST/Outboard:MAXTHRUST,SRB:THRUST/SRB:MAXTHRUST).
  }
  //WAIT 0.01.
}

CLEARSCREEN.

LOCK THROTTLE to 0.01. //F-1A throttle to 60% for max Q

//check dyn pressure change
//if ddyn < -0.004kPa/0.01s or so, throttle to 85% (was -0.04kPa/0.1s)

UNTIL ddyn <= -0.004 {
  LaunchDisplay(2,0,Outboard:THRUST/Outboard:MAXTHRUST,SRB:Thrust/SRB:MAXTHRUST).
  SET ddyn TO (SHIP:Q*constant:ATMtokPa) - dynzero. //units are kPa <- can be lock statement
  SET dynzero TO (SHIP:Q*constant:ATMtokPa). //<- these can be LOCK statements
  WAIT 0.01. //change to 0.1? <- can remove this when using lock and dividing by time.
}

LOCK THROTTLE to 0.63. //F-1A throttle to 85%

CLEARSCREEN.

//4+Gs before SRB tail-off.

//Stage SRBs and throttle to 100% when SRB thrust < 10%
UNTIL SRB:THRUST/SRB:MAXTHRUST < .1 {
  LaunchDisplay(3,1,Outboard:THRUST/Outboard:MAXTHRUST,SRB:Thrust/SRB:MAXTHRUST).
  //WAIT 0.01.
}

STAGE. //SRB jettison

LOCK THROTTLE to 1.0. //F-1A throttle to 100%

//Center engine shutdown at 26s before MS-IC burnout (G >= 3.8g)

CLEARSCREEN.

UNTIL (MSIC:MASS - MSIC:DRYMASS)/(Outboard:FUELFLOW * 5) < 26 {
  LaunchDisplay(4,2,Outboard:THRUST/Outboard:MAXTHRUST).
  //WAIT 0.01.
}

Inboard:SHUTDOWN. //Inboard cut-off.

CLEARSCREEN.

//Manage g-forces here?

//Stage MS-IC
UNTIL Outboard:FLAMEOUT = TRUE {
  IF Outboard:MAXTHRUST > 0 {//Prevent NAN
    LaunchDisplay(5,2,Outboard:Thrust/Outboard:MAXTHRUST).
  }
  //WAIT 0.01.
}

PRINT "Main Engine Cut-off   ".
WAIT 1.

STAGE. //MS-IC staging.

//Ignite MS-II

CLEARSCREEN.

WAIT 3.
STAGE. //MS-II ignition.
PRINT "Second stage ignition.".

//Skirt seperation
WAIT 30.
STAGE.
PRINT "Skirt separation.".

//LES Tower jettison
WAIT 6.
AG27 on.
PRINT "Launch escape tower jettison.".

//Ignite MS-II and develop guidance to achieve circular orbit at ~200 km - 250 km
//Code should monitor vert vel and time to AP, but code should find optimal pitch profile for MS-II flight and orbital insertion (lowest possible dV usage)
//Set throttle to zero when code terminates.
SET SHIP:CONTROL:PILOTMAINTHROTTLE to 1. //This will be changed to "set to 0" when the program is fully written.

So now the next step in the steering code is to tell the rocket to make a circular orbit after getting mostly out of the atmosphere.  I feel about 75km is the best time to start this part of the program because with the current gravity turn program, the apoapsis is already at 175 km when SRB sep happens at about 70km altitude.

WARNING: MATH AHEAD!!!

The first problem is deciding how to tell the rocket to steer itself to match a pre-set apoapsis.  After some though and looking at equations for orbital velocity, velocity at apoapsis, orbital radius at apoapsis, and more, I decided to try to get the rocket to seek to hit a target apoapsis at secondary engine cut-off (SECO) through a PID loop.  Using the equations for orbital velocity and apoapsis velocity, I assumed that I could represent orbital velocity as a function f(z) times apoapsis velocity:

NfWzB67.png

Substituting for v_orb and v_ap and solving for f(z), I get:

JvYRLX2.png

Substituting that back in and letting v_orb = v_vert*sin(theta), where theta is the rocket pitch angle, and solving for r_ap, or the apoapsis (+ radius of the earth), I eventually get:

0ZKzEJE.png

Where mu = G*M.  I think I'll have to solve this for theta since I'll be measuring errors between the final and current apoapsis to get a pitch for the rocket.  I'll also need to limit the outputs so I don't get hard steering.

If anyone wants to check my math, I can post the derivations, but I hope these equations will work for me.

Also, I promise that I'll actually fly the mission.  The autopilot is the last huge project I want to work on before I fly it.

Link to comment
Share on other sites

So it's apparently possible for Notepad++ to crash and delete an entire script.

I'm glad I posted updates, but I just lost a couple of days work because Notepad++ totally deleted my launch script during a crash. :/

 

EDIT: I found the back-ups.  My latest code for the launch script is a mess because I'm still constructing the PID controller for orbital insertion.

 

//Saturn VB Autopilot program
//Ctrl + C to kill?

RUNPATH("AresLaunchDisplay.ks").

SET ddyn to 0.
SET dynzero to 0.

//If variables are lists, can I accees each element in loops below and make code more efficient?
SET Inboard to SHIP:PARTSTAGGED("F1AInboard")[0].
SET Outboard to SHIP:PARTSTAGGED("F1AOutboard1")[0].
SET SRB to SHIP:PARTSTAGGED("SRB1")[0].
SET MSIC to SHIP:PARTSTAGGED("MS-IC")[0].

CLEARSCREEN. //in case we need this

//Display event, throttle setting, F-1A thrust %, and SRB thrust %.
//Lock steering to a variable to make it less intensive to run?
LOCK STEERING to Autopilot.
LOCK Autopilot to "Kill".
LOCK THROTTLE to 1.0.

//Temp - steering debug - delete after use
//SET STEERINGMANAGER:SHOWSTEERINGSTATS to TRUE.
SET STEERINGMANAGER:SHOWFACINGVECTORS to TRUE.
SET STEERINGMANAGER:SHOWANGULARVECTORS to TRUE.
STAGE. //F-1A ignition

//Ultimate goal of steering program is to set rocket into pre-programmed circular orbit of 200 km - 250 km.
//Pitch by x degrees, then follow prograde until rocket reaches certain altitude.
//Finally, manage pitch to put Ares in circular orbit.
//In launches using manual steering, Ares ends gravity turn between SRB sep and MS-IC burnout.

//Adjust heading to meet propulsion stack inclination (or desired inclination).  Could have this able to be set as input prior to launch.

//At v(sfc) = 50 m/s, pitch over a bit to initiate gravity turn.
//then hold prograde for gravity turn. (angle between v and a zero.)

//Pitch and roll manuever.  Correct initial pitch is trial and error right now.
//Could the gravity turn be better programmed as a diff eq (predictive equation)?

//Print that gravity turn is in progress - Integrate with LaunchDisplay function?

WHEN SHIP:VELOCITY:SURFACE:MAG >= 50 THEN {
  //Pitch then roll for inclination (90 degrees for now). - smooth out move to pitch?
  LOCK Autopilot to HEADING(90,80). //175 km AP at SRB sep.  SRB sep at 70 km. -  Last setting, 78 degrees pitch, then 83
  IF ROUND(VANG(SHIP:FACING:VECTOR, VXCL(UP:VECTOR,STEERINGMANAGER:TARGET:VECTOR))) = 90 {
    Return true.
  }
  //ELSE {
    //Return false.
  //}
  //Follow prograde next.
  WHEN SHIP:FACING:VECTOR:NORMALIZED:Z - SHIP:VELOCITY:SURFACE:NORMALIZED:Z <= 0 THEN { //might need to change this condition
   LOCK Autopilot to SHIP:VELOCITY:SURFACE. //SHIP:VELOCITY:SURFACE or SHIP:SRFPROGRADE?
   PRINT "Begin Gravity Turn" at (0,10).   
   //Start PID loop for hitting set apoapsis - lasts until SECO.
   //Output pitch (or yaw) based on set final apoapsis.
   WHEN SHIP:ALTITUDE > 75000 THEN { //75000
     PRINT "Initiate Closed-Loop Steering" at (0,10).
     SET PID TO PIDLOOP(). // do once (Kp, Ki, Kd, Minoutput, Maxoutput) - Max and min output probaby needs to be updated
	 SET PID:SETPOINT to 250000. //do once
	 //SET Distance to PID:UPDATE(TIME:SECONDS, SHIP:ORBIT:APOAPSIS).  //PID Initialization (possibly incorrect).
	 //LOCK Autopilot to HEADING(90,PID:OUTPUT).  //do once <= this PID:OUTPUT needs to update somewhere.  Then condition engine shutdown in staging part.
     LOCK Pitch1 to VANG(SHIP:FACING:VECTOR, VXCL(UP:VECTOR,STEERINGMANAGER:TARGET:VECTOR)). //initialize PID?
	 UNLOCK Autopilot. //temp
	 WHEN SHIP:APOAPSIS <> SHIP:PERIAPSIS THEN	 { //<= might be dubious SECO condition if AP shoots past PE between physics ticks.
	   //SET Pitch1 TO SHIP:DIRECTION:YAW.
	   PRINT "Pitch correction: " + Pitch1 at (0,4).
	   PRINT "PID Input:" + PID:INPUT at (0,5).  //Apoapsis
	   PRINT "PID Output :" + PID:OUTPUT at (0,6). // Error
	   PRINT "Error: " + PID:ERROR at (0,7).
	   PRINT PID:SETPOINT - SHIP:ORBIT:APOAPSIS at (0,8).
	   SET Distance to PID:UPDATE(TIME:SECONDS, SHIP:ORBIT:APOAPSIS).
	   //If Distance < 0 { //is Pitch < 0 ever?
	     //SET Pitch1 to ARCSIN(-SQRT(((ABS(Distance)+EARTH:RADIUS)*(SHIP:VERTICALSPEED)^2)/(((2*SHIP:ORBIT:SEMIMAJORAXIS/SHIP:ALTITUDE+EARTH:RADIUS)-1)*(1+ORBIT:ECCENTRICITY)*EARTH:MU))).
	   //}
	   //ELSE {
	     SET Pitch1 to ARCSIN(SQRT(((Distance+EARTH:RADIUS)*(SHIP:VERTICALSPEED)^2)/(((2*SHIP:ORBIT:SEMIMAJORAXIS/(SHIP:ALTITUDE+EARTH:RADIUS))-1)*(1+ORBIT:ECCENTRICITY)*EARTH:MU))).
	   //}
       //SET Autopilot TO HEADING(90,30). //Set this to current pitch + pitch correction.
       RETURN true.	   
	 }
   }  
  }
}

//Countdown here?

UNTIL (Outboard:THRUST/Outboard:MAXTHRUST) > 0.88 {
  IF(Outboard:MAXTHRUST > 0) {  //Prevent NAN
    LaunchDisplay(0,2,Outboard:THRUST/Outboard:MAXTHRUST,0).
  }
  
  //WAIT 0.01.
}

STAGE.  //SRB ignition and liftoff
CLEARSCREEN.

//Maybe countdown and abort mode display.

//WAIT 0.01.

//Display loop could continue on with a PRESERVE command after throttleback?
UNTIL MISSIONTIME > 25 {
  IF(SRB:MAXTHRUST > 0 AND SRB:THRUST > 0) { //Prevent NAN
    //PRINT VANG(SHIP:FACING:VECTOR, VXCL(UP:VECTOR,STEERINGMANAGER:TARGET:VECTOR)) at (0,4).
    //PRINT "Facing-vel srf Angle: " + VANG(SHIP:FACING:VECTOR, SHIP:VELOCITY:SURFACE) + "  " at (0,4).
	//PRINT "Facing Z - Vel Srf Z (Normalized): " + (SHIP:FACING:VECTOR:NORMALIZED:Z - SHIP:VELOCITY:SURFACE:NORMALIZED:Z) at (0,5).
	//PRINT "Facing-target Angle: " + VANG(SHIP:FACING:VECTOR, STEERINGMANAGER:TARGET:VECTOR) + "  " at (0,6).
    //PRINT "Facing - Target: " + (SHIP:FACING:VECTOR:Z - STEERINGMANAGER:TARGET:VECTOR:Z) + "  " at (0,7).
    //PRINT "Facing Z: " + SHIP:FACING:VECTOR:Z + "  "at (0,8).
    //PRINT "Vel Srf Z: " + SHIP:VELOCITY:SURFACE:Z + "  "at (0,9).
    LaunchDisplay(1,2,Outboard:THRUST/Outboard:MAXTHRUST,SRB:THRUST/SRB:MAXTHRUST).
  }
  //WAIT 0.01.
}

CLEARSCREEN.

LOCK THROTTLE to 0.01. //F-1A throttle to 60% for max Q

//check dyn pressure change
//if ddyn < -0.004kPa/0.01s or so, throttle to 85% (was -0.04kPa/0.1s)

UNTIL ddyn <= -0.004 {
  LaunchDisplay(2,0,Outboard:THRUST/Outboard:MAXTHRUST,SRB:Thrust/SRB:MAXTHRUST).
  SET ddyn TO (SHIP:Q*constant:ATMtokPa) - dynzero. //units are kPa <- can be lock statement
  SET dynzero TO (SHIP:Q*constant:ATMtokPa). //<- these can be LOCK statements
  WAIT 0.01. //change to 0.1? <- can remove this when using lock and dividing by time.
}

LOCK THROTTLE to 0.63. //F-1A throttle to 85%

CLEARSCREEN.

//4+Gs before SRB tail-off.

//Stage SRBs and throttle to 100% when SRB thrust < 10%
UNTIL SRB:THRUST/SRB:MAXTHRUST < .1 {
  LaunchDisplay(3,1,Outboard:THRUST/Outboard:MAXTHRUST,SRB:Thrust/SRB:MAXTHRUST).
  //WAIT 0.01.
}

STAGE. //SRB jettison

LOCK THROTTLE to 1.0. //F-1A throttle to 100%

//Center engine shutdown at 26s before MS-IC burnout (G >= 3.8g)

CLEARSCREEN.

UNTIL (MSIC:MASS - MSIC:DRYMASS)/(Outboard:FUELFLOW * 5) < 26 {
  LaunchDisplay(4,2,Outboard:THRUST/Outboard:MAXTHRUST).
  //WAIT 0.01.
}

Inboard:SHUTDOWN. //Inboard cut-off.

CLEARSCREEN.

//Manage g-forces here?

//Stage MS-IC
UNTIL Outboard:FLAMEOUT = TRUE {
  IF Outboard:MAXTHRUST > 0 {//Prevent NAN
    LaunchDisplay(5,2,Outboard:Thrust/Outboard:MAXTHRUST).
  }
  //WAIT 0.01.
}

PRINT "Main Engine Cut-off   ".
WAIT 1.

STAGE. //MS-IC staging.

//Ignite MS-II

CLEARSCREEN.

WAIT 3.
STAGE. //MS-II ignition.
PRINT "Second stage ignition.".

//Skirt seperation
WAIT 30.
STAGE.
PRINT "Skirt separation.".

//LES Tower jettison
WAIT 6.
AG27 on.
PRINT "Launch escape tower jettison.".

//Ignite MS-II and develop guidance to achieve circular orbit at ~200 km - 250 km
//Code should monitor vert vel and time to AP, but code should find optimal pitch profile for MS-II flight and orbital insertion (lowest possible dV usage)
//Set throttle to zero when code terminates.
SET SHIP:CONTROL:PILOTMAINTHROTTLE to 1. //This will be changed to "set to 0" when the program is fully written.

 

Edited by Nittany Tiger
Link to comment
Share on other sites

Amazing to see you carry through this Journey for so many months! I remember seeing the MEM while @TiktaalikDreaming was initially creating it. I wanted to make the RO configs for it, but then got busy, and I'm really happy to see that someone else did a pretty good job of it. I wasn't able to find an RO craft file of it, but I assembled it today and landed it a few times in Hellas, because I like easy mode. :P

I tried making the triple S-II TMI Journey type craft a few times in the past, but I always get heavy boiloff and abandoned the task. Now I'm mostly working on adding and configuring enough components to carry out a late 70s or 80s Mars Direct style mission.

Keep it up, @Nittany Tiger, your journey is an inspiration for us Mars lovers. :)

Link to comment
Share on other sites

Thanks.  If I can nail this autopilot program, I'll be almost ready to go.  Of course, I could just skip making it entirely because I've flown the Saturn VB into orbit manually many times, and in fact how I get it to make orbit is how I'm trying to tell kOS to put it in orbit.  Just not sure if I'll have to resort to using huge derivatives or use preset pitches.  I had to ditch guiding by apoapsis difference because the guidance failed after the rocket passed apoapsis.

Did you set your tanks to the cryogenic type?  I had to do that, and my tests show that if you use cryogenic tanks, the boil-off is reduced drastically.  You won't lose all of your LH2 in days or weeks.  Of course, I have yet to fly the mission, but it's only supposed to be 500+ days total, which cryo tanks can handle.  FASA does default to default type tanks, but there's a setting in one of the config files to change FASA tanks to cryogenic, and it's what I did and it works.

Anyway, I don't know when I'll fly the mission soon, but hopefully within the month if I can get this autopilot functioning.  Pretty much only want to do texture swap after that along with some minor final tests, and I'll be GO for Mars.

Link to comment
Share on other sites

I'll have to check the tank type, try that again. I thought I changed it, but I may have gone to BalloonCryo, which perhaps isn't as good. If you find and share the setting you changed that you know worked, i'd appreciate it. :)

We could/should start (or find a pre-existing) threat for complex RSS/RF automation like kOS or KRPC. IIIRC, I used "time to apo" as an input for my final orbital insertion program, but I had to do something clever so that it turned into a negative number when I was past AP, rather than a very large number. I think I used the orbital period, like: usefulAP = timeToAP -  orbitalPeriod when timeToAP was greater than 1000 seconds or something. I know @Agathorn and @BevoLJ have strong kOS/KRPC automation skills.

Link to comment
Share on other sites

If you're using TOA, then you'd just flip the sign or flip a difference in the calculation.  The calculation for TOA is somewhere.

I actually changed to monitoring vertical velocity and having the code aim for zero vertical acceleration.  It works, but it's still a bit inaccurate.  When I launch manually, I always check apoapsis and vertical velocity and aim to get my vertical velocity at zero right at SECO to get a circular orbit.  As for a preset apoapsis, that might depend on initial pitch deflection.

The most straightforward thing I could do is to use this equation:

Xb7P65y.png

I feel that's too much for a simple autopilot though.  I have thought about using a relation between pitch angle and other variables like apoapsis, but I get this:

0ZKzEJE.png

And if I solve for theta, I get:

naHSyhO.png

I assume that I can treat PID outputs as changes, so I think I could take the time derivative of this equation to get a formula that might give me a way to get an accurate pitch difference for a change in apoapsis and vertical velocity.  Here's the problem, though.  All of the variables except mu are dependent on time.  In other words:

CQgZ4OQ.png

So gotta break out that chain rule for d(theta)/dt.  I get

7JqZG41.png

So a lot of derivatives to do, and I have to track the time rate of change of any variable that's not part of a PID loop.  I'm still working the partials out, so I can do the calculus, but I don't know if using this equation and treating some or even all of the total derivatives as PID outputs will give me a good way to steer my rocket near and above the Karman line (where drag is negligible).  All I can do is test it later.

Right now, I think I can make a rough guidance controller measuring vertical velocity.  This is the steering portion of my code:

WHEN SHIP:VELOCITY:SURFACE:MAG >= 50 THEN {
  //Pitch then roll for inclination (90 degrees for now). - smooth out move to pitch?
  LOCK Autopilot to HEADING(90,80). //175 km AP at SRB sep.  SRB sep at 70 km. -  Last setting, 78 degrees pitch, then 83
  IF ROUND(VANG(SHIP:FACING:VECTOR, VXCL(UP:VECTOR,STEERINGMANAGER:TARGET:VECTOR))) = 90 {
    Return true.
  }
  //ELSE {
    //Return false.
  //}
  //Follow prograde next.
  WHEN SHIP:FACING:VECTOR:NORMALIZED:Z - SHIP:VELOCITY:SURFACE:NORMALIZED:Z <= 0 THEN { //might need to change this condition
   LOCK Autopilot to SHIP:VELOCITY:SURFACE. //SHIP:VELOCITY:SURFACE or SHIP:SRFPROGRADE?
   PRINT "Begin Gravity Turn" at (0,10).   
   //Start PID loop for hitting set apoapsis - lasts until SECO.
   //Output pitch (or yaw) based on set final apoapsis. - kill steering at SRB sep?
   WHEN SHIP:ALTITUDE > 75000 THEN { //75000 //PID loop assuming no conversion equation between pitch and apoapsis needed.
     PRINT "Initiate Closed-Loop Steering" at (0,10).
     SET PID TO PIDLOOP(Kp,Ki,Kd). // do once (Kp, Ki, Kd, Minoutput, Maxoutput) - Bounces horribly between min and max - pitch corrections too extreme - needs tuning and lower response time (responds too fast) - pitch bouncy between set AP?  Needs deadzone?
	 SET PID:SETPOINT to 0. //do once
	 //SET Distance to PID:UPDATE(TIME:SECONDS, SHIP:ORBIT:APOAPSIS).  //PID Initialization (possibly incorrect). <- might want to set this to monitor vertical velocity instead of Apoapsis.
	 //LOCK Autopilot to HEADING(90,PID:OUTPUT).  //do once <= this PID:OUTPUT needs to update somewhere.  Then condition engine shutdown in staging part.
     SET Pitch1 to VANG(SHIP:FACING:VECTOR, VXCL(UP:VECTOR,STEERINGMANAGER:TARGET:VECTOR)). //initialize PID?
	 //UNLOCK STEERING. //temp
	 WHEN SHIP:ORBIT:PERIAPSIS < 0 THEN { //<= might be dubious SECO condition if AP shoots past PE between physics ticks.
	   //SET Pitch1 TO SHIP:DIRECTION:YAW.
	   PRINT "Pitch: " + Pitch1 at (0,4). //This is quite large.  Might be a bad derivation.
	   PRINT "PID Input:" + PID:INPUT at (0,5).  //Apoapsis
	   PRINT "PID Output/Pitch Correction:" + PID:OUTPUT at (0,6). // Error
	   PRINT "Error: " + PID:ERROR at (0,7).
	   PRINT PID:SETPOINT - SHIP:VERTICALSPEED at (0,8).
	   SET dPitch to PID:UPDATE(TIME:SECONDS, SHIP:VERTICALSPEED).
	   //Could use preset pitch profile from SRB sep or low atmosphere up until MS-IC sep, then guide towards apoapsis. - Gravity turn -> slow pitch to zero at ~60km -> terminal guidance.
	   IF Outboard:FUELFLOW > 0 AND (MSIC:MASS - MSIC:DRYMASS)/(Outboard:FUELFLOW * 5) < 2 AND J2S:FUELFLOW = 0 AND Count = 1 {
	     SET Autopilot TO HEADING(90,Pitch1). //Hold pitch for staging. - may set to zero.
	   }
	   ELSE IF Pitch1 > 15.1 { //Transition from gravity turn.
	     SET Pitch1 to VANG(SHIP:FACING:VECTOR, VXCL(UP:VECTOR,STEERINGMANAGER:TARGET:VECTOR)).
		 PRINT "Pitching Over" at (0,3).
		 SET Autopilot to HEADING(90,15).
	   }
	   ELSE IF Pitch1 < 15 AND Pitch1 > -2 { //min and max pitch
	     PRINT "Guidance Converging       " at (0,3).
	     SET Pitch1 to Pitch1 + dPitch.
		 SET Autopilot TO HEADING(90,Pitch1). //Set this to current pitch + pitch correction.
	   }
       ELSE {
	     PRINT "test" at (0,3).
	     SET Pitch1 to VANG(SHIP:FACING:VECTOR, VXCL(UP:VECTOR,STEERINGMANAGER:TARGET:VECTOR)).
	     SET Autopilot to HEADING(90,Pitch1). //how to pitch gradually from initial pitch to 10?
	   }
	   LOG MISSIONTIME + "," + (PID:SETPOINT - SHIP:VERTICALSPEED) + "," + dPitch TO Pitch_VVert_Log.txt.
       RETURN true.   
	 }
    SET Autopilot to HEADING(90,0). //Terminal guidance for PE > 0.
   }  
  }
}

I have Kp set to 0.0002 and no Kd or Ki term.  I also have Max Stopping Time set to 0.5 for the Steering Manager.  It causes the rolls to be slow though.  This is not the final code, so it's full of comments and commented junk code, and I still think I need to increase Kd in the end.

Quote

I'll have to check the tank type, try that again. I thought I changed it, but I may have gone to BalloonCryo, which perhaps isn't as good. If you find and share the setting you changed that you know worked, i'd appreciate it.

Look for the file RO_FASA_Saturn.cfg in GameData\RealismOverhaul\RO_SuggestedMods\FASA\RO_FASA_Saturn.cfg and find the line that says @PART[FASAApalloLFTJ25XPlate]:FOR[RealismOverhaul].  This is the part module for the S-II stage tank and engine mounts.  Scroll down until you see

MODULE
	{
		name = ModuleFuelTanks
		volume = 332353.8
		type = Default
		basemass = -1
	}

Change the Default to Cryogenic and you're good to go.  For the S-IVB, just find the @PART[FASAApalloLFTJ2Plate]:FOR[RealismOverhaul] line and do the same thing.

I would think Balloon cryo would work as well, but I'm not sure.  To be honest, I haven't flown the Ares Propulsion Stack on a mission yet, so it could encounter boil-off issues that I'm not aware of yet especially near the Venus Fly-By when it's the closest to the sun.

Link to comment
Share on other sites

Update time.

Cleaned-up code steering code.  Think the count variable is unnecessary now.

//Saturn VB Autopilot program
//Ctrl + C to kill?

RUNPATH("AresLaunchDisplay.ks").

SET ddyn to 0.
SET dynzero to 0.

SET Count to 0. //<- local define later

//If variables are lists, can I accees each element in loops below and make code more efficient?
SET Inboard to SHIP:PARTSTAGGED("F1AInboard")[0].
SET Outboard to SHIP:PARTSTAGGED("F1AOutboard1")[0].
SET J2S to SHIP:PARTSTAGGED("J2S")[0].
SET SRB to SHIP:PARTSTAGGED("SRB1")[0].
SET MSIC to SHIP:PARTSTAGGED("MS-IC")[0].

CLEARSCREEN. //in case we need this

//Display event, throttle setting, F-1A thrust %, and SRB thrust %.
//Lock steering to a variable to make it less intensive to run?
LOCK STEERING to Autopilot.
LOCK Autopilot to "Kill".
LOCK THROTTLE to 1.0.

//Temp - steering debug - delete after use
//SET STEERINGMANAGER:SHOWSTEERINGSTATS to TRUE.
SET STEERINGMANAGER:SHOWFACINGVECTORS to TRUE.
SET STEERINGMANAGER:SHOWANGULARVECTORS to TRUE.

SET STEERINGMANAGER:MAXSTOPPINGTIME to 0.7. //default value 2
STAGE. //F-1A ignition

Set Kp to 0.0045. //last value 0.0015.  0.0025 gets 225km x 201 km. v_vert final 11.92 m/s.  0.0015 gets 234 km x 201 km. 0.0035 gets 220 km x 201 km with v_vert of 9.671 m/s. 0.0045 gets 218 km x 201 km with v_vert of 10.32 m/s.
Set Ki to 0.
Set Kd to 0.

//Tuning Pitch PID for terminal guidance.
LOG "Pitch PID Tuning" TO Pitch_VVert_Log.txt.
LOG "Kp:" + Kp + ",Ki:" + Ki + ",Kd:" + Kd TO Pitch_VVert_Log.txt.
LOG "t,Verical Velocity Deviation:,Pitch Correction:" TO Pitch_VVert_Log.txt.

//Ultimate goal of steering program is to set rocket into pre-programmed circular orbit of 200 km - 250 km.
//Pitch by x degrees, then follow prograde until rocket reaches certain altitude.
//Finally, manage pitch to put Ares in circular orbit.
//In launches using manual steering, Ares ends gravity turn between SRB sep and MS-IC burnout.

//Adjust heading to meet propulsion stack inclination (or desired inclination).  Could have this able to be set as input prior to launch.

//At v(sfc) = 50 m/s, pitch over a bit to initiate gravity turn.
//then hold prograde for gravity turn. (angle between v and a zero.)

//Pitch and roll manuever.  Correct initial pitch is trial and error right now.
//Could the gravity turn be better programmed as a diff eq (predictive equation)?

//Print that gravity turn is in progress - Integrate with LaunchDisplay function?

//Guidance control.
WHEN SHIP:VELOCITY:SURFACE:MAG >= 50 THEN {
  //Pitch then roll for inclination (90 degrees for now). - smooth out move to pitch?
  LOCK Autopilot to HEADING(90,80). //175 km AP at SRB sep.  SRB sep at 70 km. -  Last setting, 78 degrees pitch, then 83
  IF ROUND(VANG(SHIP:FACING:VECTOR, VXCL(UP:VECTOR,STEERINGMANAGER:TARGET:VECTOR))) = 90 { //Sometimes, the rocket pointing straight up causes next when trigger to be true, so this line prevents a vertical launch from triggering the gravity turn code.
    Return true.
  }
  //Gravity turn - Follow prograde next.
  WHEN SHIP:FACING:VECTOR:NORMALIZED:Z - SHIP:VELOCITY:SURFACE:NORMALIZED:Z <= 0 THEN { //might need to change this condition
   LOCK Autopilot to SHIP:VELOCITY:SURFACE. //SHIP:VELOCITY:SURFACE or SHIP:SRFPROGRADE?
   PRINT "Begin Gravity Turn" at (0,10).   
   WHEN SHIP:ALTITUDE > 75000 THEN { //At 75km, start program to control pitch based on current rocket path - currently monitors vertical velocity.
     PRINT "Initiate Closed-Loop Steering" at (0,10).
     SET PID TO PIDLOOP(Kp,Ki,Kd). // do once (Kp, Ki, Kd, Minoutput, Maxoutput) - Bounces horribly between min and max - pitch corrections too extreme - needs tuning and lower response time (responds too fast) - pitch bouncy between set AP?  Needs deadzone?
	 SET PID:SETPOINT to 0. //do once
     SET Pitch1 to VANG(SHIP:FACING:VECTOR, VXCL(UP:VECTOR,STEERINGMANAGER:TARGET:VECTOR)). //initialize PID?
	 WHEN true THEN { //<= loops until PE > 0.
	   PRINT "Pitch: " + Pitch1 at (0,4). //This is quite large.  Might be a bad derivation.
	   PRINT "PID Input:" + PID:INPUT at (0,5).  //Apoapsis
	   PRINT "PID Output/Pitch Correction:" + PID:OUTPUT at (0,6). // Error
	   PRINT "Error: " + PID:ERROR at (0,7).
	   PRINT PID:SETPOINT - SHIP:VERTICALSPEED at (0,8).
	   SET dPitch to PID:UPDATE(TIME:SECONDS, SHIP:VERTICALSPEED).
	   IF Outboard:FUELFLOW > 0 AND (MSIC:MASS - MSIC:DRYMASS)/(Outboard:FUELFLOW * 5) < 2 AND J2S:FUELFLOW = 0 AND Count = 1 { //Hold pitch for MS-IC/MS-II staging.
	     SET Autopilot TO HEADING(90,Pitch1).
	   }
	   ELSE IF Pitch1 > 15 { //Transition from gravity turn or oversteer past maximum.
	     SET Pitch1 to VANG(SHIP:FACING:VECTOR, VXCL(UP:VECTOR,STEERINGMANAGER:TARGET:VECTOR)).
		 PRINT "Pitching Over      " at (0,3). //change this text?
		 SET Autopilot to HEADING(90,14.9).
	   }
	   ELSE IF Pitch1 < 15 AND Pitch1 > 0 { //min and max pitch
	     PRINT "Guidance Converging       " at (0,3).
	     SET Pitch1 to Pitch1 + dPitch.
		 SET Autopilot TO HEADING(90,Pitch1).
	   }
       ELSE IF SHIP:ORBIT:PERIAPSIS > 0 { //This sets pitch to zero for final orbital insertion to make orbit as circular as possible.
	     PRINT "Terminal Guidance      " at (0,3).
         LOCK Autopilot to HEADING(90,0). //Terminal guidance for PE > 0.
		 RETURN false. //Kill steering loop.
	   }
	   ELSE { //oversteer past minimum
	     PRINT "test" at (0,3).
	     SET Pitch1 to VANG(SHIP:FACING:VECTOR, VXCL(UP:VECTOR,STEERINGMANAGER:TARGET:VECTOR)).
	     SET Autopilot to HEADING(90,0). //how to pitch gradually from initial pitch to 15 - how is this getting triggered after PE > 0?
	   }
	   IF SHIP:VERTICALSPEED < 150{
	     PRINT "Logging" at (0,11).
	     LOG MISSIONTIME + "," + (PID:SETPOINT - SHIP:VERTICALSPEED) + "," + dPitch TO Pitch_VVert_Log.txt.
       }
       RETURN true.	   
	 }  
   }  
  }
}

//Staging control.
//Countdown here?

//F-1A Ignition
UNTIL (Outboard:THRUST/Outboard:MAXTHRUST) > 0.88 {
  IF(Outboard:MAXTHRUST > 0) {  //Prevent NAN
    //PRINT STEERINGMANAGER:MAXSTOPPINGTIME at (0,4).
    LaunchDisplay(0,2,Outboard:THRUST/Outboard:MAXTHRUST,0).
  }
  
  //WAIT 0.01.
}

STAGE.  //SRB Ignition and Liftoff
CLEARSCREEN.

//Maybe countdown and abort mode display.

//WAIT 0.01.

//Display loop could continue on with a PRESERVE command after throttleback?
UNTIL MISSIONTIME > 25 {
  IF(SRB:MAXTHRUST > 0 AND SRB:THRUST > 0) { //Prevent NAN
    //PRINT VANG(SHIP:FACING:VECTOR, VXCL(UP:VECTOR,STEERINGMANAGER:TARGET:VECTOR)) at (0,4).
    //PRINT "Facing-vel srf Angle: " + VANG(SHIP:FACING:VECTOR, SHIP:VELOCITY:SURFACE) + "  " at (0,4).
	//PRINT "Facing Z - Vel Srf Z (Normalized): " + (SHIP:FACING:VECTOR:NORMALIZED:Z - SHIP:VELOCITY:SURFACE:NORMALIZED:Z) at (0,5).
	//PRINT "Facing-target Angle: " + VANG(SHIP:FACING:VECTOR, STEERINGMANAGER:TARGET:VECTOR) + "  " at (0,6).
    //PRINT "Facing - Target: " + (SHIP:FACING:VECTOR:Z - STEERINGMANAGER:TARGET:VECTOR:Z) + "  " at (0,7).
    //PRINT "Facing Z: " + SHIP:FACING:VECTOR:Z + "  "at (0,8).
    //PRINT "Vel Srf Z: " + SHIP:VELOCITY:SURFACE:Z + "  "at (0,9).
    LaunchDisplay(1,2,Outboard:THRUST/Outboard:MAXTHRUST,SRB:THRUST/SRB:MAXTHRUST).
  }
  //WAIT 0.01.
}

CLEARSCREEN.

LOCK THROTTLE to 0.01. //F-1A throttle to 60% for max Q

//check dyn pressure change
//if ddyn < -0.004kPa/0.01s or so, throttle to 85% (was -0.04kPa/0.1s)

UNTIL ddyn <= -0.01 { //originally 0.004
  LaunchDisplay(2,0,Outboard:THRUST/Outboard:MAXTHRUST,SRB:Thrust/SRB:MAXTHRUST).
  SET ddyn TO (SHIP:Q*constant:ATMtokPa) - dynzero. //units are kPa <- can be lock statement
  SET dynzero TO (SHIP:Q*constant:ATMtokPa). //<- these can be LOCK statements
  WAIT 0.01. //change to 0.1? <- can remove this when using lock and dividing by time.
}

LOCK THROTTLE to 0.63. //F-1A throttle to 85%

CLEARSCREEN.

//4+Gs before SRB tail-off.

//Stage SRBs and throttle to 100% when SRB thrust < 10%
UNTIL SRB:THRUST/SRB:MAXTHRUST < .1 {
  LaunchDisplay(3,1,Outboard:THRUST/Outboard:MAXTHRUST,SRB:Thrust/SRB:MAXTHRUST).
  //WAIT 0.01.
}

STAGE. //SRB jettison

LOCK THROTTLE to 1.0. //F-1A throttle to 100%

//Center engine shutdown at 26s before MS-IC burnout (G >= 3.8g)

CLEARSCREEN.

UNTIL (MSIC:MASS - MSIC:DRYMASS)/(Outboard:FUELFLOW * 5) < 26 {
  LaunchDisplay(4,2,Outboard:THRUST/Outboard:MAXTHRUST).
  //WAIT 0.01.
}

Inboard:SHUTDOWN. //Inboard cut-off.

CLEARSCREEN.

//Manage g-forces here?

//Remainder of MS-IC Flight
UNTIL Outboard:FLAMEOUT = TRUE {
  IF Outboard:MAXTHRUST > 0 {//Prevent NAN
    LaunchDisplay(5,2,Outboard:Thrust/Outboard:MAXTHRUST).
  }
  //WAIT 0.01.
}

//Main Engine Cut-Off
CLEARSCREEN.
LaunchDisplay(6,3,0).
WAIT 1.


CLEARSCREEN.
STAGE. //MS-IC Staging.
LaunchDisplay(7,3,0).
WAIT 3.

CLEARSCREEN.


STAGE. //MS-II Ignition.
SET t0 to TIME:SECONDS.

UNTIL TIME:SECONDS - t0 > 30 {
  LaunchDisplay(8,2,J2S:THRUST/J2S:MAXTHRUST).
} 

CLEARSCREEN.


STAGE. //Skirt seperation
Set t0 to TIME:SECONDS.

UNTIL TIME:SECONDS - t0 > 6 {
  LaunchDisplay(9,2,J2S:THRUST/J2S:MAXTHRUST).
}

CLEARSCREEN.

AG27 on. //LES Tower jettison <- this event will be moved in final code.
UNTIL SHIP:ORBIT:PERIAPSIS >= 200000 { //set to be higher than set apoapsis <- could set this to AP when PE = 0 to attempt circularization.
  LaunchDisplay(10,2,J2S:THRUST/J2S:MAXTHRUST).
}

//SECO - Orbit insertion.
CLEARSCREEN.
LOCK THROTTLE to 0.

PRINT "Secondary Engine Cut-Off" at (0,2).
PRINT "Go for Orbit" at (0,3).

//Keep code running until SECO (Periapsis > 200 km or 250 km?)

SET SHIP:CONTROL:PILOTMAINTHROTTLE to 0. //Current final orbit 234 km x 201 km

Been tweaking Kp to see how it affects the steering, mainly focusing on the final orbit and final vertical velocity.

Kp Apoapsis (km) Periapsis (km) Final Vertical Velocity (m/s) delta Q (kPa/0.01s)
0.0015 234 201 N/A -0.004
0.0025 225 201 11.92 -0.004
0.0035 220 201 9.671 -0.006
0.0045 218 201 10.32 -0.01

I'm hoping to get the final vertical velocity as low as possible so I can set the code to have the periapsis match the apoapsis.

Delta Q is the setting in the code that triggers F-1A throttle-up after the max Q throttleback.  Higher settings mean a later throttle-up, and I changed this setting to lower the max Q below 40 kPa.  Given that I need to throttle the F-1As back after max Q due to high G loading (< 4 Gs and sometimes < 4.5 Gs at times), I think I'll work on the final throttle guidance before I tune the PID loop any more.

Also, finished the time derivative of naHSyhO.png .  I'll save this equation for a more robust autopilot program in the future.

w3XKpPD.png

Link to comment
Share on other sites

On 3/9/2017 at 11:28 AM, stratochief66 said:

I'll have to check the tank type, try that again. I thought I changed it, but I may have gone to BalloonCryo, which perhaps isn't as good. If you find and share the setting you changed that you know worked, i'd appreciate it. :)

We could/should start (or find a pre-existing) threat for complex RSS/RF automation like kOS or KRPC. IIIRC, I used "time to apo" as an input for my final orbital insertion program, but I had to do something clever so that it turned into a negative number when I was past AP, rather than a very large number. I think I used the orbital period, like: usefulAP = timeToAP -  orbitalPeriod when timeToAP was greater than 1000 seconds or something. I know @Agathorn and @BevoLJ have strong kOS/KRPC automation skills.

o/ Chief!  =)

If we are talking about pitch adjustments for circularising orbits at ap or pe, I use mean anomaly.

_ap_deltaDeg = np.rad2deg(self.mean_anomaly()) - 180  # launch circ and hohmann xfers

for hohmann xfer burns at pe, I just use the mean anomaly straight for pitch adjustments.  =)

Edited by BevoLJ
apparently can't spell "hohmann"
Link to comment
Share on other sites

On 3/9/2017 at 7:48 PM, Nittany Tiger said:

If you're using TOA, then you'd just flip the sign or flip a difference in the calculation.  The calculation for TOA is somewhere.

I actually changed to monitoring vertical velocity and having the code aim for zero vertical acceleration.  It works, but it's still a bit inaccurate.  When I launch manually, I always check apoapsis and vertical velocity and aim to get my vertical velocity at zero right at SECO to get a circular orbit.  As for a preset apoapsis, that might depend on initial pitch deflection.

This is a fun thread!  Will need to set aside time this weekend to read it.  =)

I do something somewhat similar but rather than vertical speed I use orbital velocities.  set desired parking orbit and then get the required orbital velocity I will need to achieve that desired parking orbit.

_mu = gravitational_parameter
_radius = parkingOrbit_radius             # (parking orbit altitude + parent body radius)

desiredVelocity = sqrt(_mu / _radius)

I can then use the semi-major axis during launch to predict what my current velocity is at my apoapsis (if I were to cut engines during launch and just go there).  That way during launch I can see how much I need to change the velocity (deltaV) of my apoapsis to achieve the desired parking orbit I want.

Here is my predictive apoapsis speed using semi-major axis:

_mu = gravitational_parameter
_r_pe = periapsis_radius                  # (current periapsis altitude + parent body radius)
_r_ap = apoapsis_radius                   # (current apoapsis altitude + parent body radius)

predicted_apoapsis_Velocity = sqrt((2 * _mu * _r_pe) / (_r_ap * (_r_ap + _r_pe)))

using the known needed deltaV for the desired parking orbit I can now easily adjust my pitch during launch to achieve that altitude.

parkingOrbit_required_deltaV = desiredVelocity - predicted_apoapsis_Velocity

(Note: previous reply to @stratochief66 where I also use (mean anomaly - 180) to keep in mind where the ap is and include pitch adjustments for that aswell)

 

All of the above is ideal for doing Hohmann Xfers but a launch is basicly just a fancy Hohmann Xfer that (from Earth) include atmospheric flight.  :P

Edited by BevoLJ
Link to comment
Share on other sites

14 hours ago, BevoLJ said:

out pitch adjustments for circularising orbits at ap or pe, I use mean anomaly.


_ap_deltaDeg = np.rad2deg(self.mean_anomaly()) - 180  # launch circ and hohmann xfers

for hohmann xfer burns at pe, I just use the mean anomaly straight for pitch adjustments.  =)

I didn't think of using mean anomaly.  Chalk that to not knowing much about orbital mechanics despite a bachelors in physics and over 2000 hours in stock KSP (and probably a few hundred in RSS/RO).  I looked more at vertical velocity and apoapsis, and then I looked at the physics of the problem and came up with some formulas based on free-body diagrams I drew in GIMP.  That's how I got my diff eq, and then that's how I got my pitch relation that I took the time derivative of to get that huge formula.  I'm not sure if that formula is even necessary or accurate, but it looks accurate if you neglect air drag, and you could theoretically tie a PID loop for many variables to pitch control and potentially get a very nice steering program...or something crazy.  I do want to try it out after I fly this mission.  Of course, I also want to do other RSS missions like Apollo to Titan, where I might include the N1 and NERVA (because Soviet/Russian co-operation I guess).

13 hours ago, BevoLJ said:

This is a fun thread!  Will need to set aside time this weekend to read it.  =)

I do something somewhat similar but rather than vertical speed I use orbital velocities.  set desired parking orbit and then get the required orbital velocity I will need to achieve that desired parking orbit.


_mu = gravitational_parameter
_radius = parkingOrbit_radius             # (parking orbit altitude + parent body radius)

desiredVelocity = sqrt(_mu / _radius)

I can then use the semi-major axis during launch to predict what my current velocity is at my apoapsis (if I were to cut engines during launch and just go there).  That way during launch I can see how much I need to change the velocity (deltaV) of my apoapsis to achieve the desired parking orbit I want.

Here is my predictive apoapsis speed using semi-major axis:


_mu = gravitational_parameter
_r_pe = periapsis_radius                  # (current periapsis altitude + parent body radius)
_r_ap = apoapsis_radius                   # (current apoapsis altitude + parent body radius)

predicted_apoapsis_Velocity = sqrt((2 * _mu * _r_pe) / (_r_ap * (_r_ap + _r_pe)))

using the known needed deltaV for the desired parking orbit I can now easily adjust my pitch during launch to achieve that altitude.


parkingOrbit_required_deltaV = desiredVelocity - predicted_apoapsis_Velocity

(Note: previous reply to @stratochief66 where I also use (mean anomaly - 180) to keep in mind where the ap is and include pitch adjustments for that aswell)

 

All of the above is ideal for doing Hohmann Xfers but a launch is basicly just a fancy Hohmann Xfer that (from Earth) include atmospheric flight.  :P

I thought of using final orbital velocity initially, but I didn't think I would need to use it when I first went with an apoapsis PID loop, and I also thought that a final orbital velocity might not be unique to an orbit unless you aimed for a specific apoapsis first, because then every orbit with a common AP or PE will have unique orbital velocity profiles.  Plus, for circular orbits, the orbital velocity will be constant like you noted above.

As far as treating launches as Hohmann transfers, I didn't think of that because you're not burning prograde from one orbit and coasting to another, but you're burning radial out from one orbit, and burning constantly to your target orbit.  Of course, the math for each kind of orbit change might be the same.  If your approximation works for you, then there must be a way that both kinds of orbit transfers are approximately equal or even equivalent.

EDIT:

I've made changes to the throttling profile during the MS-IC burn so the Gs don't go above 4, but it's changed my launch profile.  I get a lower AP during the burn, and different final AP and v_vert.  For instance, with Kp set to 0.0015, my final AP is 231.549 km and my final v_vert is about 31.96 m/s. I set final PEs to be 170 km because the old setting of 200 km was resulting in the MS-II never shutting down until fuel exhaustion because the rocket would be below 200 km when it approached orbital insertion, and thus the PE would never go above 200 km.

Edited by Nittany Tiger
Link to comment
Share on other sites

More tuning tests with the vertical velocity PID controller.

Code as of this post:

//Saturn VB Autopilot program
//Ctrl + C to kill?

RUNPATH("AresLaunchDisplay.ks").

SET ddyn to 0.
SET dynzero to 0.

//If variables are lists, can I accees each element in loops below and make code more efficient?
SET Inboard to SHIP:PARTSTAGGED("F1AInboard")[0].
SET Outboard to SHIP:PARTSTAGGED("F1AOutboard1")[0].
SET J2S to SHIP:PARTSTAGGED("J2S")[0].
SET SRB to SHIP:PARTSTAGGED("SRB1")[0].
SET MSIC to SHIP:PARTSTAGGED("MS-IC")[0].

CLEARSCREEN. //in case we need this

//Display event, throttle setting, F-1A thrust %, and SRB thrust %.
//Lock steering to a variable to make it less intensive to run?
LOCK STEERING to Autopilot.
LOCK Autopilot to "Kill".
LOCK THROTTLE to 1.0.

//Temp - steering debug - delete after use
//SET STEERINGMANAGER:SHOWSTEERINGSTATS to TRUE.
SET STEERINGMANAGER:SHOWFACINGVECTORS to TRUE.
SET STEERINGMANAGER:SHOWANGULARVECTORS to TRUE.

SET STEERINGMANAGER:MAXSTOPPINGTIME to 0.7. //default value 2
STAGE. //F-1A ignition

Set Kp to 0.00264. //Ku = 0.0033?  
Set Ki to 0.
Set Kd to 0.0165. //Last Kd: 0.00132

//Tuning Pitch PID for terminal guidance.
//LOG "Pitch PID Tuning" TO Pitch_VVert_Log.txt.
//LOG "Kp:" + Kp + ",Ki:" + Ki + ",Kd:" + Kd TO Pitch_VVert_Log.txt.
//LOG "t,Verical Velocity Deviation:,Pitch Correction:" TO Pitch_VVert_Log.txt.

//Ultimate goal of steering program is to set rocket into pre-programmed circular orbit of 200 km - 250 km.
//Pitch by x degrees, then follow prograde until rocket reaches certain altitude.
//Finally, manage pitch to put Ares in circular orbit.
//In launches using manual steering, Ares ends gravity turn between SRB sep and MS-IC burnout.

//Adjust heading to meet propulsion stack inclination (or desired inclination).  Could have this able to be set as input prior to launch.

//At v(sfc) = 50 m/s, pitch over a bit to initiate gravity turn.
//then hold prograde for gravity turn. (angle between v and a zero.)

//Pitch and roll manuever.  Correct initial pitch is trial and error right now.
//Could the gravity turn be better programmed as a diff eq (predictive equation)?

//Print that gravity turn is in progress - Integrate with LaunchDisplay function?

//Guidance control.
WHEN SHIP:VELOCITY:SURFACE:MAG >= 50 THEN {
  //Pitch then roll for inclination (90 degrees for now). - smooth out move to pitch?
  LOCK Autopilot to HEADING(90,80). //175 km AP at SRB sep.  SRB sep at 70 km. -  Last setting,80, then 78 degrees pitch, then 83
  IF ROUND(VANG(SHIP:FACING:VECTOR, VXCL(UP:VECTOR,STEERINGMANAGER:TARGET:VECTOR))) = 90 { //Sometimes, the rocket pointing straight up causes next when trigger to be true, so this line prevents a vertical launch from triggering the gravity turn code.
    Return true.
  }
  //Gravity turn - Follow prograde next.
  WHEN SHIP:FACING:VECTOR:NORMALIZED:Z - SHIP:VELOCITY:SURFACE:NORMALIZED:Z <= 0 THEN { //might need to change this condition
   LOCK Autopilot to SHIP:VELOCITY:SURFACE. //SHIP:VELOCITY:SURFACE or SHIP:SRFPROGRADE?
   PRINT "Begin Gravity Turn" at (0,10).   
   WHEN SHIP:ALTITUDE > 75000 THEN { //At 75km, start program to control pitch based on current rocket path - currently monitors vertical velocity.
     PRINT "Initiate Closed-Loop Steering" at (0,10).
     SET PID TO PIDLOOP(Kp,Ki,Kd). // do once (Kp, Ki, Kd, Minoutput, Maxoutput) - Bounces horribly between min and max - pitch corrections too extreme - needs tuning and lower response time (responds too fast) - pitch bouncy between set AP?  Needs deadzone?
	 SET PID:SETPOINT to 0. //do once
     SET Pitch1 to VANG(SHIP:FACING:VECTOR, VXCL(UP:VECTOR,STEERINGMANAGER:TARGET:VECTOR)). //initialize PID?
	 WHEN true THEN { //<= loops until PE > 0.
	   PRINT "Pitch: " + Pitch1 at (0,4). //This is quite large.  Might be a bad derivation.
	   PRINT "PID Input:" + PID:INPUT at (0,5).  //Apoapsis
	   PRINT "PID Output/Pitch Correction:" + PID:OUTPUT at (0,6). // Error
	   PRINT "Error: " + PID:ERROR at (0,7).
	   PRINT PID:SETPOINT - SHIP:VERTICALSPEED at (0,8).
	   SET dPitch to PID:UPDATE(TIME:SECONDS, SHIP:VERTICALSPEED).
	   IF Outboard:FUELFLOW > 0 AND (MSIC:MASS - MSIC:DRYMASS)/(Outboard:FUELFLOW * 5) < 2 AND J2S:FUELFLOW = 0 { //Hold pitch for MS-IC/MS-II staging.
	     SET Autopilot TO HEADING(90,Pitch1).
	   }
	   ELSE IF Pitch1 > 15 { //Transition from gravity turn or oversteer past maximum.
	     SET Pitch1 to VANG(SHIP:FACING:VECTOR, VXCL(UP:VECTOR,STEERINGMANAGER:TARGET:VECTOR)).
		 PRINT "Pitching Over      " at (0,3). //change this text?
		 SET Autopilot to HEADING(90,14.9).
	   }
	   ELSE IF Pitch1 < 15 AND Pitch1 > 0 { //min and max pitch
	     PRINT "Guidance Converging       " at (0,3).
	     SET Pitch1 to Pitch1 + dPitch.
		 SET Autopilot TO HEADING(90,Pitch1).
	   }
       ELSE IF SHIP:ORBIT:PERIAPSIS > 0 { //This sets pitch to zero for final orbital insertion to make orbit as circular as possible.
	     PRINT "Terminal Guidance      " at (0,3).
         LOCK Autopilot to HEADING(90,0). //Terminal guidance for PE > 0.
		 RETURN false. //Kill steering loop.
	   }
	   ELSE { //oversteer past minimum
	     PRINT "test" at (0,3).
	     SET Pitch1 to VANG(SHIP:FACING:VECTOR, VXCL(UP:VECTOR,STEERINGMANAGER:TARGET:VECTOR)).
	     SET Autopilot to HEADING(90,0). //how to pitch gradually from initial pitch to 15 - how is this getting triggered after PE > 0?
	   }
	   IF SHIP:VERTICALSPEED < 150{
	     PRINT "Logging" at (0,11).
	     //LOG MISSIONTIME + "," + (PID:SETPOINT - SHIP:VERTICALSPEED) + "," + dPitch TO Pitch_VVert_Log.txt.
       }
       RETURN true.	   
	 }  
   }  
  }
}

//Staging control.
//Countdown here?

//F-1A Ignition
UNTIL (Outboard:THRUST/Outboard:MAXTHRUST) > 0.88 {
  IF(Outboard:MAXTHRUST > 0) {  //Prevent NAN
    //PRINT STEERINGMANAGER:MAXSTOPPINGTIME at (0,4).
    LaunchDisplay(0,2,Outboard:THRUST/Outboard:MAXTHRUST,0).
  }
  
  //WAIT 0.01.
}

STAGE.  //SRB Ignition and Liftoff
CLEARSCREEN.

//Maybe countdown and abort mode display.

//WAIT 0.01.

//Display loop could continue on with a PRESERVE command after throttleback?
UNTIL MISSIONTIME > 24 { //originally 25
  IF(SRB:MAXTHRUST > 0 AND SRB:THRUST > 0) { //Prevent NAN
    //PRINT VANG(SHIP:FACING:VECTOR, VXCL(UP:VECTOR,STEERINGMANAGER:TARGET:VECTOR)) at (0,4).
    //PRINT "Facing-vel srf Angle: " + VANG(SHIP:FACING:VECTOR, SHIP:VELOCITY:SURFACE) + "  " at (0,4).
	//PRINT "Facing Z - Vel Srf Z (Normalized): " + (SHIP:FACING:VECTOR:NORMALIZED:Z - SHIP:VELOCITY:SURFACE:NORMALIZED:Z) at (0,5).
	//PRINT "Facing-target Angle: " + VANG(SHIP:FACING:VECTOR, STEERINGMANAGER:TARGET:VECTOR) + "  " at (0,6).
    //PRINT "Facing - Target: " + (SHIP:FACING:VECTOR:Z - STEERINGMANAGER:TARGET:VECTOR:Z) + "  " at (0,7).
    //PRINT "Facing Z: " + SHIP:FACING:VECTOR:Z + "  "at (0,8).
    //PRINT "Vel Srf Z: " + SHIP:VELOCITY:SURFACE:Z + "  "at (0,9).
    LaunchDisplay(1,2,Outboard:THRUST/Outboard:MAXTHRUST,SRB:THRUST/SRB:MAXTHRUST).
  }
  //WAIT 0.01.
}

CLEARSCREEN.

LOCK THROTTLE to 0.01. //F-1A throttle to 60% for max Q

//check dyn pressure change
//if ddyn < -0.004kPa/0.01s or so, throttle to 85% (was -0.04kPa/0.1s)

UNTIL ddyn <= -0.01 { //originally 0.004
  LaunchDisplay(2,0,Outboard:THRUST/Outboard:MAXTHRUST,SRB:Thrust/SRB:MAXTHRUST).
  SET ddyn TO (SHIP:Q*constant:ATMtokPa) - dynzero. //units are kPa <- can be lock statement
  SET dynzero TO (SHIP:Q*constant:ATMtokPa). //<- these can be LOCK statements
  WAIT 0.01. //change to 0.1? <- can remove this when using lock and dividing by time.
}

LOCK THROTTLE to 0.63. //F-1A throttle to 85%
SET g TO EARTH:MU/EARTH:RADIUS^2.
LOCK acc TO SHIP:SENSORS:ACC - SHIP:SENSORS:GRAV.
LOCK Gforce TO acc:MAG/g.

WHEN Gforce > 4 THEN LOCK THROTTLE TO 0.01. //First G force moderation throttleback (60%).

CLEARSCREEN.

//4+Gs before SRB tail-off.

//Stage SRBs and throttle to 100% when SRB thrust < 10%
UNTIL SRB:THRUST/SRB:MAXTHRUST < .1 {
  LaunchDisplay(3,1,Outboard:THRUST/Outboard:MAXTHRUST,SRB:Thrust/SRB:MAXTHRUST). //Throttle setting should read "60%" for first throttleback.
}

STAGE. //SRB jettison

LOCK THROTTLE to 1.0. //F-1A throttle to 100%

//Center engine shutdown at 26s before MS-IC burnout (G >= 3.8g)

CLEARSCREEN.

UNTIL (MSIC:MASS - MSIC:DRYMASS)/(Outboard:FUELFLOW * 5) < 26 {
  LaunchDisplay(4,2,Outboard:THRUST/Outboard:MAXTHRUST).
  //WAIT 0.01.
}

Inboard:SHUTDOWN. //Inboard cut-off.

CLEARSCREEN.

WHEN MISSIONTIME > 160 THEN LOCK THROTTLE TO 0.63. //Second G force moderation throttleback (85%).

//Remainder of MS-IC Flight
UNTIL Outboard:FLAMEOUT = TRUE {
  IF Outboard:MAXTHRUST > 0 {//Prevent NAN
    LaunchDisplay(5,2,Outboard:Thrust/Outboard:MAXTHRUST). //Should read "85%" when throttleback occurs.
  }
}

//Main Engine Cut-Off
CLEARSCREEN.
LaunchDisplay(6,3,0).
LOCK THROTTLE TO 1.
WAIT 1.


CLEARSCREEN.
STAGE. //MS-IC Staging.
LaunchDisplay(7,3,0).
WAIT 3.

CLEARSCREEN.


STAGE. //MS-II Ignition.
SET t0 to TIME:SECONDS.

UNTIL TIME:SECONDS - t0 > 30 {
  LaunchDisplay(8,2,J2S:THRUST/J2S:MAXTHRUST).
} 

CLEARSCREEN.


STAGE. //Skirt seperation
Set t0 to TIME:SECONDS.

UNTIL TIME:SECONDS - t0 > 6 {
  LaunchDisplay(9,2,J2S:THRUST/J2S:MAXTHRUST).
}

CLEARSCREEN.

AG27 on. //LES Tower jettison <- this event will be moved in final code.
UNTIL SHIP:ORBIT:PERIAPSIS >= 170000 { //set to be higher than set apoapsis <- could set this to AP when PE = 0 to attempt circularization.
  LaunchDisplay(10,2,J2S:THRUST/J2S:MAXTHRUST).
}

//SECO - Orbit insertion.
CLEARSCREEN.
LOCK THROTTLE to 0.

PRINT "Secondary Engine Cut-Off" at (0,2).
PRINT "Go for Orbit" at (0,3).

//Keep code running until SECO (Periapsis > 200 km or 250 km?)

SET SHIP:CONTROL:PILOTMAINTHROTTLE to 0. //Current final orbit 234 km x 201 km

Apoapsis, periapsis, and final vertical velocity for new throttling profile.  The target periapsis was lowered to 170 km from 200 km as stated above.

Kp Apoapsis (km) Periapsis (km) Vertical Velocity (m/s)
0.0015 231.549 170.595 31.96
0.0025 218.669 170.653 25.10
0.0035 215.675 170.498 21.93
0.0045 220.858 170.212 19.86
0.0055 242.154 170.099 18.51

I noticed the final apoapsis was still lowest around Kp = 0.0035, so I varied Kp more finely starting at Kp = 0.0035 and lowering it by 0.0001.

Kp Apoapsis (km) Periapsis (km) Vertical Velocity (m/s)
0.0035 215.675 170.498 21.93
0.0034 215.158 170.443 22.09
0.0033 211.745 170.644 22.21
0.0032 215.783 170.601 22.80

So apoapsis is a minimum around Kp = 0.0033.  I can treat this as the ultimate gain Ku and use the PD tuning technique given in the kOS manual (Kp = 0.8 Ku, Kd = KpTu/8), I get a Kp of 0.00264.  I assume different values for Tu since I can't really get that experimentally for this PID tuner, starting at Tu = 30s and varying it by 10 seconds until I get convergent behavior with v_vert.

Ku = 0.0033 Kp = 0.00264      
Tu (s) Kd Apopsis (km) Periapsis (km) Vertical Velocity (m/s)
20 0.0066 194.638 171.517 13.25
30 0.0099 189.381 171.911 8.479
40 0.0132 187.113 172.334 4.598
50 0.0165 186.456 172.419 2.231

So, the higher Kd goes, the closer vertical velocity gets to zero.  I don't know if it actually reaches zero or just asymptotes to it, but I can find out later.  I just feel that higher Kd values might mean that the vertical velocity PID loop is approaching zero faster or sooner in time, and thus there might be a critical Kd where vertical velocity would overshoot or undershoot.

I feel though that setting Kp to 0.00264 and Kd to 0.0165 will be good enough for this autopilot.  I might start work on the heading to inclination conversion, which is the final difficult part of this code..

Link to comment
Share on other sites

This isn't good.  I'm starting to get C++ runtime errors and crashes quite frequently now during vessel loadings, usually after I fly the vessel once.  This is after putting the propulsion stage in orbit to test rendezvous.

Maybe I'm running too many mods or should reduce memory the memory usage of other programs?  This doesn't seem like a typical memory issue caused by 32-bit KSP (and I run 64-bit for RSS/RO).

Also, been having a hard time getting a relation between initial launch heading and final orbital inclination.  Dunno if i'm overthinking the problem, but I don't feel it shouldn't be that hard to find a relation.  I've tried using differentials and some linear algebra, but I keep getting stuck in the math and making quite a few careless errors.

Furthermore, starting on the 27th, I won't have the free time I had before due to some week-long evaluations I'll be going to for the next four weeks after the 27th.  I'll have weekends off, though, and I might have afternoons, but I'm not sure how much work I can get done.  I'd like to get this code ready before then, but the crashing and other bugs are slowing me down.

Edited by Nittany Tiger
Link to comment
Share on other sites

So this heading to inclination problem turned out to be much harder than I anticipated.  I had to start the problem from scratch a few times before finally finding a way to solve it.  To clarify what problem I'm talking about, I wanted to know what your final orbital inclination would be if you launched at a certain angle from North in the launch site's frame of reference.

To solve it, I did something akin to what @BevoLJ did in thinking of the problem in terms of changing orbits.  First, though, I had to show that for a 90-degree launch heading, the final orbit would be inclined at the launch site's latitude.  I had done this already to solve a special case of the general problem as a way to help me find the general solution to the heading to inclination problem.

Here's my work on the special case to prove that the initial inclination = launch site latitude.

http://www.texpaste.com/n/m89r69uq

For the general case, I thought of what kind of velocity change it would take to change the inclination of an orbit.  I let the initial orbit be the orbit for the 90 degree heading case, and the final orbit be the orbit I want.  Then I can use the burn vector, add it to the initial velocity of the rocket at the launch site, which is zero plus the velocity imparted on the rocket by the rotation of the Earth, and then find the angle between this new surface velocity vector and the north direction relative to the launch site.

Took me a couple of days of work, but I had the general equation.  I tested it with my autopilot programs and it appears to work.  My work notes are here:

http://www.texpaste.com/n/d6am1mfq

And the final equation that gives me the heading I want to launch at for a target inclination is:

djCGumy.png

Big equation, but it works.

So, this means that my autopilot code is almost complete and now performs every task I want it to (with the exception of hitting a target apoapsis).  At this point, it's just minor code clean-up and final tweaks, and then I can move on to the mission itself.

//Saturn VB Autopilot program
//Ctrl + C to kill?

RUNPATH("AresLaunchDisplay.ks").

//Pass in target inclination and convert to heading.
//Need to figure out initial heading to match desired inclination.
//parameter targetinclination is LATITUDE.
parameter initialheading is 90.
IF HASTARGET = TRUE {
  SET initialheading to ARCCOS((2*7616*sin(LATITUDE)*sin((TARGET:ORBIT:INCLINATION - LATITUDE)/2)*cos((TARGET:ORBIT:INCLINATION + LATITUDE)/2))/SQRT(4*(7616.6)^2*(sin((TARGET:ORBIT:INCLINATION - LATITUDE)/2))^2-(4*7616.6*465.1*cos(LATITUDE)*sin((TARGET:ORBIT:INCLINATION + LATITUDE)/2)*sin((TARGET:ORBIT:INCLINATION - LATITUDE)/2)) + (465.1*cos(LATITUDE)^2))). //Most confident formula for setting initial heading to hit a target inclination - still may not work due to assumptions with velocities and translating normal vector from orbit to ground. 
} 


SET ddyn to 0.
SET dynzero to 0.

//If variables are lists, can I accees each element in loops below and make code more efficient?
SET Inboard to SHIP:PARTSTAGGED("F1AInboard")[0].
SET Outboard to SHIP:PARTSTAGGED("F1AOutboard1")[0].
SET J2S to SHIP:PARTSTAGGED("J2S")[0].
SET SRB to SHIP:PARTSTAGGED("SRB1")[0].
SET MSIC to SHIP:PARTSTAGGED("MS-IC")[0].

CLEARSCREEN. //in case we need this

//Display event, throttle setting, F-1A thrust %, and SRB thrust %.
//Lock steering to a variable to make it less intensive to run?
LOCK STEERING to Autopilot.
LOCK Autopilot to "Kill".
LOCK THROTTLE to 1.0.

//Temp - steering debug - delete after use
//SET STEERINGMANAGER:SHOWSTEERINGSTATS to TRUE.
SET STEERINGMANAGER:SHOWFACINGVECTORS to TRUE.
SET STEERINGMANAGER:SHOWANGULARVECTORS to TRUE.

SET STEERINGMANAGER:MAXSTOPPINGTIME to 0.7. //default value 2
STAGE. //F-1A ignition

Set Kppitch to 0.00264. //Ku = 0.0033?  
Set Kipitch to 0.
Set Kdpitch to 0.0198. //Last Kdpitch: 0.00132

Set Kpinc to 0.001.
Set Kiinc to 0.
Set Kdinc to 0.

//Tuning Inclination PID.
LOG "Inclination PID Tuning" TO Inclination_Log.txt.
LOG "Kp:" + Kpinc + ",Ki:" + Kiinc + ",Kd:" + Kdinc TO Inclination_Log.txt.
LOG "t,Inclination Deviation:" TO Inclination_Log.txt.

//Ultimate goal of steering program is to set rocket into pre-programmed circular orbit of 200 km - 250 km.
//Pitch by x degrees, then follow prograde until rocket reaches certain altitude.
//Finally, manage pitch to put Ares in circular orbit.
//In launches using manual steering, Ares ends gravity turn between SRB sep and MS-IC burnout.

//Adjust heading to meet propulsion stack inclination (or desired inclination).  Could have this able to be set as input prior to launch.

//At v(sfc) = 50 m/s, pitch over a bit to initiate gravity turn.
//then hold prograde for gravity turn. (angle between v and a zero.)

//Pitch and roll manuever.  Correct initial pitch is trial and error right now.
//Could the gravity turn be better programmed as a diff eq (predictive equation)?

//Print that gravity turn is in progress - Integrate with LaunchDisplay function?

//LOCK dHeading TO PID1:UPDATE(TIME:SECONDS,SHIP:ORBIT:INCLINATION).
//LOCK Heading1 TO Heading1 + PID1:UPDATE(TIME:SECONDS,SHIP:ORBIT:INCLINATION).
WHEN SHIP:VELOCITY:SURFACE:MAG >= 50 THEN {
  //Pitch then roll for inclination. - smooth out move to pitch?
  LOCK Autopilot to HEADING(initialheading,80). //175 km AP at SRB sep.  SRB sep at 70 km. -  Last setting,80, then 78 degrees pitch, then 83
  PRINT initialheading at (0,4).
  IF ROUND(VANG(SHIP:FACING:VECTOR, VXCL(UP:VECTOR,STEERINGMANAGER:TARGET:VECTOR))) = 90 { //Sometimes, the rocket pointing straight up causes next when trigger to be true, so this line prevents a vertical launch from triggering the gravity turn code.
    RETURN true.
  }
  //Gravity turn - Follow prograde next.
  WHEN SHIP:FACING:VECTOR:NORMALIZED:Z - SHIP:VELOCITY:SURFACE:NORMALIZED:Z <= 0 AND VANG(UP:VECTOR, SHIP:VELOCITY:SURFACE) < 80 THEN { //triggers too early for some inclinations.
   LOCK Autopilot to SHIP:VELOCITY:SURFACE.
   PRINT "Begin Gravity Turn" at (0,10).
   WHEN SHIP:ALTITUDE > 75000 THEN { //At 75km, start program to control pitch based on current rocket path - currently monitors vertical velocity.
     PRINT "Initiate Closed-Loop Steering" at (0,10).
	 SET PID1 TO PIDLOOP(Kpinc, Kiinc, Kdinc). //Inclination guidance.
     SET PID2 TO PIDLOOP(Kppitch,Kipitch,Kdpitch). // do once (Kppitch, Kipitch, Kdpitch, Minoutput, Maxoutput) - Bounces horribly between min and max - pitch corrections too extreme - needs tuning and lower response time (responds too fast) - pitch bouncy between set AP?  Needs deadzone?
	 IF HASTARGET = TRUE {
       SET PID1:SETPOINT to TARGET:ORBIT:INCLINATION. 
     }
     ELSE {
       SET PID1:SETPOINT to 90. //change this to proper formula for inclination => heading.
     }
	 SET PID2:SETPOINT to 0. //do once
     SET Pitch1 to VANG(SHIP:FACING:VECTOR, VXCL(UP:VECTOR,SHIP:FACING:VECTOR)). //Doesn't represent pitch - initialize PID?
	 SET Heading1 TO SHIP:HEADING.
	 WHEN true THEN { //<= loops until PE > 0.
	   //PRINT "Pitch: " + VANG(SHIP:FACING:VECTOR, VXCL(UP:VECTOR,SHIP:FACING:VECTOR)) at (0,6). //positive even when pitch is below horizon.
	   //PRINT "Pitch1 (Commanded Pitch): " + Pitch1 at (0,7).
	   //PRINT "PID Input:" + PID2:INPUT at (0,5).  //Apoapsis
	   //PRINT "PID Output/Pitch Correction:" + PID2:OUTPUT at (0,6). // Error
	   //PRINT "Error: " + PID2:ERROR at (0,7).
	   //PRINT PID2:SETPOINT - SHIP:VERTICALSPEED at (0,8).
	   PRINT "INPUT:" + PID1:INPUT at (0,5).
	   PRINT "OUTPUT:" + PID1:OUTPUT at (0,6).
	   PRINT "ERROR:" + PID1:ERROR at (0,7).
	   PRINT "Heading1:" + Heading1 at (0,8).
	   PRINT "Heading:" + SHIP:HEADING + "   "at (0,9).
	   SET dPitch to PID2:UPDATE(TIME:SECONDS, SHIP:VERTICALSPEED).
	   SET dHeading to PID1:UPDATE(TIME:SECONDS,SHIP:ORBIT:INCLINATION).
	   IF Outboard:FUELFLOW > 0 AND (MSIC:MASS - MSIC:DRYMASS)/(Outboard:FUELFLOW * 5) < 2 AND J2S:FUELFLOW = 0 { //Hold pitch for MS-IC/MS-II staging.
	     PRINT "Test." at (0,5).
	     //SET Autopilot TO "Kill".
		 SET Pitch1 to 0.
		 SET Heading1 to HEADING.
	   }
	   //Pitch control.
	   ELSE IF Pitch1 >= 15 OR (VANG(SHIP:FACING:VECTOR, VXCL(UP:VECTOR,SHIP:FACING:VECTOR)) >= 15 AND SHIP:FACING:VECTOR:Y >= 0) { //Transition from gravity turn or oversteer past maximum.
	     SET Pitch1 to 14.9.
		 PRINT "Pitching Over                " at (0,3). //change this text?
	   }
	   ELSE IF (Pitch1 < 15 AND Pitch1 >= 0) AND SHIP:FACING:VECTOR:Y >= 0 { //min and max pitch
	     PRINT "Pitch Guidance Converging       " at (0,3).
		 //If statements needed to limit Pitch1 variable to between 0 and 15 degrees within this if statement.
	     SET Pitch1 to Pitch1 + dPitch. 	 
	   }
	   ELSE { //oversteer past minimum //fine after stage 2 ignition?
	     PRINT "Oversteer.                 " at (0,3).
	     SET Pitch1 to 0.1.
	   }
	   //Heading Control.
	   //SET Heading1 to 90. //temp.
	   IF (HEADING > 10 + initialheading) OR (Heading1 > 10 + initialheading) {
	     PRINT "Oversteer - Heading.    " at (0,4).
	     SET Heading1 TO initialheading + 10.
       }		 
	   ELSE IF HEADING <= (10 + initialheading) AND HEADING >= (initialheading - 10) { //heading limits if needed.
	     PRINT "Heading Guidance Converging.   " at (0,4).
	     SET Heading1 to Heading1 + dHeading.  //Inclination correction
	   }
	   ELSE IF (HEADING < initialheading - 10) OR (Heading1 < initialheading - 10) { 
	     PRINT "Understeer - Heading.     " at (0,4).
	     SET Heading1 TO initialheading - 10.
	   }
	   IF SHIP:VERTICALSPEED < 150 { //temp loop.
	     PRINT "Logging" at (0,11).
	     //LOG MISSIONTIME + "," + (PID2:SETPOINT - SHIP:VERTICALSPEED) + "," + dPitch TO Pitch_VVert_Log.txt.
       }
	   IF SHIP:ORBIT:PERIAPSIS > 0 { //This sets pitch to zero for final orbital insertion to make orbit as circular as possible.
	     PRINT "Terminal Guidance               " at (0,3).
		 SET Pitch1 to 0. //Terminal guidance for PE > 0.
		 RETURN false. //Kill steering loop.
	   }
	   SET Autopilot TO HEADING(Heading1,Pitch1). //SET, don't LOCK.
	   //PRINT SHIP:FACING:VECTOR at (0,5).
	   //LOG MISSIONTIME + "," + (PID1:SETPOINT - SHIP:ORBIT:INCLINATION) TO Inclination_Log.txt.
       RETURN true.	   
	 }  
   }  
  }
}

//Staging control.
//Countdown here?

//F-1A Ignition
UNTIL (Outboard:THRUST/Outboard:MAXTHRUST) > 0.88 {
  IF(Outboard:MAXTHRUST > 0) {  //Prevent NAN
    //PRINT STEERINGMANAGER:MAXSTOPPINGTIME at (0,4).
    LaunchDisplay(0,2,Outboard:THRUST/Outboard:MAXTHRUST,0).
  }
  
  //WAIT 0.01.
}

STAGE.  //SRB Ignition and Liftoff
CLEARSCREEN.

//Maybe countdown and abort mode display.

//WAIT 0.01.

//Display loop could continue on with a PRESERVE command after throttleback?
UNTIL MISSIONTIME > 24 { //originally 25
  IF(SRB:MAXTHRUST > 0 AND SRB:THRUST > 0) { //Prevent NAN
    //PRINT VANG(SHIP:FACING:VECTOR, VXCL(UP:VECTOR,STEERINGMANAGER:TARGET:VECTOR)) at (0,4).
    //PRINT "Facing-vel srf Angle: " + VANG(SHIP:FACING:VECTOR, SHIP:VELOCITY:SURFACE) + "  " at (0,4).
	//PRINT "Facing Z - Vel Srf Z (Normalized): " + (SHIP:FACING:VECTOR:NORMALIZED:Z - SHIP:VELOCITY:SURFACE:NORMALIZED:Z) at (0,5).
	//PRINT "Facing-target Angle: " + VANG(SHIP:FACING:VECTOR, STEERINGMANAGER:TARGET:VECTOR) + "  " at (0,6).
    //PRINT "Facing - Target: " + (SHIP:FACING:VECTOR:Z - STEERINGMANAGER:TARGET:VECTOR:Z) + "  " at (0,7).
    //PRINT "Facing Z: " + SHIP:FACING:VECTOR:Z + "  "at (0,8).
    //PRINT "Vel Srf Z: " + SHIP:VELOCITY:SURFACE:Z + "  "at (0,9).
    LaunchDisplay(1,2,Outboard:THRUST/Outboard:MAXTHRUST,SRB:THRUST/SRB:MAXTHRUST).
  }
  //WAIT 0.01.
}

CLEARSCREEN.

LOCK THROTTLE to 0.01. //F-1A throttle to 60% for max Q

//check dyn pressure change
//if ddyn < -0.004kPa/0.01s or so, throttle to 85% (was -0.04kPa/0.1s)

UNTIL ddyn <= -0.01 { //originally 0.004
  LaunchDisplay(2,0,Outboard:THRUST/Outboard:MAXTHRUST,SRB:Thrust/SRB:MAXTHRUST).
  SET ddyn TO (SHIP:Q*constant:ATMtokPa) - dynzero. //units are kPa <- can be lock statement
  SET dynzero TO (SHIP:Q*constant:ATMtokPa). //<- these can be LOCK statements
  WAIT 0.01. //change to 0.1? <- can remove this when using lock and dividing by time.
}

LOCK THROTTLE to 0.63. //F-1A throttle to 85%
SET g TO EARTH:MU/EARTH:RADIUS^2.
LOCAL LOCK acc TO SHIP:SENSORS:ACC - SHIP:SENSORS:GRAV. //if grav code doesn't work, set these to global.
LOCAL LOCK Gforce TO acc:MAG/g.

WHEN Gforce > 4 THEN LOCK THROTTLE TO 0.01. //First G force moderation throttleback (60%).

CLEARSCREEN.

//4+Gs before SRB tail-off.

//Stage SRBs and throttle to 100% when SRB thrust < 10% (change to 9%)?
UNTIL SRB:THRUST/SRB:MAXTHRUST < .1 {
  LaunchDisplay(3,1,Outboard:THRUST/Outboard:MAXTHRUST,SRB:Thrust/SRB:MAXTHRUST). //Throttle setting should read "60%" for first throttleback.
}

STAGE. //SRB jettison

LOCK THROTTLE to 1.0. //F-1A throttle to 100%

//Center engine shutdown at 26s before MS-IC burnout (G >= 3.8g)

CLEARSCREEN.

UNTIL (MSIC:MASS - MSIC:DRYMASS)/(Outboard:FUELFLOW * 5) < 26 {
  LaunchDisplay(4,2,Outboard:THRUST/Outboard:MAXTHRUST).
  //WAIT 0.01.
}

Inboard:SHUTDOWN. //Inboard cut-off.

CLEARSCREEN.

WHEN MISSIONTIME > 160 THEN LOCK THROTTLE TO 0.63. //Second G force moderation throttleback (85%).

//Remainder of MS-IC Flight
UNTIL Outboard:FLAMEOUT = TRUE {
  IF Outboard:MAXTHRUST > 0 {//Prevent NAN
    LaunchDisplay(5,2,Outboard:Thrust/Outboard:MAXTHRUST). //Should read "85%" when throttleback occurs.
  }
}

//Main Engine Cut-Off
CLEARSCREEN.
LaunchDisplay(6,3,0).
LOCK THROTTLE TO 1.
WAIT 1.


CLEARSCREEN.
STAGE. //MS-IC Staging.
LaunchDisplay(7,3,0).
WAIT 3.

CLEARSCREEN.


STAGE. //MS-II Ignition.
SET t0 to TIME:SECONDS.

UNTIL TIME:SECONDS - t0 > 30 {
  LaunchDisplay(8,2,J2S:THRUST/J2S:MAXTHRUST).
} 

CLEARSCREEN.


STAGE. //Skirt seperation
Set t0 to TIME:SECONDS.

UNTIL TIME:SECONDS - t0 > 6 {
  LaunchDisplay(9,2,J2S:THRUST/J2S:MAXTHRUST).
}

CLEARSCREEN.

AG27 on. //LES Tower jettison <- this event will be moved in final code.

SET v_orb to 1000000.
WHEN SHIP:ORBIT:PERIAPSIS >= 0 THEN SET v_orb to SQRT(EARTH:MU/(SHIP:ORBIT:APOAPSIS + EARTH:RADIUS)). //Could set to altitude.

UNTIL SHIP:VELOCITY:ORBIT:MAG >= v_orb { //SECO when v_orb for circular orbit at alt = periapsis reached.
  LaunchDisplay(10,2,J2S:THRUST/J2S:MAXTHRUST).
}

//SECO - Orbit insertion.
CLEARSCREEN.
LOCK THROTTLE to 0.

PRINT "Secondary Engine Cut-Off" at (0,3).
PRINT "Go for Orbit" at (0,4).

//Keep code running until SECO (Periapsis > 200 km or 250 km?)

SET SHIP:CONTROL:PILOTMAINTHROTTLE to 0. //Current final orbit 234 km x 201 km


EDIT: I do need to mention a strange bug where after 75km, my HEADING variable is somehow floating around zero despite my actual heading being far from zero.  Have yet to track this bug down.

Edited by Nittany Tiger
Link to comment
Share on other sites

  • 3 weeks later...

Time for an update.

Spent some time tuning the inclination PID loop.  Got it to where it centers itself to the proper inclination with a 0.0002 degree error or less.  I possibly could tune it somewhat better, but it's tight enough to where I think it's good.

Some graphs used in the tuning.  Apologies for the sloppy labels, but I Google Sheets is a pain to work with when you upload a lot of data to it.  It also doesn't allow for label editing to my knowledge.

KLNEFC7.png

This is the recorded inclination difference between about 160 seconds and orbital insertion.  I decided to use the behavior between about 220 seconds and 363 seconds for PID tuning.

EldHUGy.png

Amplitude changes are as follows:

Kp Average Amplitude Change (deg x 10^-4) Average Period (s)
1.5 -9.21 N/A
2.5 2.18 29 (Tu)
2.5 -4.82 N/A

From this and the PD tuning method in the kOS documentation, I use Kp = 1.6 and Kd = 5.8, and those values seem to work fine.

So now all of the autopilot functions are programmed in and work in a satisfactory way.  I do feel that maybe I should wait to engage the heading autopilot after MS-IC sep because the MS-IC has a lot of torque and engaging the heading autopilot seems to make the rocket steer in an odd way (turns left, and then down).

Now I'm looking at one of the minor details of the Saturn-VB launch sequence: abort modes.  I'm curious how aborts would work with this rocket.  I would assume some of the abort modes are similar to the Apollo/Saturn V with the obvious lack of S-IVB to COI capability and mode III (S-IVB to Orbit) due to a lack of an S-IVB or equivalent stage.  Some browsing on Wikipedia and a document I found gave me an idea of what abort modes trigger when during the Saturn VB launch, so I assumed that the mode 1 aborts for Ares would be the same as Apollo.  This means that mode II (CSM abort) is actually reached before MS-IC sep but after SRB sep, and I adjusted the code to fire the LES tower at around 80 km height.  The only abort mode I haven't nailed down is the mode III abort for the Saturn VB, which is the same as mode IV (CSM to orbit) on Apollo.

The CSM has 3081 m/s of dV according to Mechjeb, so I would figure mode III would happen when there is less than 2581 m/s remaining before orbital insertion.  This gives the CSM 500 m/s of dV to work with and deorbit with, which I feel is more than enough.

Abort Mode MET (s) Altitude (km)
Ia (LES + Pitch Motor) 0 - 22 0 - 3
Ib (LES + Canards) 22 - 80 (1:20) 3 - 30.5
Ic (LES + RCS) 80 - 124 (2:04) 30.5 - 80
II (CSM) 124 (2:04) - Unk 80+
III (CSM to Orbit) Unk Unk

I promise to get this table filled out soon.

I did consider two possible alternate abort options, one being an early MS-IC sep and the other using the OMM to boost the stack to orbit.  Both of these would save the mission as it would not discard the AMM and MEM.  Unfortunately the windows for both possible aborts might be too narrow, especially for the OMM to orbit option since the OMM only has 283 m/s of dV.  The MS-II usually has about 400 m/s left after SECO during a nominal launch, so an early MS-IC sep would need enough dV remaining in the MS-II and OMM to make orbit, also resulting in a narrow window in which the abort is possible, albeit less narrow than an OMM to orbit situation.  Nonetheless, I don't feel these alternate aborts have enough of a time window to be useful, though I may investigate the early MS-IC sep option a bit more.

In conclusion, some minor tweaks to the code and terminal display changes are needed to consider the autopilot code complete.  I'm not going to code in automatic aborts but I will display the abort mode.  In fact, I have all but mode III coded in.  I figure I could do automatic aborts later.  What's left after this I would assume be just some minor texture replacements, but those are optional, and then the first full flight of Ares (finally).

Edited by Nittany Tiger
Added values to table.
Link to comment
Share on other sites

  • 3 weeks later...

Small update.

I worked out most of the bugs for the terminal display for the autopilot. Also changed when the heading convergence starts, but I'm still seeing odd behavior in the steering when heading guidance engages.  My best guess is that the steering program might be trying to prevent gimbal lock since I've read up on gimbal lock, and odd rotational behavior can come about in 3D programs if you try to rotate an object in a way that causes gimbal lock.  I figure a clever workaround is in order.

Pitch/roll program issues will be the absolute last part on this program I work on.  After that, I'm done with the program and I'll move onto texture replacement, and then finally fly this mission.  I know I keep mentioning that I hope to fly this mission soon, but life is unpredictable, and with me trying to get a job, I'm finding myself with less free time to work on this project.  Nonetheless, I'm dedicated to completing it and producing a few flights of Ares with a hopeful video.

I actually want to produce some charts showing some launch data along with other data.  For some really, I'm really invested in detailed analysis of this rocket and mission, so maybe I'll post a graph similar to the one below for the launch of the Ares, and I may produce a timetable for the whole mission.  I might also investigate abort modes for other aspects of the mission such as the trans-Cytherian injection (fancy name for burn to Venus), coasts to Venus and Mars, Mars insertion burn, and Martian landing attempt.

Link to comment
Share on other sites

After months of work, the autopilot code is more or less complete.  Still need to debug the dV calculation for Mode III abort, but it's at a point that the code flies the rocket into orbit at a set inclination.

Dunno if I would have done this if I had known it would have taken me so long to complete, but it was also a very fun challenge.

//Saturn VB Autopilot program - Might have memory leak issues or need memory optimization.

RUNPATH("AresLaunchDisplay.ks").

//Pass in target inclination and convert to heading.
parameter targetinclination is LATITUDE. //- preferred parameter
parameter targetapoapsis is 200.
IF HASTARGET = TRUE {
  SET initialheading to ARCCOS((2*7616*sin(LATITUDE)*sin((TARGET:ORBIT:INCLINATION - LATITUDE)/2)*cos((TARGET:ORBIT:INCLINATION + LATITUDE)/2))/SQRT(4*(7616.6)^2*(sin((TARGET:ORBIT:INCLINATION - LATITUDE)/2))^2-(4*7616.6*465.1*cos(LATITUDE)*sin((TARGET:ORBIT:INCLINATION + LATITUDE)/2)*sin((TARGET:ORBIT:INCLINATION - LATITUDE)/2)) + (465.1*cos(LATITUDE)^2))). //Ares Propulsion Stack is in 500km orbit, so target orbital velocity is set to 500 km.  More accurate to set to expected orbital insertion velocity?
} 
ELSE {
  SET targetvelocity to SQRT(EARTH:MU/targetapoapsis).
  SET initialheading to ARCCOS((2*targetvelocity*sin(LATITUDE)*sin((targetinclination - LATITUDE)/2)*cos((targetinclination + LATITUDE)/2))/SQRT(4*(targetvelocity)^2*(sin((targetinclination - LATITUDE)/2))^2-(4*targetvelocity*465.1*cos(LATITUDE)*sin((targetinclination + LATITUDE)/2)*sin((targetinclination - LATITUDE)/2)) + (465.1*cos(LATITUDE)^2))).
}

SET Inboard to SHIP:PARTSTAGGED("F1AInboard")[0].
SET Outboard to SHIP:PARTSTAGGED("F1AOutboard1")[0].
SET J2S to SHIP:PARTSTAGGED("J2S")[0].
SET SRB to SHIP:PARTSTAGGED("SRB1")[0].
SET MSIC to SHIP:PARTSTAGGED("MS-IC")[0].
SET MSII to SHIP:PARTSTAGGED("MS-II")[0].

CLEARSCREEN.

LOCK STEERING to Autopilot.
LOCK Autopilot to "Kill".
LOCK THROTTLE to 1.0.

SET STEERINGMANAGER:MAXSTOPPINGTIME to 0.5. //default value 2
STAGE. //F-1A ignition

Set Kppitch to 0.00264. //Ku = 0.0033?  
Set Kipitch to 0.
Set Kdpitch to 0.0198.

Set Kpinc to 1.6. //Ku = 2
Set Kiinc to 0.
Set Kdinc to 5.8.

//Steering program.

WHEN SHIP:VELOCITY:SURFACE:MAG >= 50 THEN {
  //Pitch then roll for inclination.
  LOCK Autopilot to HEADING(initialheading,80).
  IF ROUND(VANG(SHIP:FACING:VECTOR, VXCL(UP:VECTOR,STEERINGMANAGER:TARGET:VECTOR))) = 90 { //Sometimes, the rocket pointing straight up causes next when trigger to be true, so this line prevents a vertical launch from triggering the gravity turn code.
    RETURN true.
  }
  //Gravity turn
  WHEN SHIP:FACING:VECTOR:NORMALIZED:Z - SHIP:VELOCITY:SURFACE:NORMALIZED:Z <= 0 AND VANG(UP:VECTOR, SHIP:VELOCITY:SURFACE) < 80 THEN { //triggers too early for some inclinations.
   LOCK Autopilot to SHIP:VELOCITY:SURFACE.
   WHEN SHIP:ALTITUDE > 75000 THEN { //At 75km, start program to control pitch based on current rocket path - Want to initiate heading guidance after MS-II ignition.
     PRINT "Initiate Closed-Loop Steering" at (0,10).
	 SET PID1 TO PIDLOOP(Kpinc, Kiinc, Kdinc). //Inclination guidance.
     SET PID2 TO PIDLOOP(Kppitch,Kipitch,Kdpitch). //Heading guidance - bouncy pitch at lower bound.
	 IF HASTARGET = TRUE {
       SET PID1:SETPOINT to TARGET:ORBIT:INCLINATION. 
     }
     ELSE {
       SET PID1:SETPOINT to targetinclination.
     }
	 SET PID2:SETPOINT to 0.
     SET Pitch1 to VANG(SHIP:FACING:VECTOR, VXCL(UP:VECTOR,SHIP:FACING:VECTOR)). //Doesn't represent pitch - initialize PID?
	 SET Heading1 TO -SHIP:BEARING.
	 WHEN true THEN { //Iterative guidance.
	   SET dPitch to PID2:UPDATE(TIME:SECONDS, SHIP:VERTICALSPEED).
	   SET dHeading to -PID1:UPDATE(TIME:SECONDS,SHIP:ORBIT:INCLINATION). //sign of dHeading negative if rocket approaching descending node, positive if rocket approaching ascending node. - Might want to kill heading changes until MS-II ignition.  MS-IC steers too violently.
	   IF Outboard:FUELFLOW > 0 AND (MSIC:MASS - MSIC:DRYMASS)/(Outboard:FUELFLOW * 5) < 2 AND J2S:FUELFLOW = 0 { //Hold pitch for MS-IC/MS-II staging.
		 SET Autopilot TO "Kill".
	   }
	   //Pitch control.
	   ELSE IF Pitch1 >= 15 OR (VANG(SHIP:FACING:VECTOR, VXCL(UP:VECTOR,SHIP:FACING:VECTOR)) >= 15 AND SHIP:FACING:VECTOR:Y >= 0) { //Transition from gravity turn or oversteer past maximum.
	     SET Pitch1 to 14.9.
		 PRINT "+Limit - Pitch.            " at (0,6). //change this text?
	   }
	   ELSE IF (Pitch1 < 15 AND Pitch1 >= 0) AND SHIP:FACING:VECTOR:Y >= 0 { //min and max pitch
	     PRINT "Pitch Guidance Converging.             " at (0,6).
	     SET Pitch1 to Pitch1 + dPitch. 	 
	   }
	   ELSE { //oversteer past minimum //fine after stage 2 ignition?
	     PRINT "-Limit - Pitch.                         " at (0,6).
	     SET Pitch1 to 0.1.
	   }
	   //Heading Control.
	   IF STAGE:NUMBER <= 19 { //Heading control starts after skirt sep.
	     IF (-SHIP:BEARING > 10 + initialheading) OR (Heading1 > 10 + initialheading) {
	       PRINT "+Limit - Heading.         " at (0,7).
	       SET Heading1 TO initialheading + 9.9.
		   //SET dHeading to -0.1.
         }		 
	     ELSE IF (-SHIP:BEARING <= (10 + initialheading) AND -SHIP:BEARING >= (initialheading - 10)) AND (Heading1 <= (10 + initialheading) AND Heading1 >= (initialheading - 10)) { //heading limits if needed.
	       PRINT "Heading Guidance Converging.             " at (0,7).
	       SET Heading1 to Heading1 + dHeading.  //Inclination correction - needs to be limited
	     }
	     ELSE IF (-SHIP:BEARING < initialheading - 10) OR (Heading1 < initialheading - 10) { 
	       PRINT "-Limit - Heading.                 " at (0,7).
	       SET Heading1 TO initialheading - 9.9.
		   //SET dHeading to +0.1.
	     }
       }
	   ELSE PRINT "Heading Unlocked." at (0,7).
	   IF SHIP:ORBIT:PERIAPSIS > 0 { //This sets pitch to zero for final orbital insertion to make orbit as circular as possible.
	     PRINT "Terminal Guidance                    " at (0,6).
		 PRINT "                                     " at (0,7).
		 SET Pitch1 to 0. //Terminal guidance for PE > 0.
		 RETURN false. //Kill steering loop.
	   }
	   SET Autopilot TO HEADING(Heading1,Pitch1).  
       RETURN true.	   
	 }  
   }  
  }
}

//Staging control.

//F-1A Ignition
UNTIL (Outboard:THRUST/Outboard:MAXTHRUST) > 0.88 {
  IF(Outboard:MAXTHRUST > 0.0001) {  //Prevent NAN
    LaunchDisplay(0,2,Outboard:THRUST/Outboard:MAXTHRUST,0).
  }
}

STAGE.  //SRB Ignition and Liftoff
CLEARSCREEN.


UNTIL MISSIONTIME > 24 { //originally 25
  IF(SRB:MAXTHRUST > 0.0001 AND SRB:THRUST > 0.0001) { //Prevent NAN
    LaunchDisplay(1,2,Outboard:THRUST/Outboard:MAXTHRUST,SRB:THRUST/SRB:MAXTHRUST).
  }
}

CLEARSCREEN.

LOCK THROTTLE to 0.01. //F-1A throttle to 60% for max Q

DECLARE LOCAL ddyn to 0.
DECLARE LOCAL dynzero to 0.
SET t0 to TIME:SECONDS.

UNTIL ddyn <= -1 { //originally 0.4
  LaunchDisplay(2,0,Outboard:THRUST/Outboard:MAXTHRUST,SRB:Thrust/SRB:MAXTHRUST).
  If TIME:SECONDS <> t0 { //Prevents NAN.
    SET ddyn TO ((SHIP:Q*constant:ATMtokPa) - dynzero)/(TIME:SECONDS - t0).
	SET dynzero TO (SHIP:Q*constant:ATMtokPa).
    SET t0 to TIME:SECONDS.
  } 
}

LOCK THROTTLE to 0.63. //F-1A throttle to 85%
SET g TO EARTH:MU/EARTH:RADIUS^2.
LOCAL LOCK acc TO SHIP:SENSORS:ACC - SHIP:SENSORS:GRAV. //if grav code doesn't work, set these to global.
LOCAL LOCK Gforce TO acc:MAG/g.

WHEN Gforce > 4 THEN LOCK THROTTLE TO 0.01. //First G force moderation throttleback (60%).

CLEARSCREEN.

UNTIL SRB:THRUST/SRB:MAXTHRUST < .09 {
  IF Outboard:THRUST/Outboard:MAXTHRUST < .90 AND Outboard:THRUST/Outboard:MAXTHRUST > .65 { //was .8
    LaunchDisplay(3,1,Outboard:THRUST/Outboard:MAXTHRUST,SRB:Thrust/SRB:MAXTHRUST). //85% thrust.
  }
  ELSE {
    LaunchDisplay(4,0,Outboard:THRUST/Outboard:MAXTHRUST,SRB:Thrust/SRB:MAXTHRUST). //60% thrust.
  }
}

STAGE. //SRB jettison

LOCK THROTTLE to 1.0. //F-1A throttle to 100%

CLEARSCREEN.

UNTIL (MSIC:MASS - MSIC:DRYMASS)/(Outboard:FUELFLOW * 5) < 26 {
  LaunchDisplay(5,2,Outboard:THRUST/Outboard:MAXTHRUST).
}

Inboard:SHUTDOWN. //Inboard cut-off (25s before MS-IC burnout).

CLEARSCREEN.

WHEN MISSIONTIME > 160 THEN LOCK THROTTLE TO 0.63. //Second G force moderation throttleback (85%).

//Remainder of MS-IC Flight
UNTIL Outboard:FLAMEOUT = TRUE {
  IF Outboard:MAXTHRUST > 0.0001 AND Outboard:FLAMEOUT = FALSE {//Prevent NAN
    IF Outboard:Thrust/Outboard:MAXTHRUST > .95 AND Outboard:Thrust/Outboard:MAXTHRUST < 1.05 {
	  LaunchDisplay(6,2,Outboard:Thrust/Outboard:MAXTHRUST). //100% thrust.
	}
	ELSE {
      LaunchDisplay(4,1,Outboard:Thrust/Outboard:MAXTHRUST). //85% thrust.
	}  
  }
}

//Main Engine Cut-Off
CLEARSCREEN.
LaunchDisplay(7,3,0).
LOCK THROTTLE TO 1.
WAIT 1.


CLEARSCREEN.
STAGE. //MS-IC Staging.
LaunchDisplay(8,3,0).
WAIT 3.

CLEARSCREEN.


STAGE. //MS-II Ignition.
SET t0 to TIME:SECONDS.

UNTIL TIME:SECONDS - t0 > 30 {
  LaunchDisplay(9,2,J2S:THRUST/J2S:MAXTHRUST).
} 

CLEARSCREEN.

STAGE. //Skirt seperation
Set t0 to TIME:SECONDS.

UNTIL TIME:SECONDS - t0 > 6 {
  LaunchDisplay(10,2,J2S:THRUST/J2S:MAXTHRUST).
}

CLEARSCREEN.

//Keep code running until SECO.
SET v_orb to 10000000.
WHEN SHIP:ORBIT:PERIAPSIS >= 0 THEN SET v_orb to SQRT(EARTH:MU/(SHIP:ALTITUDE + EARTH:RADIUS)). //Was periapsis.

UNTIL SHIP:VELOCITY:ORBIT:MAG >= v_orb { //SECO when v_orb for circular orbit at alt = periapsis reached.
  LaunchDisplay(11,2,J2S:THRUST/J2S:MAXTHRUST).
}

//SECO - Orbit insertion.
CLEARSCREEN.
LOCK THROTTLE to 0.

PRINT "Secondary Engine Cut-Off" at (0,3).
PRINT "Go for Orbit" at (0,4).

//Makes sure throttle is set to zero after program terminates.
SET SHIP:CONTROL:PILOTMAINTHROTTLE to 0.
//Display program for Ares Launch program.

SET AbMode to list("Ia","Ib","Ic","II","III").
SET GuidMode to list("Vertical Launch", "Pitch/Roll Program", "Gravity Turn       ", "Iterative Guidance").
SET State to list("Ignition Sequence Start", "Liftoff", "Max Q", "Throttle Up     ", "G Throttleback         ", "SRB Sep", "Center Engine Shutdown", "Main Engine Cut-Off", "Staging", "Stage Two Ignition", "Skirt Separation", "Boosting Into Orbit").
SET Level to list("60", "85", "100", "0").

function LaunchDisplay{

  parameter statevariable.
  parameter throttlelevel.
  parameter liquidthrust.
  parameter SRBthrust is 0.
  
  //Abort mode.
  SET sa to "Abort Mode: ".
  SET la to sa:LENGTH.
  PRINT sa at (0,0).
  IF SHIP:ALTITUDE < 3000 {
    PRINT AbMode[0] at (la,0).
  }
  ELSE IF SHIP:ALTITUDE < 30500 {
    PRINT AbMode[1] at (la,0).
  }
  ELSE IF SHIP:ALTITUDE < 80000 {
    PRINT AbMode[2] at (la,0).
  }
  ELSE IF (J2S:IGNITION = FALSE) OR (9.8 * J2S:ISP * LN(SHIP:MASS/(SHIP:WETMASS - MSII:WETMASS)) > 2881) OR STAGE:NUMBER > 19 { //dV calculated here is 400 more than possible stage dV.
    PRINT AbMode[3] at (la,0).
    AG27 on.
  }
  ELSE {
    PRINT AbMode[4] at (la,0).
  }
  
  //Launch situation, throttle, and thrust levels.
  PRINT "Situation: " + State[statevariable] at (0,1).
  
  PRINT "Throttle Setting: " + Level[throttlelevel] + "%  " at (0,2).
  
  IF statevariable <= 7 {
    PRINT "F-1A Thrust: " + ROUND(liquidthrust * 100,1) + "%  " at (0,3).
  } ELSE {
    PRINT "J-2S Thrust: " + ROUND(liquidthrust * 100,1) + "%  " at (0,3).
  }
  
  IF statevariable <= 4 AND statevariable > 0 {
    PRINT "UA1564 Thrust: " + ROUND(SRBthrust * 100,1) + "%  " at (0,4).
  }
  
  //Guidance mode
  
  SET sb to "Guidance Mode: ".
  SET lb to sb:LENGTH.
  PRINT sb at (0,5).
  IF SHIP:VELOCITY:SURFACE:MAG < 50 {
    PRINT GuidMode[0] at (lb,5).
  }
  ELSE IF (SHIP:FACING:VECTOR:NORMALIZED:Z - SHIP:VELOCITY:SURFACE:NORMALIZED:Z > 0 OR VANG(UP:VECTOR, SHIP:VELOCITY:SURFACE) >= 80) AND MISSIONTIME <= 24 {
    PRINT GuidMode[1] at (lb,5).
  }
  ELSE IF SHIP:ALTITUDE <= 75000 {
    PRINT GuidMode[2] at (lb,5).
  }
  ELSE {
    PRINT GuidMode[3] at (lb,5).
  }
}

I forgot to post changes to the display subprogram.  Oh well.

All that's left that I want to do now is texture replacement.  Finally close to launch.

Edited by Nittany Tiger
Link to comment
Share on other sites

I got a surprise in the mail today.

I had a friend look for a copy of Voyage in a book store in Texas.  They found it, but they never said anything else.

Well, it arrived today.  I finally have the book legit, and now I can do this recreation justice by having the actual book this whole mission is based on.

Unfortunately, I can't stream the mission due to current technical limitations, but it doesn't mean I can't in the future.  What I might do is just screenshots first, then a video, which I want to do eventually.  I do want to do a run through of the mission first for practice and to see if I need to make changes to the propulsion stage.

Anyway, can't wait to finish the book and then see if I can't make this first attempt like an illustrated slideshow of the book.

Link to comment
Share on other sites

  • 2 weeks later...

More Venus probe tests.

6F3385DDC041D558541BED4654860F6FE8A02841 (1280×720)

Using a probe with a different skin provided by @MeCripp

E56A9EBF4C8004412E88ABAF97D6996278C99BC7 (1280×720)

EDIT: As far as what I have left to do, or at least what I want to do before I start the mission, it's about three things:

  • Test Venus probe entry paths.
  • Practice MEM descent from an elliptical orbit.  This is just in case the Ares cluster can only make an elliptical orbit around Mars without running out of delta V.  In the book, I believe they make an initial elliptical orbit, and I'll have to check if they circularize it like with Apollo before detaching or not.  I plan on trying to make my Martian orbit as circular as possible before landing, but only if necessary.  I know the MEM can reach the Ares cluster in an elliptical orbit.  I just don't know if it can descend from one without additional solid rocket motors.
  • Fast forward my game time to the appropriate time, and then get the flight plan from Flyby Finder and KSP TOT.
Edited by Nittany Tiger
Link to comment
Share on other sites

  • 4 weeks later...

Hey everyone.  Just an update.

I've gotten into the game Payday 2, and I've been focusing on trying to find work as a tutor, so this project got put on hold.  I do intend on flying the mission very soon though as I'm pretty much ready to go.  However, I want to know what you guys would love to see from me as far as content.  Would you like a video series on the mission, or illustrated pictures?  If I go for the former, I can figure out how to make a video and put something nice together.  I've had ideas floating in my head for either an extended single video like Chris P Bacon's and rsferino's video, or a series of videos that go into the mission in more detail.  For the latter, I can post a new thread here or continue this thread with pictures.

Let me know so I can focus on one or the other going forward and make plans to do the mission soon.  I want to complete this project so I can move forward with a couple of planned future missions based in the Voyage universe:

  • Ares 2: Second mission to Mars.  Includes unmanned launch of cargo MEM on a single Saturn VB followed by another manned mission with a cosmonaut (since they may need Russian funding for a second mission)
  • Apollo to Titan: Send a craft in the Voyage-verse to Titan.  It's not based on the book Titan, so it's not a one-way trip.  This would also be an US-Russia collab.  Russia might launch nuclear components on their N-1 such as a reactor and NERVA engines.  This assumes Russia has been developing nuclear technology in secret and didn't stop after Apollo N.  NASA would provide the fueling and living quarters based on the Ares launch vehicle.  The whole craft would probably take Cassini's route to Saturn, but I'd have to figure out how to get them home after their landing on Titan.  I also want to use the MEM for a Titan landing, modified for landing on Titan, but this may change.
Link to comment
Share on other sites

I completely understand... That's how my little adventure story got completely out of control and I am currently at 203 pages and over 72,000 words.. Basically a decent size novel by now.. and I'm not even half done.

Link to comment
Share on other sites

  • 3 weeks later...

So in the book, the Ares cluster gets in an initial 219.9 mi x 12,611.3 mi orbit, or in metric, 353.9 km x 20,259.5 km.  It's a pretty eccentric orbit in terms of orbits with an eccentricity of 0.727.D7CA1AB1B60E968AA4AF940E53CD4EC1586F64DB

I set the orbit using Hyperedit and did some descent tests from this orbit.  Landing on Mars is very possible from this orbit, so it might be one aspect of the book that's valid.  I still wonder if the Ares cluster did another burn to circularize, though.

The Challenger MEM actually does two solid retroburns in the book.  I guess this might be a departure point in this simulation unless I could edit the part config file for the retropack to give it two SRB tanks and allow for two ignitions.  Could do it in the future.  I think for now, it's OK to do one burn to the target, especially with the aid of the Trajectories mod.

Edited by Nittany Tiger
Resolving issues getting image to embed.
Link to comment
Share on other sites

Join the conversation

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

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

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

×   Your previous content has been restored.   Clear editor

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

×
×
  • Create New...