0

I have a python script that reads the input signal of a joystick via pygame and passes that input to a motor controller.

Now i would like to add a ramping function. let's say to ramp up to the input value with a given delay. if the input of the joystick is '100' it should only pass that value to the motor controller after the delay has passed and 'fade' in between.

Also, it would be a plus to define the ramp. (linear or logarithmic curve)

Is there a simple way of doing that? thanks for your help!

user3603948
  • 153
  • 3
  • 12

1 Answers1

0

A simple class could look like this:

class RampUp:
    def __init__(self):
        self.value = 0
        self.target = 0
        self.next = self.__next__
        self.calc = None

    def __iter__(self):
        return self

    def __next__(self):
        if self.value == self.target:
            return self.value
        else:
            self.value = self.calc(self.value, self.target)
            return self.value 

this class simply holds a state, is iterable and calls a function that calculates a new value in every iteration.

A simple "ramp" function that simply increases the output value by a given delta could be:

def simple(value, target):
    if value < target:
        value = min(value + 1, target)
    else:
        value = max(value - 1, target)
    return value

Example of usage:

gen = RampUp()
gen.calc = simple
gen.target = 20
for _ in xrange(100):
    # that's the value you pass to your motor controller
    print next(gen)

Another example ramp function that is more complex:

def smooth(value, target):
    # maximum acceleration is 2
    delta_max = 2
    # minimun acceleration is 0.5
    delta = max(0.5, (abs(target) - abs(target-value)) / 10.)
    delta = min(delta, delta_max)
    if value < target:
        value = min(value + delta, target)
    else:
        value = max(value - delta, target)
    return value

In response to your comment:

def with_step(step):            
    def simple(value, target):
        if value < target:
            value = min(value + step, target)
        else:
            value = max(value - step, target)
        return value            
    return simple

gen = RampUp()
gen.target = 20
# you could move this line into the class
# reaches the target value in 12 steps
gen.calc = with_step((gen.target - gen.value)/12.)
sloth
  • 99,095
  • 21
  • 171
  • 219
  • thank you for your input! I tried the simple code, which simply adds one step each iteration, which is nice, but i would like to also specify the time it takes to 'fade' from start value to output value. How could i do that with the more complex function? – user3603948 Feb 18 '15 at 20:53
  • You could alter the function in a way that it diesn't simply add or substract 1, but another value. See my updated answer. Of course it depends on how often you call `next(gen)`. In my example, if you call it once per second, it will reach its target value of `20` in 12 seconds. You can simply adjust the values to fit your requirements. – sloth Feb 19 '15 at 08:10