From 0885beb81ca32e30e996e7bc009bc951ecc62a2a Mon Sep 17 00:00:00 2001
From: Jake Read <jake.read@cba.mit.edu>
Date: Wed, 30 Oct 2019 09:31:06 -0400
Subject: [PATCH] near refactor for periods

---
 hunks/adhoc/saturn.js | 238 ++++++++++++++++++++++++++++--------------
 1 file changed, 160 insertions(+), 78 deletions(-)

diff --git a/hunks/adhoc/saturn.js b/hunks/adhoc/saturn.js
index 22cc0bb..524ad12 100644
--- a/hunks/adhoc/saturn.js
+++ b/hunks/adhoc/saturn.js
@@ -112,8 +112,8 @@ export default function Saturn() {
 
       // to calculate the maximum entrance, given our exit, to make within one period of time:
       // let t = 2 * d / (speeds[i] + speeds[i + 1]) // current t ...
-      // v2, where t = period
-      let maxEntranceByPeriod = period / (2 * d) - speeds[i]
+      // v2, where t = period (1.5 is a safety factor for later rounding)
+      let maxEntranceByPeriod = (period * 1.5) / (2 * d) - speeds[i]
 
       // set the entrance speed to the min of JD or our Max Entrance, but no lower than the minspeed
       let max = Math.max(minSpeed, Math.min(speeds[i], maxEntranceByAccel, maxEntranceByPeriod))
@@ -166,9 +166,8 @@ export default function Saturn() {
       if (debug) console.log(`entrance speed is ${vi}`)
       if (debug) console.log(`exit speed is ${vf}`)
       if (debug) console.log(`d is ${d}, maxEntry ${maxEntry}, maxExit ${maxExit}`)
-      // big switch
-      if (maxExit <= vf) {
-        if (debug) console.log(`/`)
+      // these are common and useful:
+      let writeUpTick = () => {
         ramps.push({
           vi: vi,
           vf: vf,
@@ -176,9 +175,8 @@ export default function Saturn() {
           pi: pi,
           pf: pf
         })
-        if (ramps[ramps.length - 1].t < period) console.warn('RampPass generates too-short ramp:', ramps[ramps.length - 1])
-      } else if (maxEntry <= vi) {
-        if (debug) console.log('\\')
+      }
+      let writeDownTick = () => {
         ramps.push({
           vi: vi,
           vf: vf,
@@ -186,8 +184,20 @@ export default function Saturn() {
           pi: pi,
           pf: pf
         })
+      }
+      // big switch
+      if (maxExit <= vf) {
+        // the all-up and all-down segments should always be clear:
+        // since we already swept for these cases in the revpass
+        if (debug) console.log(`/`)
+        writeUpTick()
+        if (ramps[ramps.length - 1].t < period) console.warn('RampPass generates too-short ramp:', ramps[ramps.length - 1])
+      } else if (maxEntry <= vi) {
+        if (debug) console.log('\\')
+        writeDownTick()
         if (ramps[ramps.length - 1].t < period) console.warn('RampPass generates too-short ramp:', ramps[ramps.length - 1])
       } else if (vi === cruise && vf === cruise) {
+        // similarely, since we're not segmenting cruise any farther, it should also be OK
         if (debug) console.log('--')
         ramps.push({
           vi: vi,
@@ -201,100 +211,172 @@ export default function Saturn() {
         if (debug) console.log('--\\')
         let dcDist = (Math.pow(cruise, 2) - Math.pow(vf, 2)) / (2 * accel)
         let pInter = math.add(pf, vScalar(vUnitBetween(pf, pi), dcDist))
-        // seg1
-        ramps.push({
-          vi: vi,
-          vf: cruise,
-          t: (d - dcDist) / cruise,
-          pi: pi,
-          pf: pInter
-        })
-        if (ramps[ramps.length - 1].t < period) console.warn('RampPass generates too-short ramp:', ramps[ramps.length - 1])
-        // seg 2,
-        ramps.push({
-          vi: cruise,
-          vf: vf,
-          t: (cruise - vf) / accel,
-          pi: pInter,
-          pf: pf
-        })
-        if (ramps[ramps.length - 1].t < period) console.warn('RampPass generates too-short ramp:', ramps[ramps.length - 1])
-      } else if (vf === cruise) {
-        if (debug) console.log('/--')
-        let acDist = (Math.pow(cruise, 2) - Math.pow(vi, 2)) / (2 * accel)
-        let pInter = math.add(pi, vScalar(vUnitBetween(pi, pf), acDist))
-        // seg1
-        ramps.push({
-          vi: vi,
-          vf: cruise,
-          t: (cruise - vi) / accel,
-          pi: pi,
-          pf: pInter
-        })
-        if (ramps[ramps.length - 1].t < period) console.warn('RampPass generates too-short ramp:', ramps[ramps.length - 1])
-        // seg2
-        ramps.push({
-          vi: cruise,
-          vf: vf,
-          t: (d - acDist) / cruise,
-          pi: pInter,
-          pf: pf
-        })
-        if (ramps[ramps.length - 1].t < period) console.warn('RampPass generates too-short ramp:', ramps[ramps.length - 1])
-      } else {
-        let dcDist = (Math.pow(cruise, 2) - Math.pow(vf, 2)) / (2 * accel)
-        let acDist = (Math.pow(cruise, 2) - Math.pow(vi, 2)) / (2 * accel)
-        if (acDist + dcDist < d) {
-          if (debug) console.log('/--\\')
-          let pa = math.add(pi, vScalar(vUnitBetween(pi, pf), acDist))
-          let pb = math.add(pf, vScalar(vUnitBetween(pf, pi), dcDist))
-          // 3 segs
+        // now, we need to tune accel / cruise phases so that neither t is < 1 period
+        let tSeg1 = (d - dcDist) / cruise
+        let tSeg2 = (cruise - vf) / accel
+        if(tSeg1 < period || tSeg2 < period){
+          // hopeless, write downtick
+          // there are other options here: adjust one to suit other, but we're not here for it
+          // and in these cases, the small segments, being small, can just get washed into a big ramp, ok
+          writeDownTick()
+        } else {
+          // and if we can't do that, we backtrack to '\\' type
+          // seg1
           ramps.push({
             vi: vi,
             vf: cruise,
-            t: (cruise - vi) / accel,
+            t: tSeg1,
             pi: pi,
-            pf: pa
-          })
-          if (ramps[ramps.length - 1].t < period) console.warn('trouble seg1/3', ramps[ramps.length - 1])
-          ramps.push({
-            vi: cruise,
-            vf: cruise,
-            t: (d - acDist - dcDist) / cruise,
-            pi: pa,
-            pf: pb
+            pf: pInter
           })
-          if (ramps[ramps.length - 1].t < period) console.warn('trouble seg2/3', ramps[ramps.length - 1])
+          if (ramps[ramps.length - 1].t < period) console.warn('RampPass generates too-short ramp:', ramps[ramps.length - 1])
+          // seg 2,
           ramps.push({
             vi: cruise,
             vf: vf,
-            t: (cruise - vf) / accel,
-            pi: pb,
+            t: tSeg2,
+            pi: pInter,
             pf: pf
           })
-          if (ramps[ramps.length - 1].t < period) console.warn('trouble seg3/3', ramps[ramps.length - 1])
+          if (ramps[ramps.length - 1].t < period) console.warn('RampPass generates too-short ramp:', ramps[ramps.length - 1])
+        }
+      } else if (vf === cruise) {
+        if (debug) console.log('/--')
+        let acDist = (Math.pow(cruise, 2) - Math.pow(vi, 2)) / (2 * accel)
+        let pInter = math.add(pi, vScalar(vUnitBetween(pi, pf), acDist))
+        // I feel the same about this as I did above
+        let tSeg1 = (cruise - vi) / accel
+        let tSeg2 = (d - acDist) / cruise
+        if(tSeg1 < period || tSeg2 < period){
+          writeDownTick()
         } else {
-          if (debug) console.log('/\\')
-          let vPeak = Math.sqrt(((2 * accel * d + Math.pow(vi, 2) + Math.pow(vf, 2)) / 2))
-          let acDist = (Math.pow(vPeak, 2) - Math.pow(vi, 2)) / (2 * accel)
-          let pInter = math.add(pi, vScalar(vUnitBetween(pi, pf), acDist))
+          // seg1
           ramps.push({
             vi: vi,
-            vf: vPeak,
-            t: (vPeak - vi) / accel,
+            vf: cruise,
+            t: tSeg1,
             pi: pi,
             pf: pInter
           })
           if (ramps[ramps.length - 1].t < period) console.warn('RampPass generates too-short ramp:', ramps[ramps.length - 1])
+          // seg2
           ramps.push({
-            vi: vPeak,
+            vi: cruise,
             vf: vf,
-            t: (vPeak - vf) / accel,
+            t: tSeg2,
             pi: pInter,
             pf: pf
           })
           if (ramps[ramps.length - 1].t < period) console.warn('RampPass generates too-short ramp:', ramps[ramps.length - 1])
         }
+      } else {
+        let dcDist = (Math.pow(cruise, 2) - Math.pow(vf, 2)) / (2 * accel)
+        let acDist = (Math.pow(cruise, 2) - Math.pow(vi, 2)) / (2 * accel)
+        let writeTriangle = () => {
+          if (debug) console.log('/\\')
+          let vPeak = Math.sqrt(((2 * accel * d + Math.pow(vi, 2) + Math.pow(vf, 2)) / 2))
+          let acDist = (Math.pow(vPeak, 2) - Math.pow(vi, 2)) / (2 * accel)
+          let pInter = math.add(pi, vScalar(vUnitBetween(pi, pf), acDist))
+          // finally, we have to check here if either / or side is too small, then default to smallticks
+          let tSeg1 = (vPeak - vi) / accel
+          let tSeg2 = (vPeak - vf) / accel
+          if(tSeg1 < period || tSeg2 < period){
+            // bail hard,
+            if(vf > vi){
+              writeUpTick()
+            } else {
+              writeDownTick()
+            }
+          } else {
+            ramps.push({
+              vi: vi,
+              vf: vPeak,
+              t: tSeg1,
+              pi: pi,
+              pf: pInter
+            })
+            if (ramps[ramps.length - 1].t < period) console.warn('RampPass generates too-short ramp:', ramps[ramps.length - 1])
+            ramps.push({
+              vi: vPeak,
+              vf: vf,
+              t: tSeg2,
+              pi: pInter,
+              pf: pf
+            })
+            if (ramps[ramps.length - 1].t < period) console.warn('RampPass generates too-short ramp:', ramps[ramps.length - 1])
+          }
+        }
+        if (acDist + dcDist < d) {
+          if (debug) console.log('/--\\')
+          let pa = math.add(pi, vScalar(vUnitBetween(pi, pf), acDist))
+          let pb = math.add(pf, vScalar(vUnitBetween(pf, pi), dcDist))
+          // ok,
+          let tSeg1 = (cruise - vi) / accel
+          let tSeg2 = (d - acDist - dcDist) / cruise
+          let tSeg3 = (cruise - vf) / accel
+          if(tSeg2 < period){
+            // for this case, contencating into a triangle is fine... it will be within ~ 50ms of extra accel time: not much
+            writeTriangle()
+          } else if (tSeg1 < period && tSeg3 < period){
+            // contencate to slow-up or slow-down
+            if(vf > vi){
+              writeUpTick()
+            } else {
+              writeDownTick()
+            }
+          } else if (tSeg1 < period){
+            // write slow-triangle up to pb,
+            // HERE 
+            // and last seg. as normal
+            ramps.push({
+              vi: cruise,
+              vf: vf,
+              t: tSeg3,
+              pi: pb,
+              pf: pf
+            })
+          } else if (tSeg3 < period){
+            // write first seg as normal,
+            ramps.push({
+              vi: vi,
+              vf: cruise,
+              t: tSeg1,
+              pi: pi,
+              pf: pa
+            })
+            // second as slow-loss from pa -> vf
+            // HERE
+          } else {
+            // 3 segs
+            ramps.push({
+              vi: vi,
+              vf: cruise,
+              t: tSeg1,
+              pi: pi,
+              pf: pa
+            })
+            if (ramps[ramps.length - 1].t < period) console.warn('trouble seg1/3', ramps[ramps.length - 1])
+            ramps.push({
+              vi: cruise,
+              vf: cruise,
+              t: tSeg2,
+              pi: pa,
+              pf: pb
+            })
+            if (ramps[ramps.length - 1].t < period) console.warn('trouble seg2/3', ramps[ramps.length - 1])
+            ramps.push({
+              vi: cruise,
+              vf: vf,
+              t: tSeg3,
+              pi: pb,
+              pf: pf
+            })
+            if (ramps[ramps.length - 1].t < period) console.warn('trouble seg3/3', ramps[ramps.length - 1])
+          }
+        } else {
+          // the actual triangle case
+          writeTriangle()
+        }
       } // end BIGSWITCH
     } // end for-over-positions
     return ramps
-- 
GitLab