Shop OBEX P1 Docs P2 Docs Learn Events
Accel curve help needed by math wiz. — Parallax Forums

Accel curve help needed by math wiz.

T ChapT Chap Posts: 4,223
edited 2008-10-27 02:55 in Propeller 1
I have been searching here and google for a while with no luck finding accel formulas that could easily apply (no extra cogs for float) to fix this curve shown below.

Can anyone suggest a quick easy formula to adjust fix the red curve to look more like the blue one?

The idea is, the fix needs to be spread over 4320 loops, and maintain the same start value(0) and end value(MaxSpeed) so that the curve still ends up at the same place at the same time it always did to preserve the profile.

It seems if there is no better way to fix the main curve, then the offset would simply count up to some number, then count back down, possibly even into the negative to retain the same MaxSpeed/Time end point.

Post Edited (Originator) : 10/25/2008 10:31:12 PM GMT
486 x 463 - 56K

Comments

  • SRLMSRLM Posts: 5,045
    edited 2008-10-26 00:47
    It appears to be like the following image:

    ·attachment.php?attachmentid=56395


    This is an image of x2 and x1/2 . The former is on the bottom, and the latter is above. I may be able to come up with a solution on how to convert, but it will take a little while.

    Post Edited (SRLM) : 10/26/2008 12:54:24 AM GMT
    902 x 880 - 23K
  • T ChapT Chap Posts: 4,223
    edited 2008-10-26 01:14
    What I did as a temporary workaround that improves the curve:
    
    PUB AccelForward(len)    'len = distance to travel based on 30% new target pos
          aRate := (MinSpeed - MaxSpeed)/Len        '    = 34  at 30%
          dRate := 10 '(MinSpeed - MaxSpeed)/Len  
          a3 := len/2
          posold := pos
          repeat  len                               
            accel   := ((accel - (aRate + A3))  #> MaxSpeed) <# MinSpeed 
            'a3 is an offset using the length (len) / 2,   start subtracting the distance moved from the len/2 
            a3 :=  a3 -  ||(pos-posold)    #> 0                     
            pos := pos  + 1                                                                        
            waitcnt(accel + cnt)
            if newpos < pos
              Quit                                     
          decel := accel
    
    
    



    This is crude but effective to put the curve on the top side.
  • SRLMSRLM Posts: 5,045
    edited 2008-10-26 01:40
    Okay. Here's what I have. It's purely a mathematical proof: I leave it up to you to figure out how to use it and tie it into your data.
    So, that said, let's begin.

    You have two curves:
    The given curve: xn = c
    The desired curve: x1/n = a
    Where c and a are the values given at point x (the point in your sample list)

    ''The proof:
     
    x[sup]n[/sup] = c                     ''What you have
    log[sub]x[/sub]c = n                  ''Convert in order to get n out
    1 / n = 1 / log[sub]x[/sub]c          ''Divide both sides by n and log[sub]x[/sub]c
    x[sup]1/n[/sup] = x [sup]1 / log[sub]x[/sub]c[/sup] = a        ''Substitute in for 1/n
    
    

    So to convert, just use x 1 / logxc· to get the value that you want.
  • SRLMSRLM Posts: 5,045
    edited 2008-10-26 01:46
    Can you give some sample points so that I can test? The above proof is good for converting between a root function and an exponential, but your data might not fit into that range.

    I'll give an example of how to use it:

     a = x [sup]1 / log[sub]x[/sub]c[/sup]      ''Your equation to use
     
    ''To find out the desired data at point .5, and supposing that you measured a value of .25 at that point
     
    a = (.5)[sup]1 / log[sub](.5)[/sub](.25)[/sup]
    a = .707107
    
  • T ChapT Chap Posts: 4,223
    edited 2008-10-26 02:14
    Thanks a lot for that SRLM. I will have to put a lot of thought into this to apply it, since the actually numbers used are inverted so to speak, the faster the speed = a smaller number (using waitcnt to set speed between loops). This will have to go on hold till tomorrow but I will let you know what I came up with.
  • SRLMSRLM Posts: 5,045
    edited 2008-10-26 03:45
    Wait: so the graph that you gave me is NOT what you actually measured and want? It's something else? If so, then my solution may or may not work, and you may or may not be able to do some more math to get the equation that you really want.

    And, truth be told, I mostly looked at your graph, and skimmed over the rest. Without the full background, it's difficult to make the project in my mind. But, with the graph I can still do the math. [noparse]:)[/noparse]
  • T ChapT Chap Posts: 4,223
    edited 2008-10-26 21:47
    SRLM, The graph I drew was for illustration purposes only.

    I have a better idea now, either predefine 10 reference points over the distance of the accel curve, or, define one point as the 'knee' and calculate the rest using a curve/angle value to determine the sharpness/roundness of the curve.

    I like the idea much better to be able to semi-graphically define the curve, only in this case the graphic is on paper rather than a GUI.


    PUB AccelForward(len)      |   X            'len = ramp up distance to travel based on 30% new target pos  
         'phase 1 =  MinSpeed(=175_000) - MaxSpeed(=25_000) = 150_000   /   
          phaseLen  =   len/10          '   example   distance 4320   /   10 points  = 432 
          
         index := 0
         phasecounter  := 0
         PCindex  := 0
         accel := MinSpeed     '175000  example
        
          AccelPhase[noparse][[/noparse] 0]  := 0                   'predefined curve values  
          AccelPhase[noparse][[/noparse] 1]   :=  20000         
          AccelPhase[noparse][[/noparse] 2]   :=  30000     
          AccelPhase[noparse][[/noparse] 3]   :=  50000
          AccelPhase[noparse][[/noparse] 4]   :=  90000
          AccelPhase[noparse][[/noparse] 5]   :=  110000
          AccelPhase[noparse][[/noparse] 6]   :=  130000
          AccelPhase[noparse][[/noparse] 7]   :=  135000
          AccelPhase[noparse][[/noparse] 8]   :=  140000
          AccelPhase[noparse][[/noparse] 9]   :=  145000
          AccelPhase[noparse][[/noparse] 10] :=   150000 
       
         PhaseOffset[noparse][[/noparse] 1] :=   (AccelPhase[noparse][[/noparse] 1]  - AccelPhase[noparse][[/noparse] 0] )/ phaseLen        'offset value for each iteration 
         PhaseOffset[noparse][[/noparse] 2] :=   (AccelPhase[noparse][[/noparse] 2]  - AccelPhase[noparse][[/noparse] 1] )/ phaseLen      
         PhaseOffset[noparse][[/noparse] 3] :=   (AccelPhase[noparse][[/noparse] 3]  - AccelPhase[noparse][[/noparse] 2] )/ phaseLen    
         PhaseOffset[noparse][[/noparse] 4] :=   (AccelPhase[noparse][[/noparse] 4]  - AccelPhase[noparse][[/noparse] 3] )/ phaseLen      
         PhaseOffset[noparse][[/noparse] 5] :=   (AccelPhase[noparse][[/noparse] 5]  - AccelPhase[noparse][[/noparse] 4] )/ phaseLen
         PhaseOffset[noparse][[/noparse] 6] :=   (AccelPhase[noparse][[/noparse] 6]  - AccelPhase[noparse][[/noparse] 5] )/ phaseLen   
         PhaseOffset[noparse][[/noparse] 7] :=   (AccelPhase[noparse][[/noparse] 7]  - AccelPhase[noparse][[/noparse] 6] )/ phaseLen      
         PhaseOffset[noparse][[/noparse] 8] :=   (AccelPhase[noparse][[/noparse] 8]  - AccelPhase[noparse][[/noparse] 7] )/ phaseLen    
         PhaseOffset[noparse][[/noparse] 9] :=   (AccelPhase[noparse][[/noparse] 9]  - AccelPhase[noparse][[/noparse] 8] )/ phaseLen      
         PhaseOffset[noparse][[/noparse] 0] :=   (AccelPhase[noparse][[/noparse] 10]  - AccelPhase[noparse][[/noparse] 9] )/ phaseLen   
    
         PhaseChange[noparse][[/noparse] 1]  := phaseLen              'values to indicate when to change to next PhaseOffset value   
         PhaseChange[noparse][[/noparse] 2]  := phaseLen * 2
         PhaseChange[noparse][[/noparse] 3]  := phaseLen * 3
         PhaseChange[noparse][[/noparse] 4]  := phaseLen * 4
         PhaseChange[noparse][[/noparse] 5]  := phaseLen * 5
         PhaseChange[noparse][[/noparse] 6]  := phaseLen * 6
         PhaseChange[noparse][[/noparse] 7]  := phaseLen * 7
         PhaseChange[noparse][[/noparse] 8]  := phaseLen * 8
         PhaseChange[noparse][[/noparse] 9]  := phaseLen * 9
         'PhaseChange[noparse][[/noparse] 10]  := Len                 'doesn't need 10
    
     {{  accel is derived by MinSpeed - MaxSpeed +  offset .  An example is 175000 - 25000 =  150000 + offset
      the speed of the motor is determined by PWM, PWM is derived from an Error produced by a Profile generating routine 
      below, which increments/decrements a position counter (pos).  A PID calculator compares an 
      encoder value to the position,   and computes a corresponding PWM motor speed to compensate for the Error.  
      Using waitcnt with the Minimum speed  as the starting (slower) speed, amounts are subtracted from the 
      Minimum speed to increase the speed. 
            }} 
    
          repeat  len                       
            accel   := ((accel  -  PhaseOffset[noparse][[/noparse]Index] ) < # MinSpeed)  #> MaxSpeed  'reduce waitcnt  by Phase[noparse][[/noparse]index]                   
            pos := pos  + 1
            if  phasecounter ==  PhaseChange[noparse][[/noparse] PCindex]    'if phasecounter has reached 1rst phase end, or ex 432  (len/10)... 
                  index++                                          'then go to next phaseOffset value                  
                  PCindex++                                    'and increment the PhaseChange index
            phasecounter+                                  'increment the phasecounter
            waitcnt(accel + cnt)                         'waitcnt = value to set speed of pulses     
            if newpos < pos                               'if new position has been rec'd, get out and go decel somewhere else
              Quit                                     
          decel := accel       'let decel  value be same value as value that accel left off at  
    
    
    

    Post Edited (Originator) : 10/26/2008 9:55:11 PM GMT
    470 x 603 - 94K
  • SRLMSRLM Posts: 5,045
    edited 2008-10-26 22:59
    I like your second version better. I'm not sure what you mean by knee, but here's my impression: the first is a series of points, and you extrapolate in a linear fasion to get the data that you want. The second is an equation given by two points and a "curve amount". The easiest thing would be if you could come up with some sort of equation: then it just takes a single line of code to calculate what you want. Otherwise, you're going to have a big ifelse statement (one statement for each predefined point).
  • T ChapT Chap Posts: 4,223
    edited 2008-10-26 23:18
    SRLM said...
    The easiest thing would be if you could come up with some sort of equation: then it just takes a single line of code to calculate what you want. Otherwise, you're going to have a big ifelse statement (one statement for each predefined point).

    Actually the code above is what is working out fine for 10 predefined points, it take the 10 points and calculates the 10 ranges of offset values, there are no other if statements needed as the counter bumps up the index keeping everything working at the right time.

    Thanks for the advice, very helpful.
  • SRLMSRLM Posts: 5,045
    edited 2008-10-27 02:55
    For that though, you need about 30 lines of predefined code. You have to find and decide which point to use as offsets, and your graph will just be a collection of lines. An equation is much more dynamic: you don't need any sort of predefined data. (or at least not as much)
Sign In or Register to comment.