2.6 Python Servo Motion classes (for linear and rotational motion)

When seeking a way to get rid of that pesky single actuator known as the ServoMotion actuator, I came across a 2.49 solution by cyboarg_ar.
His solution created a linear servo that was identacle to the servo motion actuator. I didn’t want all of it (ie reference objects), but wanted it as simple as possible, so I got rid of quite a bit. I also wanted a rotational servo, where you could set a torque and desired rotation speed.
Here are the two classes I ended up with, and they work pretty well.

class rotServo:    '''Acts like a servo motion actuator, but rotationally'''
    integral = mathutils.Vector([0,0,0])
    prev_error = mathutils.Vector([0,0,0])
    pid = [30.0, 0.5, 0]
    def __init__(self, owner, torque_max = [0,0,0], torque_min = [0,0,0], rotV = [0,0,0], local=True):
        '''Sets initial values for the servo'''
        self.torque_max = mathutils.Vector(torque_max)
        self.torque_min = mathutils.Vector(torque_min)
        self.rotV = mathutils.Vector(rotV)
        self.owner = owner
        self.local = local
    def update(self):
        '''This function must be run each time you want the servo to update'''
        cur_speed = mathutils.Vector(self.owner.getAngularVelocity(self.local))
        error = self.rotV - cur_speed
        self.integral += error
        derivative  = error - self.prev_error
        self.prev_error = error
        action = error * self.pid[0] + self.integral  * self.pid[1] + derivative  * self.pid[2]
        for i in range(3):
            if self.torque_min[i] != None and action[i] < self.torque_min[i]:
                action[i] = self.torque_min[i]
            if self.torque_max[i] != None and action[i] > self.torque_max[i]:
                action[i] = self.torque_max[i]
        self.owner.applyTorque(action, self.local)


class linServo:
    '''Acts like a servo motion actuator'''
    integral = mathutils.Vector([0,0,0])
    prev_error = mathutils.Vector([0,0,0])
    pid = [30.0, 0.5, 0]
    def __init__(self, owner, force_max = [0,0,0], force_min = [0,0,0], linV = [0,0,0], local=True):
        '''Sets initial values for the servo'''
        self.force_max = mathutils.Vector(force_max)
        self.force_min = mathutils.Vector(force_min)
        self.linV = mathutils.Vector(linV)
        self.owner = owner
        self.local = local
    def update(self):
        '''This function must be run each time you want the servo to update'''
        cur_speed = mathutils.Vector(self.owner.getLinearVelocity(self.local))
        error = self.linV - cur_speed
        self.integral += error
        derivative  = error - self.prev_error
        self.prev_error = error
        action = error * self.pid[0] + self.integral  * self.pid[1] + derivative  * self.pid[2]
        for i in range(3):
            if self.force_min[i] != None and action[i] < self.force_min[i]:
                action[i] = self.force_min[i]
            if self.force_max[i] != None and action[i] > self.force_max[i]:
                action[i] = self.force_max[i]
        self.owner.applyForce(action, self.local)

Instructions for use:

Create a servo by creating an instance of the class, and dump it somewhere:

cont.owner['rot_servo'] = rotServo(cont.owner, torque_max=[5,5,5], torque_min=[-5,-5,-5])

Give it a target velocity:

cont.owner['rot_servo'].rotV = [5,0,0]

And every frame you want it to take effect, update it:

cont.owner['rot_servo'].update()

The only difference between a rotational servo and a linear one is that:
- torque_max vs force_max
- torque_min vs force_min
- rotV vs linV

Hopefully someone else finds this useful, and if anyone sees any improvements, feel free to do so, and post back here.

<b>Bugs:</b>
- There seems to be a little drifting, but I'm not sure why.

Does this create a Actuator for the Logic Bricks?

Nope, it’s a python-only implementation.

Nice work !!

Could you make a simple .blend with it working?
I see how it works, but I don’t really know how to apply it.

just a rigid body pinned to another object?

How would you set the target object with this, or rather change the code to use a target object?

@blueprint
Here you go:
demo.blend (498 KB)

@kevin:
What do you mean by ‘target object’? A reference object that the object moves/rotates with? That is not currencly implimented. If you mean like the track-toactuator, this script does not do ‘track to’ style stuff. (Though it soon may if BPR keeps pressuring me!)

Thats exactly what I mean, and I know its not implemented I’m just not sure how I would get that to work with your script, but I’ll open a thread in the discussion forum so I don’t clutter this thread:), for now I’ll just take a look at your example file and see if I can figure something out.