Reputation: 73
I'm creating the "framework" to control a Hexapod. So (simplifying) I have a Servo class:
class Servo(object):
...
def setAngle(self, angle):
##Executes order to move servo to specified angle
##Returns False if not possible or True if OK
offsetAngle=self.offset+angle
if not self.checkServoAngle(offsetAngle):
#Angle not within servo range
return=False
else:
pwmvalue=self._convAngleToPWM(offsetAngle)
self._setPWM(pwmvalue)
self.angle=value
return=True
...
and a child HexBone class:
class HexBone(Servo):
## Servo.__init__ override:
def __init__(self, I2C_ADDRESS, channel, length, startAngle, reversed=False, minAngle=NULL, maxAngle):
self = Servo(I2C_ADDRESS, channel, reversed, minAngle, maxAngle)
#Setting bone length
self.length=length
#Positions bone in Starting Position
self.setAngle(startAngle)
and also a HexLimb class:
class HexLimb(object):
def __init__(self, I2C_ADDRESS, femurLength, tibiaLength, femurInv, tibiaInv):
#Setting precision of Limb Positioning
self.precision=1
#Setting i2c address and servo channels
self.femur = HexBone(I2C_ADDRESS, 1, femurLength, 45, femurInv, 5, 190)
self.tibia = HexBone(I2C_ADDRESS, 2, tibiaLength, 90, tibiaInv, 5, 190)
def calcPosition(self):
L1=self.femur.length
L2=self.tibia.length
try:
a1=90-self.femur.angle#########!!!!!!
a2=180-self.tibia.angle
self.x=L1*math.cos(math.radians(a1))+L2*math.cos(math.radians(a1-a2))
self.y=L1*math.sin(math.radians(a1))+L2*math.sin(math.radians(a1-a2))
except:
return False
else:
return True
In the HexLimb class whenever I do: self.femur.setAngle(30) I want to call self.calcPosition() to recalculate the limb's tip position.
I've been searching all over and couldn't found any answer...Am I doing it the wrong way?
(edited accordingly comments bellow)
Upvotes: 0
Views: 1341
Reputation: 32580
Your HexLimb
needs to know about the HexBones
attached to it to calculate its position. But the HexBones
, being Servo
s, also need to know about the HexLimb
they are attached to so that they can trigger a re-calculation of the limb's position.
One solution is to keep a back-reference on the HexBones
to the HexLimb
they're attached to.
In this example, I create a back-reference called limb
in HexLimb.__init__()
on both bones - you could also call it parent
to be more generic about it.
from random import random
class Servo(object):
"""Servo controller"""
def __init__(self):
self.angle = 0
def set_angle(self, angle):
print "Setting angle to %s" % angle
self.angle = angle
# Let limb recalculate its position
self.limb.calc_position()
class HexBone(Servo):
"""A bone that can be attached to a limb and moved."""
def __init__(self, length):
super(HexBone, self).__init__()
self.length = length
# Will be assigned later when attached to a limb
self.limb = None
class HexLimb(object):
"""A limb consisting of several bones."""
def __init__(self):
self.femur = HexBone(42)
self.femur.limb = self
self.tibia = HexBone(30)
self.tibia.limb = self
def calc_position(self):
print "Calculating position..."
# Something that needs self.femur and self.tibia
self.x = self.femur.length * random()
self.y = self.tibia.length * random()
def extend(self):
self.tibia.set_angle(0) # extend knee
left_leg = HexLimb()
left_leg.extend()
Upvotes: 1
Reputation: 73
Taking what Lukas Graf suggested i've changed the code a little bit in order to maintain the Servo class more general. Basically Servo (and inherently its child class HexBone) take a callback function reference as an optional argument for init (which defaults to None). When calling Servo.setAngle in the end this will execute the callback function. Code is as follows:
from random import random
class Servo(object):
"""Servo controller"""
def __init__(self, callback=None): #Servo takes a callback function as argument
self.angle = 0
self.callback=callback
def set_angle(self, angle):
print("Setting angle to %s" % angle)
self.angle = angle
# After angle set executes the callback function
if self.callback is not None: self.callback()
class HexBone(Servo):
"""A bone that can be attached to a limb and moved."""
def __init__(self, length, callback):
super(HexBone, self).__init__(callback)
self.length = length
class HexLimb(object):
"""A limb consisting of several bones."""
def __init__(self):
self.femur = HexBone(42, self.calc_position)
self.femur.limb = self
self.tibia = HexBone(30, self.calc_position)
self.tibia.limb = self
def calc_position(self):
print("Calculating position...")
# Something that needs self.femur and self.tibia
self.x = self.femur.length * random()
self.y = self.tibia.length * random()
def extend(self):
self.tibia.set_angle(0) # extend knee
left_leg = HexLimb()
left_leg.extend()
Upvotes: 0