Я пишу платформу Python для симуляции распределенных скоплений датчиков. Идея заключается в том, что конечный пользователь может написать собственный узел, состоящий из поведения SensorNode (связь, ведение журнала и т. Д.), А также реализовать ряд различных датчиков.
Пример ниже кратко демонстрирует концепцию.
#prewritten
class Sensor(object):
def __init__(self):
print "Hello from Sensor"
#...
#prewritten
class PositionSensor(Sensor):
def __init__(self):
print "Hello from Position"
Sensor.__init__(self)
#...
#prewritten
class BearingSensor(Sensor):
def __init__(self):
print "Hello from Bearing"
Sensor.__init__(self)
#...
#prewritten
class SensorNode(object):
def __init__(self):
print "Hello from SensorNode"
#...
#USER WRITTEN
class MySensorNode(SensorNode,BearingSensor,PositionSensor):
def CustomMethod(self):
LogData={'Position':position(), 'Bearing':bearing()} #position() from PositionSensor, bearing() from BearingSensor
Log(LogData) #Log() from SensorNode
НОВОЕ РЕДАКТИРОВАНИЕ:
Во-первых, обзор того, чего я пытаюсь достичь:
Я пишу симулятор для моделирования алгоритмов разведки роя с особым акцентом на мобильные сенсорные сети Эти сети состоят из множества маленьких роботов, передающих данные отдельных датчиков для создания сложной сенсорной карты окружающей среды.
Основная цель этого проекта - разработать платформу для моделирования, которая предоставляет абстрактные интерфейсы для датчиков, чтобы те же функции, реализованные пользователем, могли быть напрямую перенесены в роботизированный рой со встроенным Linux. Поскольку целью является роботизированная реализация, мне нужно спроектировать так, чтобы программный узел вел себя одинаково и имел доступ только к информации, которую имел бы физический узел.
Как часть механизма моделирования, я буду предоставлять набор классов, моделирующих различные типы датчиков и различные типы узлов датчиков. Я хочу абстрагироваться от всей этой сложности от пользователя так, чтобы все, что пользователь должен сделать, это определить, какие датчики присутствуют на узле, и какой тип узла датчика (мобильный, фиксированное положение) реализуется.
Вначале я думал, что каждый датчик будет предоставлять метод read (), который будет возвращать соответствующие значения, однако, прочитав ответы на вопрос, я вижу, что, возможно, было бы полезно использовать более описательные имена методов (.distance (), .position (), .bearing () и т. д.).
Первоначально я хотел использовать отдельные классы для датчиков (с общими предками), чтобы более технический пользователь мог легко расширить один из существующих классов, чтобы создать новый датчик, если он пожелает. Например:
Sensor
|
DistanceSensor(designed for 360 degree scan range)
| | |
IR Sensor Ultrasonic SickLaser
(narrow) (wider) (very wide)
Причина, по которой я изначально думал о множественном наследовании (хотя оно и частично нарушает отношения наследования IS-A), была вызвана принципом, лежащим в основе системы моделирования. Позвольте мне объяснить:
Внедренный пользователем MySensorNode не должен иметь прямого доступа к своей позиции в среде (сродни роботу, доступ косвенный через интерфейс датчика), аналогично датчики не должны знать, где они находятся. Однако это отсутствие прямых знаний создает проблему, поскольку все возвращаемые значения датчиков зависят от их положения и ориентации в среде (которую необходимо смоделировать для получения правильных значений).
SensorNode, как класс, реализованный в библиотеках симуляции, отвечает за отрисовку MySensorNode в среде Pygame - таким образом, это единственный класс, который должен иметь прямой доступ к положению и ориентации узла датчика в среде.
SensorNode также отвечает за перемещение и вращение в окружающей среде, однако это перемещение и вращение является побочным эффектом приведения двигателя в действие.
Под этим я подразумеваю, что роботы не могут напрямую изменять свое положение в мире, все, что они могут сделать, - это обеспечивать питание двигателей, а движение внутри мира является побочным эффектом взаимодействия двигателей с окружающей средой. Мне нужно точно смоделировать это в симуляции.
Итак, для перемещения пользовательские функции могут использовать:
motors(50,50)
Этот вызов, как побочный эффект, изменит положение узла в мире.
Если SensorNode был реализован с использованием композиции, SensorNode.motors (...) не сможет напрямую изменять переменные экземпляра (например, положение), и MySensorNode.draw () не будет разрешен в SensorNode.draw (), поэтому SensorNode imo должен быть реализован с использованием наследования.
С точки зрения датчиков, преимущество композиции для такой проблемы очевидно, MySensorNode состоит из нескольких датчиков - достаточно сказать.
Однако проблема, как я вижу, заключается в том, что Сенсорам нужен доступ к их положению и ориентации в мире, и если вы используете композицию, вы получите вызов, подобный:
>>> PosSensor.position((123,456))
(123,456)
Опять же, подумав, вы можете передать себя датчику при инициализации, например:
PosSensor = PositionSensor(self)
потом позже
PosSensor.position()
однако для этого PosSensor.position () потребуется доступ к информации, локальной для экземпляра (передаваемой как self во время init ()), так зачем вообще вызывать PosSensor, если вы можете получить доступ к информации локально? Также передача вашего экземпляра объекту, из которого вы состоите, кажется просто не совсем правильной, пересекая границы инкапсуляции и сокрытия информации (даже несмотря на то, что python мало что делает для поддержки идеи сокрытия информации).
Если бы решение было реализовано с использованием множественного наследования, эти проблемы исчезли бы:
class MySensorNode(SensorNode,PositionSensor,BearingSensor):
def Think():
while bearing()>0:
# bearing() is provided by BearingSensor and in the simulator
# will simply access local variables provided by SensorNode
# to return the bearing. In robotic implementation, the
# bearing() method will instead access C routines to read
# the actual bearing from a compass sensor
motors(100,-100)
# spin on the spot, will as a side-effect alter the return
# value of bearing()
(Ox,Oy)=position() #provided by PositionSensor
while True:
(Cx,Cy)=position()
if Cx>=Ox+100:
break
else:
motors(100,100)
#full speed ahead!will alter the return value of position()
Надеюсь, эта редакция прояснила некоторые вещи, если у вас есть какие-либо вопросы, я с радостью постараюсь их прояснить
СТАРЫЕ ВЕЩИ:
Когда создается объект типа MySensorNode, необходимо вызывать все конструкторы из суперклассов. Я не хочу усложнять пользователю необходимость писать собственный конструктор для MySensorNode, который вызывает конструктор из каждого суперкласса. В идеале, я бы хотел, чтобы это произошло:
mSN = MySensorNode()
# at this point, the __init__() method is searched for
# and SensorNode.__init__() is called given the order
# of inheritance in MySensorNode.__mro__
# Somehow, I would also like to call all the other constructors
# that were not executed (ie BearingSensor and PositionSensor)
Любое понимание или общие комментарии приветствуются,
Ура :) 1062 *
СТАРЫЙ РЕДАКТИРОВАТЬ:
Делать что-то вроде:
#prewritten
class SensorNode(object):
def __init__(self):
print "Hello from SensorNode"
for clss in type(self).__mro__:
if clss!=SensorNode and clss!=type(self):
clss.__init__(self)
Это работает, так как self является экземпляром MySensorNode. Однако это решение грязное.