Shop OBEX P1 Docs P2 Docs Learn Events
Translating Math to Spin — Parallax Forums

Translating Math to Spin

Kirk FraserKirk Fraser Posts: 364
edited 2013-08-25 21:49 in Propeller 1
Math notation is sometimes confusing when translating a two dimensional formula into a single line computer statement. The formula I need a little help interpreting is equation 3 here: http://mathworld.wolfram.com/LogisticEquation.html

Now I know from Fortran there is an order of execution based on the more complex operations first while in Smalltalk it's straight left to right execution. Which does math symbols use and which does Spin use?

In the link, formula 3 looks translatable to a program. But I'm uncertian if the 1+ is added after or before multiplying the terms in parantheses by e to the specified power. Is this correct?

xt := 1 / 1 + (1 / x0 - 1) * e ** (-r * t)

Thank you.
«1

Comments

  • John AbshierJohn Abshier Posts: 1,116
    edited 2012-12-20 09:31
    Remember that Spin does integer math. Also ** is multiply and return upper 32 bits. Since e is not an integer you probably will have to use a floating point object. I would recommend F32 from the OBEX. Table 2-9 in the Propeller Manual lists all Spin math and logic operators. Table 2-10 is a list of precedence levels.

    John Abshier
  • SRLMSRLM Posts: 5,045
    edited 2012-12-20 09:41
    Take a look in the Propeller manual: http://www.parallax.com/Portals/0/Downloads/docs/prod/prop/Web-PropellerManual-v1.2.pdf

    From the manual:
    The Propeller chip applies the order-of-operations rules as does Algebra: expressions are evaluated left-to-right, except where parentheses and differing levels of precedence exist.

    Look at table 2-10 on page 145.

    In your case, the equation that you posted would incorrectly evaluate since the / operator would be evaluated before the addition operator (possibly among other things). When in doubt, use parenthesis to change the order of evaluation:
    xt := 1 / (1 + (1/x_0 - 1)*e(-r * t) )
    

    Now, here is a couple of things:
    1. Spin is integer only, so your equation wouldn't work very well as is.
    2. Spin doesn't have e defined by default.
    3. Spin doesn't have an pow function (** is multiply high, which is for 64 bit multiplication).

    To get around the Spin integer only, there are two alternatives. You can multiply both the numerator and denominator by the same number (say, 1,000,000) and remember that any number that comes out of your equation is 10^6 times larger than it should be.

    The second alternative is to use a floating point library. I recommend F32.
  • JonnyMacJonnyMac Posts: 8,929
    edited 2012-12-20 10:01
    Per John's suggestion vis-a-vis F32, you should be able to do something like this:
    pub logistic(x0, r, t)
    
    '' Parameters are floats
    '' xt := 1 / (1 + ((1 / x0) - 1) * (e ** (-r * t)))
    
      x0 := fp.fsub(fp.fdiv(1.0, x0), 1.0)
      r  := fp.exp(fp.fmul(fp.fneg(r), t))
    
      result := fp.fdiv(1.0, fp.fmul(x0, r))
    
  • Martin_HMartin_H Posts: 4,051
    edited 2012-12-20 11:05
    I've been a bit spooked by F32 since Duane Degn found a bug in the ATAN function.
  • Duane DegnDuane Degn Posts: 10,588
    edited 2012-12-20 11:36
    Martin_H wrote: »
    I've been a bit spooked by F32 since Duane Degn found a bug in the ATAN function.

    Martin, The ATan2 bug spooked be a bit too, but F32 has been around long enough that I think we're seeing the last of the bugs.

    My patched version is available in the F32 thread (post #92).

    I believe the ATan method is fine.

    I still think F32 is still the best floating point object.
  • Kirk FraserKirk Fraser Posts: 364
    edited 2013-07-14 08:48
    I need help on this code to get a debug display of values from the Scurve generator. I currently get a compiler error on the x variable identified in the code. Do I need to identify a variable that will be a float as a long or what? Will I need a special version of the serial terminal? I had a slightly different error when I incorporated the previous line of code in the one with the error, which I don't understand either. Thanks.
    {{Debug scurve
    }}
    obj
      fp       : "F32"                                              '
    floating point functions
      fstr     : "FloatString"                                      '
    Convert Float to String
      dbug     : "Serial Terminal"                                  ' pc serial IO
    con
       e = 2.71828
      _clkmode = xtal1 + pll16x
      _xinfreq = 5_000_000                                         ' use
    5MHz crystal
    pub main | x, it
       fp.start
       dbug.startRxTx(31, 30, 0, 115200)            ' start debug object
       waitcnt(clkfreq*3+cnt)                       ' Wait for Debug
    Startup
       dbug.Str(string(13,"Debug Start "))
    
       repeat it from 1 to 15
         x := scurve(1000, 1.0, it)
         x :=  fstr.FloatToString(x)
    
    '****************************
    ' bug follows on x variable
         dbug.Str(string(13, x))
    '*****************************
    
         dbug.Str(string(10))
    '
    pub scurve(x0, r, t)
    ' x0 = Initial point as float at time 0.0
    ' r = rate -1.0 decelerate to 0.0 flat to +1.0 accelerate
    ' t = time 0.0 to 10.0 (time or positons as float to complete curve)
    ' result = % of top speed / 100
    
    ' http://mathworld.wolfram.com/LogisticEquation.html
    ' http://forums.parallax.com/showthread.php?144766-Translating-Math-to-Spin
    ' xt := 1 / (1 + ((1 / x0) - 1) * (e ** (-r * t)))
    
      x0 := fp.fsub(fp.fdiv(1.0, x0), 1.0)
      r  := fp.exp(fp.fmul(fp.fneg(r), t))
    
      result := fp.fdiv(1.0, fp.fmul(x0, r))
    
  • Duane DegnDuane Degn Posts: 10,588
    edited 2013-07-14 13:59
    I need help on this code to get a debug display of values from the Scurve generator. I currently get a compiler error on the x variable identified in the code. Do I need to identify a variable that will be a float as a long or what?

    Hi Kirk,

    Yes, a variable that will be used as a float should be setup as a long.

    You can't mix floats and integers in math functions. If you've going to perform a float calculation on a number it needs to be a floating point number before using it as a parameter in a float method call.

    Hopefully this version will clear up some of these issues.
    {{Debug scurve}}
    CON
       
      _clkmode = xtal1 + pll16x
      _xinfreq = 5_000_000          ' use 5MHz crystal
      'e = 2.71828
      BAUD = 115200
    
    
    VAR
    
    
      long fSCurveX
      long strPtr
        
    OBJ
    
    
      fp       : "F32"              'floating point functions
      fstr     : "FloatString"      'Convert Float to String
      dbug     : "Parallax Serial Terminal"  ' pc serial IO
      
    PUB Main | x, it
    
    
       fp.start
       dbug.start(BAUD)                    ' start debug object
       waitcnt(clkfreq * 3 + cnt)   ' Wait for Debug Startup
       dbug.Str(string(13,"Debug Start "))
    
    
       repeat it from 1 to 15
         fSCurveX := SCurve(1000.0, 1.0, it)
         strPtr :=  fstr.FloatToString(fSCurveX)
    
    
         dbug.Char(13)
         dbug.Str(strPtr) 
    
    
         'dbug.Char(10) ' Not needed with PST
      repeat ' keep cog alive
      
    PUB SCurve(x0, r, t)
    ' x0 = Initial point as float at time 0.0
    ' r = rate -1.0 decelerate to 0.0 flat to +1.0 accelerate
    ' t = time 0.0 to 10.0 (time or positons as float to complete curve)
    ' result = % of top speed / 100
    
    
    ' http://mathworld.wolfram.com/LogisticEquation.html
    ' http://forums.parallax.com/showthread.php?144766-Translating-Math-to-Spin
    ' xt := 1 / (1 + ((1 / x0) - 1) * (e ** (-r * t)))
    
    
      t := fp.FFloat(t)
      x0 := fp.fsub(fp.fdiv(1.0, x0), 1.0)
      r  := fp.exp(fp.fmul(fp.fneg(r), t))
    
    
      result := fp.fdiv(1.0, fp.fmul(x0, r))
    

    I haven't check through the math involved. I just made integers floating point numbers so the equation would have a chance to work.

    You can also see how to display a float using the float to string object.

    This is the output of the above code. Is it anything like you were expecting?
    Debug Start      
    -2.721008 
    -7.396457
    -20.10573
    -54.65288
    -148.5609
    -403.8313
    -1097.73
    -2983.943
    -8111.185
    -22048.51
    -59934.1
    -162917.2
    -442857.1
    -1203809
    -3272286
    

    Edit(3/11/15): Warning, the code attached is an old version. There are likely better options available.
    I plan to upload this program or an improved version to my GitHub account
    If there isn't code similar to what is attached here on my on GitHub, send me a message and I'll make and check for any improved versions of the code.
  • Kirk FraserKirk Fraser Posts: 364
    edited 2013-07-14 15:45
    Duane Degn wrote: »
    Hi Kirk,

    Yes, a variable that will be used as a float should be setup as a long. You can't mix floats and integers in math functions. If you've going to perform a float calculation on a number it needs to be a floating point number before using it as a parameter in a float method call.

    Hopefully this version will clear up some of these issues. I haven't check through the math involved. I just made integers floating point numbers so the equation would have a chance to work. You can also see how to display a float using the float to string object.

    This is the output of the above code. Is it anything like you were expecting?
    Debug Start      
    -2.721008 
    -7.396457
    -20.10573
    -54.65288
    -148.5609
    -403.8313
    -1097.73
    -2983.943
    -8111.185
    -22048.51
    -59934.1
    -162917.2
    -442857.1
    -1203809
    -3272286
    

    Hi Duane,

    Thanks. I copied your code but the best I can get is the first statement "Debug Start" without the numbers. What would you suggest?

    On the result numbers, they don't fit the curve shown in the link
    http://mathworld.wolfram.com/LogisticEquation.html
    Is there some kind of math error? I traced the math given in the link to the code and it looks ok to me. But it should be delivering numbers that go from 0 to 1 which would allow various uses such as slowly turning on an LED. Changing the x parameter should produce 1 to 0. Am I starting with X0 = 1000.0 incorrectly?

    I want to use the formula to generate a series of numbers, 0 to 1, 1, 1 to 0 as X moves within the range less than your position sensor output smaller than 0 to 4095 such as 1000 to 2000, then in reverse over the range 2000 to 1000 varying the output again from 0 to 1, 1, 1 to 0 producing a smoothed trapezoid curve in each direction which will reduce jerk and backlash motion in a robot or CNC.
  • Duane DegnDuane Degn Posts: 10,588
    edited 2013-07-14 16:18
    Kirk,

    Did you try the Spin file attached to post #8?
  • AribaAriba Posts: 2,682
    edited 2013-07-14 20:07
    Duane

    I think your code misses the 1+ from the formula: xt := 1 / (1 + ((1 / x0) - 1) * (e ** (-r * t)))

    the last line should be:
      result := fp.fdiv(1.0, fp.fadd(1.0, fp.fmul(x0, r)))
    

    Andy
  • Duane DegnDuane Degn Posts: 10,588
    edited 2013-07-14 20:20
    Ariba wrote: »
    Duane

    I think your code misses the 1+ from the formula: xt := 1 / (1 + ((1 / x0) - 1) * (e ** (-r * t)))

    Andy,

    With your correction, the output is:
    Debug Start
    1.581055
    1.156337
    1.05234
    1.018638
    1.006777
    1.002482
    1.000912
    1.000335
    1.000123
    1.000045
    1.000017
    1.000006
    1.000002
    1.000001
    1
    

    Which looks better than the earlier output but I don't think this is what Kirk is looking for either.

    Thanks for pointing out the error in the code.
  • AribaAriba Posts: 2,682
    edited 2013-07-14 22:18
    The x0 value should be in the range 0...1.0, not 1000. The different colors in the plots on the website show different x0 values from 0 to 1.
    And t should start at 0 not 1.
    So a main-loop can be: (the first parameter of SCurve can be varied between 0.05 and 0.95 to get the different colored curves)
       repeat it from 0 to 15
         fSCurveX := SCurve(0.1, 1.0, it)
         strPtr :=  fstr.FloatToString(fSCurveX)
    

    Andy
  • Duane DegnDuane Degn Posts: 10,588
    edited 2013-07-15 07:35
    Ariba wrote: »
    The x0 value should be in the range 0...1.0, not 1000. The different colors in the plots on the website show different x0 values from 0 to 1.
    And t should start at 0 not 1.
    So a main-loop can be: (the first parameter of SCurve can be varied between 0.05 and 0.95 to get the different colored curves)

    Thanks for looking the math over to see what's it's supposed to do. I hadn't looked at the math behind the equations yet myself.

    I'm pretty sure Kirk wants to use these equations to smooth out the movement of some actuators (I believe they're hydraulic). I myself wonder if you need such complicated equations to get nice smooth ramping.

    If I use an acceleration of one unit distance per time unit squared and a max speed of 25 distance units per time unit I get a displacement graph like this:

    ConstanAcceleration130715a.PNG


    This graph also shows a deceleration of the same magnitude as the acceleration. The shape of the curve could be squashed or stretched by changing the acceleration magnitude.

    I personally think this would be easier to program and use parameters which would be easier to understand.

    What do you think Kirk? Andy? Others?
    715 x 506 - 24K
  • AribaAriba Posts: 2,682
    edited 2013-07-15 09:51
    Your smoothed curve looks a bit like a part of a sine curve, so why not use the sine rom table for de-/acceleration?

    Here is a test with output to PropTerminal:
    CON
      _clkmode  = xtal1 + pll16x
      _xinfreq  = 5_000_000
    
    OBJ
      term :  "pc_interface"
          
    PUB Main : y | t
      term.start(31,30)
      repeat t from 0 to 300
        y := smooth(50,200,300,t)
        term.plot(t,240-y)
    
    PUB smooth(x0,x1,steps,n) : x | h
      h := (x0+x1) / 2
      x := cos(n*4096/steps, x0-h ) + h
    
    PUB cos(angle, range) : s | c,z
      angle += 2048
      c := angle & $800
      z := angle & $1000
      if c
        angle := -angle
      angle |= $E000>>1
      angle <<= 1
      s := word[angle]
      if z
        s := -s
      return (s*range)~>16     ' return cosine = -range..+range
    
    And the output:
    smooth.gif


    Andy
    332 x 280 - 3K
  • Duane DegnDuane Degn Posts: 10,588
    edited 2013-07-15 11:54
    Ariba wrote: »
    Your smoothed curve looks a bit like a part of a sine curve, so why not use the sine rom table for de-/acceleration?

    Here is a test with output to PropTerminal:

    Cool! Very nice.

    I'm pretty sure the curves are identical in shape (any difference could be removed by a squash or stretch). This reminds me of the sinusoidal motion demo in physics where a ball oscillating on a spring has the same vertical motion as a ball on the edge of a rotating disc.

    I'm still thinking an acceleration algorithm may be a better fit for this application since I'm pretty sure Kirk will want to compute both the displacement and the speed.

    I'll modify your code to illustrate the way I'm thinking it could be done. I'll post the code and PropTerminal output in a bit.

    Thanks for the example of how to use the sine ROM table. I haven't used the ROM tables myself.
  • Duane DegnDuane Degn Posts: 10,588
    edited 2013-07-15 16:39
    As I think about this a bit more, there are many reasons to use acceleration and velocity to compute the movement. Mainly since the physical limitations will be based on these parameters.

    While I think the curve produce by using the ROM sine looks nice, I think in reality there will likely be a section of the motion path without acceleration.

    It took a bit of fiddling to get integer values for acceleration, max speed and distance traveled that would fill the PropTerminal display.

    This the code I ended up using (some comes from the stepper motor code I'm working on).
    CON  _clkmode  = xtal1 + pll16x
      _xinfreq  = 5_000_000
    
    
     
      MAX_SPEED = 200             
     
      ACCELERATION = 2 
      
      DISTANCE_TO_MOVE = 40_000
    
    
      MAX_DISPLAY_Y = 220
      DISPLAY_SCALE = DISTANCE_TO_MOVE / MAX_DISPLAY_Y
      
      ' driverState enumeration
      #0, RAMP_UP, FULL_SPEED, RAMP_DOWN, STOP
    
    
    VAR
    
    
      long speed, time, distance
      long rampDownTarget
      
      byte driverState
      
    OBJ
      term :  "pc_interface"
          
    PUB Main
      term.start(31,30)
      driverState := RAMP_UP
      speed := 0
      
      repeat 
        Move
        term.plot(time++, MAX_DISPLAY_Y - (distance / DISPLAY_SCALE))
      while driverState <> STOP
      repeat
    
    
    PUB Move
    
    
      case driverState
        RAMP_UP:
          RampUp 
        FULL_SPEED:
          FullSpeed
        RAMP_DOWN:
          RampDown
      distance += speed
            
    PUB RampUp
    
    
      result := speed + ACCELERATION
      if result => MAX_SPEED
        speed := MAX_SPEED         
        rampDownTarget := DISTANCE_TO_MOVE - distance
        if rampDownTarget =< 0
          driverState := RAMP_DOWN
        else
          driverState := FULL_SPEED
      else
        speed := result
              
    PUB FullSpeed
    
    
      if distance + speed => rampDownTarget
        driverState := RAMP_DOWN
    
    
    PUB RampDown
    
    
      result := speed - ACCELERATION
      result #>= 1
      if distance + result => DISTANCE_TO_MOVE
        speed := DISTANCE_TO_MOVE - distance
        driverState := STOP
      else
        speed := result
    

    This is the output to the PropTerminal.

    ConstanAcceleration130715b.PNG


    I think the main difference in this curve from the one produced using the sine tables is the straight line section of constant speed. If this constant speed section were removed, I think the graphs would look very similar.
  • Kirk FraserKirk Fraser Posts: 364
    edited 2013-07-15 18:05
    Thanks to all for taking a look at this.

    My previous code segment was just attempting a third of the problem, the acceleration or rise from 0 to 1. The second stage must stay at 1 for most of the move along an axis. The third stage decelerates from 1 to 0 so the motion along say the X axis will arrive exactly at the specified point. So the result is a trapezoid but I'm trying for smoother curved transitions instead of the angles of a trapezoid.

    At this stage of my understanding and project any curve will be an improvement but eventually Duane is right I will want to be able to specify acceleration for a controlled jerk into action. I'm guessing some tweaking will be needed based on weight of the object moved. Can a weight parameter be used to calculate the appropriate curve squashing?

    In the long run I'll need to use a Proportional Integral Derivative (PID) algorithm or other feedback loop to hold a robot or CNC motion at the position specified as end of motion, until a new motion command is generated, to counteract gravity, backlash, and other forces which might act on the part being moved. I currently don't know how a PID could be integrated into the trapezoid like curve since it's intended to swing back and forth.

    I don't know enough about PID's, if they are used in the whole motion or just at the end of travel. Perhaps there is some simpler way to hold position until a new position command is received. In any case getting it to work at all would be progress. I wasn't able to get numbers out of my setup let alone a graph. How do you guys do that? Thank you.
  • Duane DegnDuane Degn Posts: 10,588
    edited 2013-07-15 19:50
    At this stage of my understanding and project any curve will be an improvement but eventually Duane is right I will want to be able to specify acceleration for a controlled jerk into action.

    By using acceleration, the movement should be smooth. You used the work "jerk" which has a technical meaning as well as the usual one most people think about when they hear/use the word. Velocity is the change of position over time, acceleration is the change in velocity over time and the jerk is the change in acceleration over time. In general a constant acceleration is enough for smooth motion.

    I'm guessing your use of the word "jerk" referred to an abrupt movement?
    I'm guessing some tweaking will be needed based on weight of the object moved. Can a weight parameter be used to calculate the appropriate curve squashing?

    Generally a PID algorithm would take care of the weight. For example, my Mecanum wheeled robot requires more power to drive on carpet than a smooth floor. When the robot encounters carpet, the control algorithm automatically compensates for the increased resistance which allows the robot to maintain the desired speed.
    In the long run I'll need to use a Proportional Integral Derivative (PID) algorithm or other feedback loop to hold a robot or CNC motion at the position specified as end of motion, until a new motion command is generated, to counteract gravity, backlash, and other forces which might act on the part being moved. I currently don't know how a PID could be integrated into the trapezoid like curve since it's intended to swing back and forth.

    The target speed would be calculated by using whatever curved trapezoid algorithm you use for computed desired speed. The PID algorithm would use feedback in order to make the actual measured speed match this target speed. They can remain independent of each other.
    I don't know enough about PID's, if they are used in the whole motion or just at the end of travel.

    The PID algorithm would likely be active the entire path of the mechanism.
    Perhaps there is some simpler way to hold position until a new position command is received. In any case getting it to work at all would be progress. I wasn't able to get numbers out of my setup let alone a graph. How do you guys do that? Thank you.

    For one thing I chose my constants in order to avoid the need for fractional numbers. I then pretty much just copied Andy's method of graphing the output. Andy used a program called PropTerminal to graph the output. Here's a thread with a link and a bit of discussion.

    @Andy, Are you the same Andy who wrote PropTerminal? If so, very, very cool!
  • AribaAriba Posts: 2,682
    edited 2013-07-15 20:20
    Duane Degn wrote: »
    ....
    @Andy, Are you the same Andy who wrote PropTerminal? If so, very, very cool!

    Yes, I am. Thank's for the kudos. Here is the original thread about PropTerminal. This was my first post in this forum, it's quite a few years since...

    Andy
  • Kirk FraserKirk Fraser Posts: 364
    edited 2013-07-15 21:21
    Duane Degn wrote: »
    By using acceleration, the movement should be smooth. You used the work "jerk" which has a technical meaning as well as the usual one most people think about when they hear/use the word. Velocity if the change of position over time, acceleration is the change in velocity over time and the jerk is the change in acceleration over time. In general a constant acceleration is enough for smooth motion.

    I'm guessing your use of the word "jerk" referred to an abrupt movement?

    Yes although there can be many reasons for needing an abrupt movement. Say you want to make a robot move through a spring loaded door by pushing it open with just enough force so it shuts behind the robot instead of on the robot. In my human experience that takes precise acceleration control. Or say the hydraulic cylinders encounter "stiction" which is a technical term for a tendency of staying in position even when force is applied due to O-rings sticking to the wall of the cylinder. A measured amount of acceleration might overcome a tendency to stick well enough to appear that they're smooth.
    Duane Degn wrote: »
    Generally a PID algorithm would take care of the weight. For example, my Mecanum wheeled robot requires more power to drive on carpet than a smooth floor. When the robot encounters carpet, the control algorithm automatically compensates for the increased resistance which allows the robot to maintain the desired speed.

    The target speed would be calculated by using whatever curved trapezoid algorithm you use for computed desired speed. The PID algorithm would use feedback in order to make the actual measured speed match this target speed. They can remain independent of each other.

    The PID algorithm would likely be active the entire path of the mechanism.

    Great! I'm glad you know this stuff.
    Duane Degn wrote: »
    For one thing I chose my constants in order to avoid the need for fractional numbers. I then pretty much just copied Andy's method of graphing the output. Andy used a program called PropTerminal to graph the output. Here's a thread with a link and a bit of discussion.

    @Andy, Are you the same Andy who wrote PropTerminal? If so, very, very cool!

    Ok, but I'm not even able to get the numbers as you might see when you load up my software. Maybe it's my copy of the serial terminal? Or maybe I don't know how to do a reset from the new Propeller Project Board which doesn't have a reset switch, or maybe I have some setting wrong so the terminal interrupts the Propeller Tool and vice versa instead of operating as one like the old Basic Stamp software. Thanks, I'll try the PropTerminal and see if that fixes my problem.
  • Duane DegnDuane Degn Posts: 10,588
    edited 2013-07-16 11:32
    As far as using he PropTerminal, you inablity to reset the Prop, may be the problem since neither Andy's nor my programs add a delay prior to graphing the output.

    My Propeller Project board has reset button. It's near the corner farthest away from the USB connector. The button faces forward rather than up. I think you could also reset the Prop from within PropTerminal.

    I'm attaching spin code which doesn't require you to reset the Propeller to see the graph. Just load "AccelerationSCurve130716a.spin" into the Prop open PropTerminal, Select Options\Com Enabled (to connect to the serial line) from the menu. You should see a bunch of "Press any key to start." messages. When a key is pressed on the keyboard, the screen will be cleared and the graph displayed.
    Ok, but I'm not even able to get the numbers as you might see when you load up my software. Maybe it's my copy of the serial terminal?

    I've noticed you use a different serial object than what I'm used to. Is there something you don't like about Parallax Serial Terminal.spin and/or Parallax Serial Terminal.exe.

    Andy's PropTerminal is cool in that it will let you do some basic graphics and uses colored text but for reading debug text, I much prefer to use Parallax Serial Terminal.exe. PST allows much more text to be displayed at one time than PropTerminal.

    I'm attaching a similar version of the graphing code which displays the output as numbers. The Program "AccelerationPst130716b.spin" is intended to be used with PST. This program also starts with a "Press any key to start." message so you can take as long as you like enabling PST.

    This is the output from "AccelerationPst130716b.spin".
    t = 0    , a = 2 , s = 2  , d = 2
    t = 1    , a = 2 , s = 4  , d = 6
    t = 2    , a = 2 , s = 6  , d = 12
    t = 3    , a = 2 , s = 8  , d = 20
    t = 4    , a = 2 , s = 10 , d = 30
    t = 5    , a = 2 , s = 12 , d = 42
    t = 6    , a = 2 , s = 14 , d = 56
    t = 7    , a = 2 , s = 16 , d = 72
    t = 8    , a = 2 , s = 18 , d = 90
    t = 9    , a = 2 , s = 20 , d = 110
    t = 10   , a = 2 , s = 22 , d = 132
    t = 11   , a = 2 , s = 24 , d = 156
    t = 12   , a = 2 , s = 26 , d = 182
    t = 13   , a = 2 , s = 28 , d = 210
    t = 14   , a = 2 , s = 30 , d = 240
    t = 15   , a = 2 , s = 32 , d = 272
    t = 16   , a = 2 , s = 34 , d = 306
    t = 17   , a = 2 , s = 36 , d = 342
    t = 18   , a = 2 , s = 38 , d = 380
    t = 19   , a = 2 , s = 40 , d = 420
    t = 20   , a = 2 , s = 42 , d = 462
    t = 21   , a = 2 , s = 44 , d = 506
    t = 22   , a = 2 , s = 46 , d = 552
    t = 23   , a = 2 , s = 48 , d = 600
    t = 24   , a = 2 , s = 50 , d = 650
    t = 25   , a = 2 , s = 52 , d = 702
    t = 26   , a = 2 , s = 54 , d = 756
    t = 27   , a = 2 , s = 56 , d = 812
    t = 28   , a = 2 , s = 58 , d = 870
    t = 29   , a = 2 , s = 60 , d = 930
    t = 30   , a = 2 , s = 62 , d = 992
    t = 31   , a = 2 , s = 64 , d = 1056
    t = 32   , a = 2 , s = 66 , d = 1122
    t = 33   , a = 2 , s = 68 , d = 1190
    t = 34   , a = 2 , s = 70 , d = 1260
    t = 35   , a = 2 , s = 72 , d = 1332
    t = 36   , a = 2 , s = 74 , d = 1406
    t = 37   , a = 2 , s = 76 , d = 1482
    t = 38   , a = 2 , s = 78 , d = 1560
    t = 39   , a = 2 , s = 80 , d = 1640
    t = 40   , a = 2 , s = 82 , d = 1722
    t = 41   , a = 2 , s = 84 , d = 1806
    t = 42   , a = 2 , s = 86 , d = 1892
    t = 43   , a = 2 , s = 88 , d = 1980
    t = 44   , a = 2 , s = 90 , d = 2070
    t = 45   , a = 2 , s = 92 , d = 2162
    t = 46   , a = 2 , s = 94 , d = 2256
    t = 47   , a = 2 , s = 96 , d = 2352
    t = 48   , a = 2 , s = 98 , d = 2450
    t = 49   , a = 2 , s = 100, d = 2550
    t = 50   , a = 2 , s = 102, d = 2652
    t = 51   , a = 2 , s = 104, d = 2756
    t = 52   , a = 2 , s = 106, d = 2862
    t = 53   , a = 2 , s = 108, d = 2970
    t = 54   , a = 2 , s = 110, d = 3080
    t = 55   , a = 2 , s = 112, d = 3192
    t = 56   , a = 2 , s = 114, d = 3306
    t = 57   , a = 2 , s = 116, d = 3422
    t = 58   , a = 2 , s = 118, d = 3540
    t = 59   , a = 2 , s = 120, d = 3660
    t = 60   , a = 2 , s = 122, d = 3782
    t = 61   , a = 2 , s = 124, d = 3906
    t = 62   , a = 2 , s = 126, d = 4032
    t = 63   , a = 2 , s = 128, d = 4160
    t = 64   , a = 2 , s = 130, d = 4290
    t = 65   , a = 2 , s = 132, d = 4422
    t = 66   , a = 2 , s = 134, d = 4556
    t = 67   , a = 2 , s = 136, d = 4692
    t = 68   , a = 2 , s = 138, d = 4830
    t = 69   , a = 2 , s = 140, d = 4970
    t = 70   , a = 2 , s = 142, d = 5112
    t = 71   , a = 2 , s = 144, d = 5256
    t = 72   , a = 2 , s = 146, d = 5402
    t = 73   , a = 2 , s = 148, d = 5550
    t = 74   , a = 2 , s = 150, d = 5700
    t = 75   , a = 2 , s = 152, d = 5852
    t = 76   , a = 2 , s = 154, d = 6006
    t = 77   , a = 2 , s = 156, d = 6162
    t = 78   , a = 2 , s = 158, d = 6320
    t = 79   , a = 2 , s = 160, d = 6480
    t = 80   , a = 2 , s = 162, d = 6642
    t = 81   , a = 2 , s = 164, d = 6806
    t = 82   , a = 2 , s = 166, d = 6972
    t = 83   , a = 2 , s = 168, d = 7140
    t = 84   , a = 2 , s = 170, d = 7310
    t = 85   , a = 2 , s = 172, d = 7482
    t = 86   , a = 2 , s = 174, d = 7656
    t = 87   , a = 2 , s = 176, d = 7832
    t = 88   , a = 2 , s = 178, d = 8010
    t = 89   , a = 2 , s = 180, d = 8190
    t = 90   , a = 2 , s = 182, d = 8372
    t = 91   , a = 2 , s = 184, d = 8556
    t = 92   , a = 2 , s = 186, d = 8742
    t = 93   , a = 2 , s = 188, d = 8930
    t = 94   , a = 2 , s = 190, d = 9120
    t = 95   , a = 2 , s = 192, d = 9312
    t = 96   , a = 2 , s = 194, d = 9506
    t = 97   , a = 2 , s = 196, d = 9702
    FULL_SPEED
    t = 98   , a = 0 , s = 200, d = 9900
    t = 99   , a = 0 , s = 200, d = 10100
    t = 100  , a = 0 , s = 200, d = 10300
    t = 101  , a = 0 , s = 200, d = 10500
    t = 102  , a = 0 , s = 200, d = 10700
    t = 103  , a = 0 , s = 200, d = 10900
    t = 104  , a = 0 , s = 200, d = 11100
    t = 105  , a = 0 , s = 200, d = 11300
    t = 106  , a = 0 , s = 200, d = 11500
    t = 107  , a = 0 , s = 200, d = 11700
    t = 108  , a = 0 , s = 200, d = 11900
    t = 109  , a = 0 , s = 200, d = 12100
    t = 110  , a = 0 , s = 200, d = 12300
    t = 111  , a = 0 , s = 200, d = 12500
    t = 112  , a = 0 , s = 200, d = 12700
    t = 113  , a = 0 , s = 200, d = 12900
    t = 114  , a = 0 , s = 200, d = 13100
    t = 115  , a = 0 , s = 200, d = 13300
    t = 116  , a = 0 , s = 200, d = 13500
    t = 117  , a = 0 , s = 200, d = 13700
    t = 118  , a = 0 , s = 200, d = 13900
    t = 119  , a = 0 , s = 200, d = 14100
    t = 120  , a = 0 , s = 200, d = 14300
    t = 121  , a = 0 , s = 200, d = 14500
    t = 122  , a = 0 , s = 200, d = 14700
    t = 123  , a = 0 , s = 200, d = 14900
    t = 124  , a = 0 , s = 200, d = 15100
    t = 125  , a = 0 , s = 200, d = 15300
    t = 126  , a = 0 , s = 200, d = 15500
    t = 127  , a = 0 , s = 200, d = 15700
    t = 128  , a = 0 , s = 200, d = 15900
    t = 129  , a = 0 , s = 200, d = 16100
    t = 130  , a = 0 , s = 200, d = 16300
    t = 131  , a = 0 , s = 200, d = 16500
    t = 132  , a = 0 , s = 200, d = 16700
    t = 133  , a = 0 , s = 200, d = 16900
    t = 134  , a = 0 , s = 200, d = 17100
    t = 135  , a = 0 , s = 200, d = 17300
    t = 136  , a = 0 , s = 200, d = 17500
    t = 137  , a = 0 , s = 200, d = 17700
    t = 138  , a = 0 , s = 200, d = 17900
    t = 139  , a = 0 , s = 200, d = 18100
    t = 140  , a = 0 , s = 200, d = 18300
    t = 141  , a = 0 , s = 200, d = 18500
    t = 142  , a = 0 , s = 200, d = 18700
    t = 143  , a = 0 , s = 200, d = 18900
    t = 144  , a = 0 , s = 200, d = 19100
    t = 145  , a = 0 , s = 200, d = 19300
    t = 146  , a = 0 , s = 200, d = 19500
    t = 147  , a = 0 , s = 200, d = 19700
    t = 148  , a = 0 , s = 200, d = 19900
    t = 149  , a = 0 , s = 200, d = 20100
    t = 150  , a = 0 , s = 200, d = 20300
    t = 151  , a = 0 , s = 200, d = 20500
    t = 152  , a = 0 , s = 200, d = 20700
    t = 153  , a = 0 , s = 200, d = 20900
    t = 154  , a = 0 , s = 200, d = 21100
    t = 155  , a = 0 , s = 200, d = 21300
    t = 156  , a = 0 , s = 200, d = 21500
    t = 157  , a = 0 , s = 200, d = 21700
    t = 158  , a = 0 , s = 200, d = 21900
    t = 159  , a = 0 , s = 200, d = 22100
    t = 160  , a = 0 , s = 200, d = 22300
    t = 161  , a = 0 , s = 200, d = 22500
    t = 162  , a = 0 , s = 200, d = 22700
    t = 163  , a = 0 , s = 200, d = 22900
    t = 164  , a = 0 , s = 200, d = 23100
    t = 165  , a = 0 , s = 200, d = 23300
    t = 166  , a = 0 , s = 200, d = 23500
    t = 167  , a = 0 , s = 200, d = 23700
    t = 168  , a = 0 , s = 200, d = 23900
    t = 169  , a = 0 , s = 200, d = 24100
    t = 170  , a = 0 , s = 200, d = 24300
    t = 171  , a = 0 , s = 200, d = 24500
    t = 172  , a = 0 , s = 200, d = 24700
    t = 173  , a = 0 , s = 200, d = 24900
    t = 174  , a = 0 , s = 200, d = 25100
    t = 175  , a = 0 , s = 200, d = 25300
    t = 176  , a = 0 , s = 200, d = 25500
    t = 177  , a = 0 , s = 200, d = 25700
    t = 178  , a = 0 , s = 200, d = 25900
    t = 179  , a = 0 , s = 200, d = 26100
    t = 180  , a = 0 , s = 200, d = 26300
    t = 181  , a = 0 , s = 200, d = 26500
    t = 182  , a = 0 , s = 200, d = 26700
    t = 183  , a = 0 , s = 200, d = 26900
    t = 184  , a = 0 , s = 200, d = 27100
    t = 185  , a = 0 , s = 200, d = 27300
    t = 186  , a = 0 , s = 200, d = 27500
    t = 187  , a = 0 , s = 200, d = 27700
    t = 188  , a = 0 , s = 200, d = 27900
    t = 189  , a = 0 , s = 200, d = 28100
    t = 190  , a = 0 , s = 200, d = 28300
    t = 191  , a = 0 , s = 200, d = 28500
    t = 192  , a = 0 , s = 200, d = 28700
    t = 193  , a = 0 , s = 200, d = 28900
    t = 194  , a = 0 , s = 200, d = 29100
    t = 195  , a = 0 , s = 200, d = 29300
    t = 196  , a = 0 , s = 200, d = 29500
    t = 197  , a = 0 , s = 200, d = 29700
    t = 198  , a = 0 , s = 200, d = 29900
    RAMP_DOWN
    t = 199  , a = -2, s = 200, d = 30100
    t = 200  , a = -2, s = 198, d = 30298
    t = 201  , a = -2, s = 196, d = 30494
    t = 202  , a = -2, s = 194, d = 30688
    t = 203  , a = -2, s = 192, d = 30880
    t = 204  , a = -2, s = 190, d = 31070
    t = 205  , a = -2, s = 188, d = 31258
    t = 206  , a = -2, s = 186, d = 31444
    t = 207  , a = -2, s = 184, d = 31628
    t = 208  , a = -2, s = 182, d = 31810
    t = 209  , a = -2, s = 180, d = 31990
    t = 210  , a = -2, s = 178, d = 32168
    t = 211  , a = -2, s = 176, d = 32344
    t = 212  , a = -2, s = 174, d = 32518
    t = 213  , a = -2, s = 172, d = 32690
    t = 214  , a = -2, s = 170, d = 32860
    t = 215  , a = -2, s = 168, d = 33028
    t = 216  , a = -2, s = 166, d = 33194
    t = 217  , a = -2, s = 164, d = 33358
    t = 218  , a = -2, s = 162, d = 33520
    t = 219  , a = -2, s = 160, d = 33680
    t = 220  , a = -2, s = 158, d = 33838
    t = 221  , a = -2, s = 156, d = 33994
    t = 222  , a = -2, s = 154, d = 34148
    t = 223  , a = -2, s = 152, d = 34300
    t = 224  , a = -2, s = 150, d = 34450
    t = 225  , a = -2, s = 148, d = 34598
    t = 226  , a = -2, s = 146, d = 34744
    t = 227  , a = -2, s = 144, d = 34888
    t = 228  , a = -2, s = 142, d = 35030
    t = 229  , a = -2, s = 140, d = 35170
    t = 230  , a = -2, s = 138, d = 35308
    t = 231  , a = -2, s = 136, d = 35444
    t = 232  , a = -2, s = 134, d = 35578
    t = 233  , a = -2, s = 132, d = 35710
    t = 234  , a = -2, s = 130, d = 35840
    t = 235  , a = -2, s = 128, d = 35968
    t = 236  , a = -2, s = 126, d = 36094
    t = 237  , a = -2, s = 124, d = 36218
    t = 238  , a = -2, s = 122, d = 36340
    t = 239  , a = -2, s = 120, d = 36460
    t = 240  , a = -2, s = 118, d = 36578
    t = 241  , a = -2, s = 116, d = 36694
    t = 242  , a = -2, s = 114, d = 36808
    t = 243  , a = -2, s = 112, d = 36920
    t = 244  , a = -2, s = 110, d = 37030
    t = 245  , a = -2, s = 108, d = 37138
    t = 246  , a = -2, s = 106, d = 37244
    t = 247  , a = -2, s = 104, d = 37348
    t = 248  , a = -2, s = 102, d = 37450
    t = 249  , a = -2, s = 100, d = 37550
    t = 250  , a = -2, s = 98 , d = 37648
    t = 251  , a = -2, s = 96 , d = 37744
    t = 252  , a = -2, s = 94 , d = 37838
    t = 253  , a = -2, s = 92 , d = 37930
    t = 254  , a = -2, s = 90 , d = 38020
    t = 255  , a = -2, s = 88 , d = 38108
    t = 256  , a = -2, s = 86 , d = 38194
    t = 257  , a = -2, s = 84 , d = 38278
    t = 258  , a = -2, s = 82 , d = 38360
    t = 259  , a = -2, s = 80 , d = 38440
    t = 260  , a = -2, s = 78 , d = 38518
    t = 261  , a = -2, s = 76 , d = 38594
    t = 262  , a = -2, s = 74 , d = 38668
    t = 263  , a = -2, s = 72 , d = 38740
    t = 264  , a = -2, s = 70 , d = 38810
    t = 265  , a = -2, s = 68 , d = 38878
    t = 266  , a = -2, s = 66 , d = 38944
    t = 267  , a = -2, s = 64 , d = 39008
    t = 268  , a = -2, s = 62 , d = 39070
    t = 269  , a = -2, s = 60 , d = 39130
    t = 270  , a = -2, s = 58 , d = 39188
    t = 271  , a = -2, s = 56 , d = 39244
    t = 272  , a = -2, s = 54 , d = 39298
    t = 273  , a = -2, s = 52 , d = 39350
    t = 274  , a = -2, s = 50 , d = 39400
    t = 275  , a = -2, s = 48 , d = 39448
    t = 276  , a = -2, s = 46 , d = 39494
    t = 277  , a = -2, s = 44 , d = 39538
    t = 278  , a = -2, s = 42 , d = 39580
    t = 279  , a = -2, s = 40 , d = 39620
    t = 280  , a = -2, s = 38 , d = 39658
    t = 281  , a = -2, s = 36 , d = 39694
    t = 282  , a = -2, s = 34 , d = 39728
    t = 283  , a = -2, s = 32 , d = 39760
    t = 284  , a = -2, s = 30 , d = 39790
    t = 285  , a = -2, s = 28 , d = 39818
    t = 286  , a = -2, s = 26 , d = 39844
    t = 287  , a = -2, s = 24 , d = 39868
    t = 288  , a = -2, s = 22 , d = 39890
    t = 289  , a = -2, s = 20 , d = 39910
    t = 290  , a = -2, s = 18 , d = 39928
    t = 291  , a = -2, s = 16 , d = 39944
    t = 292  , a = -2, s = 14 , d = 39958
    t = 293  , a = -2, s = 12 , d = 39970
    t = 294  , a = -2, s = 10 , d = 39980
    t = 295  , a = -2, s = 8  , d = 39988
    t = 296  , a = -2, s = 6  , d = 39994
    STOP
    t = 297  , a = 0 , s = 2  , d = 39998
    

    The program "AccelerationPst130716b" adds an acceleration value ("a" in the output) to the speed value ("s") with each loop of the program.

    You shouldn't need to reset either of these programs to see the output but I thought I'd let you know you can reset the Propeller from PST. Checking and unchecking the DTR box will reset the Propeller.

    Here's the box I'm referring to.

    attachment.php?attachmentid=102827&d=1373999438

    Let me know if you have trouble with either of the attached programs.

    Edit(3/11/15): Warning, the code attached is an old version. There are likely better options available.
    I plan to upload this program or an improved version to my GitHub account
    If there isn't code similar to what is attached here on my on GitHub, send me a message and I'll make and check for any improved versions of the code.
  • Kirk FraserKirk Fraser Posts: 364
    edited 2013-07-16 12:52
    Ok, it all works as you've explained. I thought that blob of metal might be a switch but I couldn't see the button with my old eyes. I can feel it click now though.

    The PST I sent is the same as yours except I removed "Parallax" from the file name since the length is too long for the minimized Propeller Tool as it overwrites other tab names when several are in use.

    So what is next? PID? Or if you're pretty much done, I'd appreciate you looking at my call to your sensor demo as I don't think I have the right method to get the data which goes to the screen.
  • Duane DegnDuane Degn Posts: 10,588
    edited 2013-07-16 13:01
    So what is next? PID? Or if you're pretty much done, I'd appreciate you looking at my call to your sensor demo as I don't think I have the right method to get the data which goes to the screen.

    I'm working on some similar code that will make it easy to adjust the acceleration and maximum speed parameters.

    I've considered adding a magnetic encoder to a threaded rod attached to the stepper on my new CNC machine but I'm not sure if the stepper would behave anywhere near as similar to your hydraulic gear to be a valid test rig. If it is close enough to use for some testing, then I could write the code with my stepper in mind and once I get it working switch the control type from a variable frequency to a PWM duty cycle.

    This is what I'm currently working on.
  • Kirk FraserKirk Fraser Posts: 364
    edited 2013-07-16 13:20
    I know it wouldn't be an exact match for hydraulics but if slow PWM is close then I can probably use the code to revive my dead CNC with a Propeller based controller. So I'll be very interested to see what you find. It would be cool to be able to use the same electronics and firmware for both servos and hydraulics.
  • Kirk FraserKirk Fraser Posts: 364
    edited 2013-07-24 01:03
    Duane,

    Although your algorithm does what you wrote, it doesn't exactly do what I need. It took working to integrate your methods before I realized they do not produce a smoothed trapezoid but a literal S curve. One obvious thing is the fast center section of the curve ought to be flat at 1.0, not going up at 45 degrees. I was suspicious when I saw your ever increasing d-value numbers but didn't figure it out until now. The s-value numbers look like they can be adapted to make a pin go from 0 to 1 and back.
  • Duane DegnDuane Degn Posts: 10,588
    edited 2013-07-24 08:24
    The s-curve shown in post #17 is the displacement with respect to time. The speed curve would be a trapezoid (unsmoothed). This is the speed curve when I graph the output from post #22 in a spreadsheet program.

    attachment.php?attachmentid=102991&d=1374678063

    I left out the displacement since it would distort the scale of the speed curve. This speed curve results from a constant acceleration. As I mentioned previously, I think this would be sufficent for most applications.
    Duane Degn wrote: »
    By using acceleration, the movement should be smooth. You used the work "jerk" which has a technical meaning as well as the usual one most people think about when they hear/use the word. Velocity is the change of position over time, acceleration is the change in velocity over time and the jerk is the change in acceleration over time. In general a constant acceleration is enough for smooth motion.

    If jerk were added to the movement algorithm (unnecessary in my opinion) the speed curve would look something like this.

    attachment.php?attachmentid=102992&d=1374678065

    In this example I used a jerk of 0.05 with a maximum acceleration of 2 (units are not defined in this example, I just choose numbers to illustrate the principles). Again the maximum speed is 200. I didn't do the calculations necessary to get the displacements to be equal in both sets of data.

    I imagine this second graph is what you are looking for? I still think a constant acceleration (first graph) would be fine and you don't need the added complication of a variable acceleration.

    When you drop an item it undergoes constant acceleration and it ramps up to speed nice and smooth. Even though the first speed graph looks like it has abrupt changes, the displacement of the object undergoes nice smooth movement as illustrated by the displacement curve (post #17).

    Edit: I'm sure there are applications which would benefit from the acceleration changing gradually, I don't think they are very common. I'm concerned with how using jerk in a motion algorithm will affect the performance of a PID system. My initial thoughts are it would make the PID system sluggish but I don't have experience to back up this assumption.
    565 x 360 - 14K
    573 x 338 - 14K
  • Kirk FraserKirk Fraser Posts: 364
    edited 2013-07-24 18:13
    Duane Degn wrote: »
    If jerk were added to the movement algorithm (unnecessary in my opinion) the speed curve would look something like this.

    attachment.php?attachmentid=102992&d=1374678065

    In this example I used a jerk of 0.05 with a maximum acceleration of 2 (units are not defined in this example, I just choose numbers to illustrate the principles). Again the maximum speed is 200. I didn't do the calculations necessary to get the displacements to be equal in both sets of data.

    I imagine this second graph is what you are looking for? I still think a constant acceleration (first graph) would be fine and you don't need the added complication of a variable acceleration.

    Yes, this second graph is what I'm looking for. There are two reasons, one is I'm trying for human like motion and humans can control their motions that precisely. Also, some professional motion control systems which control larger industrial systems than the one I'm building come pre-programmed with the S-curve solution. I believe that is because of the large weights being moved and stabilized. I believe the same behavior can had with an affordable Propeller based solution (amplifying if needed) instead of having to choose the expensive control systems professionals use. For toy robots and other lightweight motion applications where the mass doesn't create much jerk, I'm sure you are correct a simple trapezoid would work fine. My current robot is designed to lift 250 lbs and a future robot may be built to lift 1000 lbs so I do want the software that produces the second graph.
    Duane Degn wrote: »
    When you drop an item it undergoes constant acceleration and it ramps up to speed nice and smooth. Even though the first speed graph looks like it has abrupt changes, the displacement of the object undergoes nice smooth movement as illustrated by the displacement curve (post #17).

    Edit: I'm sure there are applications which would benefit from the acceleration changing gradually, I don't think they are very common. I'm concerned with how using jerk in a motion algorithm will affect the performance of a PID system. My initial thoughts are it would make the PID system sluggish but I don't have experience to back up this assumption.

    Unfortunately I have no experience with PID or new insights on it at present. The only thing I know I want is to have it maintain its position against all external and internal forces when it has reached its last commanded position and there is no current input command. Any further functionality is welcome.
  • Duane DegnDuane Degn Posts: 10,588
    edited 2013-07-24 21:29
    Yes, this second graph is what I'm looking for. There are two reasons, . . .

    The more I think about ramping the acceleration and not just ramping the speed, the more I like the idea. I still think a constant acceleration would give smooth movement but it sure seems using a ramped acceleration has advantages.

    Here's the displacement curve again with constant acceleration:

    attachment.php?attachmentid=103005&d=1374726338

    With jerk added to the equation, the displacement curve has a gentler transition at the beginning and end.

    attachment.php?attachmentid=103006&d=1374726339

    I don't think it would be very difficult to add jerk to a motion algorithm.
    726 x 611 - 25K
  • Kirk FraserKirk Fraser Posts: 364
    edited 2013-07-24 22:14
    Duane Degn wrote: »
    With jerk added to the equation, the displacement curve has a gentler transition at the beginning and end.

    attachment.php?attachmentid=103006&d=1374726339

    I don't think it would be very difficult to add jerk to a motion algorithm.

    Excellent!
Sign In or Register to comment.