我正在创建控制Hexapod的“框架”。 所以(简化)我有一个Servo类:
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
...
和一个孩子HexBone类:
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)
以及HexLimb类:
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
每当我这样做时,在HexLimb类中: self.femur.setAngle(30)我想调用self.calcPosition()重新计算肢体的尖端位置。
我一直在寻找,但找不到任何答案......我这样做的方式是错误的吗?
(相应地编辑评论)
答案 0 :(得分:1)
您的HexLimb
需要了解附加到其中的HexBones
以计算其排名。但是HexBones
,Servo
,也需要了解它们所附着的HexLimb
,以便它们可以触发重新计算肢体的位置。
一种解决方案是在HexBones
上保持反向引用至HexLimb
。
在这个示例中,我在limb
的两个骨骼上创建了一个名为HexLimb.__init__()
的反向引用 - 您也可以将其称为parent
,使其更加通用。
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()
答案 1 :(得分:0)
考虑到Lukas Graf的建议我已经改变了一些代码,以保持Servo类更通用。 基本上,Servo(以及它的子类HexBone)将回调函数引用作为 init 的可选参数(默认为None)。 最后调用 Servo.setAngle 时,将执行回调函数。 代码如下:
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()