Python - 扩展类实例方法

时间:2013-12-27 16:29:57

标签: python

我正在创建控制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()重新计算肢体的尖端位置。

我一直在寻找,但找不到任何答案......我这样做的方式是错误的吗?

(相应地编辑评论)

2 个答案:

答案 0 :(得分:1)

您的HexLimb需要了解附加到其中的HexBones以计算其排名。但是HexBonesServo,也需要了解它们所附着的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()