diff --git a/Examples/BB2B_networking.py b/Examples/BB2B_networking.py index 327926b..c384a40 100644 --- a/Examples/BB2B_networking.py +++ b/Examples/BB2B_networking.py @@ -1,3 +1,7 @@ +import sys +from os import path +sys.path.append(path.abspath(path.join(path.dirname(__file__), '..'))) + from LocalParticipant import LocalParticipant from Things.DifferentialDrive import DifferentialDrive from Things.TouchSensor import TouchSensor @@ -5,13 +9,15 @@ import time # Create a local participant for handling communcation # using default settings (UDP communciation over port 7681) -participant = LocalParticipant() +participant = LocalParticipant(port=7681, local_port=7682) # The robot's propulsion is a differential drive bb2b = DifferentialDrive(participant) +bb2b.model_url = "https://passer.life/extras/ant1_transparent.png" + # It has a touch sensor at the front left of the roboid -touch_left = TouchSensor(bb2b) +touch_left = TouchSensor(parent=bb2b) # and other one on the right -touch_right = TouchSensor(bb2b) +touch_right = TouchSensor(parent=bb2b) # Do forever: while True: @@ -26,6 +32,6 @@ while True: bb2b.SetWheelVelocity(wheel_speed_left, wheel_speed_right) # Update the roboid state - bb2b.Update(True) + participant.Update() # and sleep for 100ms time.sleep(100) diff --git a/LocalParticipant.py b/LocalParticipant.py index 3caa71b..0a0c1e4 100644 --- a/LocalParticipant.py +++ b/LocalParticipant.py @@ -1,5 +1,6 @@ import socket import threading +import time from Participant import Participant from Thing import Thing @@ -24,7 +25,6 @@ class LocalParticipant(Participant): Currently, only UDP communication is supported """ - publishInterval = 3000 # 3 seconds buffer = None ## The network ID of the participant @@ -34,20 +34,25 @@ class LocalParticipant(Participant): thread = None name = "Participant" - def __init__(self, port=7681, ip_address = "0.0.0.0", remote=False, udp_socket = None): - super().__init__(ip_address, port) - self.ip_address = ip_address - self.port = port + def __init__(self, port=7681, ip_address="0.0.0.0", local_port=0, remote=False, udp_socket = None): + super().__init__(ip_address = ip_address, port = port) + # self.ip_address = ip_address + # self.port = port + if local_port == 0: + local_port = port + self.local_port = local_port self.others = [] self.network_id = 0 self.buffer = bytearray(256) self.thing_msg_processors = {} self.new_thing_handlers = [] + self.publishInterval = 3000 # 3 seconds + if remote == False: self.udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) self.udp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) - self.udp_socket.bind(("0.0.0.0", port)) + self.udp_socket.bind(("0.0.0.0", self.local_port)) self.AddParticipant(self.ip_address, self.port) self.thread = threading.Thread(target = self.Receiver) @@ -70,7 +75,7 @@ class LocalParticipant(Participant): def AddParticipant(self, ip_address, port): # print(f'{self.name} Add participant {ip_address} {port}') - remote_participant = LocalParticipant(ip_address, port, remote=True, udp_socket=self.udp_socket) + remote_participant = Participant(ip_address = ip_address, port = port) remote_participant.network_id = len(self.others) self.others.append(remote_participant) return remote_participant @@ -90,18 +95,18 @@ class LocalParticipant(Participant): #region Send - def SendThingInfo(self, thing): - self.Send(ThingMsg(self.network_id, thing)) - self.Send(NameMsg(self.network_id, thing)) - self.Send(ModelUrlMsg(self.network_id, thing)) + def SendThingInfo(self, owner, thing): + self.Send(owner, ThingMsg(self.network_id, thing)) + self.Send(owner, NameMsg(self.network_id, thing)) + self.Send(owner, ModelUrlMsg(self.network_id, thing)) - def Send(self, msg): + def Send(self, owner, msg): buffer_size = msg.Serialize([self.buffer]) if buffer_size <= 0: return True - # print(f'{self.name} send {self.buffer[0]} to {self.ip_address} {self.port}') - self.udp_socket.sendto(self.buffer[:buffer_size], (self.ip_address, self.port)) + print(f'{self.name} send {self.buffer[0]} to {owner.ip_address} {owner.port}') + self.udp_socket.sendto(self.buffer[:buffer_size], (owner.ip_address, owner.port)) return True def Publish(self, msg): @@ -129,14 +134,14 @@ class LocalParticipant(Participant): remote_participant = self.AddParticipant(remote_ip_address, remote_port) self.ReceiveData(data, remote_participant) - def ReceiveData(self, data, remote_participant): + def ReceiveData(self, data, sender): msgId = data[0] # print(f'msg {msgId} ') match msgId: case ParticipantMsg.id: - self.ProcessClientMsg(remote_participant, ParticipantMsg(data)) + self.ProcessClientMsg(sender, ParticipantMsg(data)) case NetworkIdMsg.id: - self.ProcessNetworkIdMsg(remote_participant, NetworkIdMsg(data)) + self.ProcessNetworkIdMsg(sender, NetworkIdMsg(data)) # case InvestigateMsg.id: # self.ProcessInvestigateMsg(InvestigateMsg(data)) case ThingMsg.id: @@ -156,9 +161,9 @@ class LocalParticipant(Participant): print(f'{self.name} receive network id {self.network_id} -> {msg.network_id}') if self.network_id != msg.network_id: self.network_id = msg.network_id - # print(f'sending all things {len(Thing.allThings)}') + print(f'sending all things {len(self.things)}') for thing in self.things: - sender.SendThingInfo(thing) + self.SendThingInfo(sender, thing) # self.Send(NameMsg(self.network_id, thing)) def ProcessInvestigateMsg(self, data: bytearray): diff --git a/Messages/ThingMsg.py b/Messages/ThingMsg.py index 262d414..133b115 100644 --- a/Messages/ThingMsg.py +++ b/Messages/ThingMsg.py @@ -20,7 +20,10 @@ class ThingMsg(IMessage): if thing is not None: self.thing_id = thing.id self.thing_type = thing.type - self.parent_id = thing.parent_id + if thing.parent is not None: + self.parent_id = thing.parent.id + else: + self.parent_id = 0 def Serialize(self, buffer_ref): if self.network_id is None or self.thing_id is None: diff --git a/Participant.py b/Participant.py index 537bc0c..8e361c3 100644 --- a/Participant.py +++ b/Participant.py @@ -11,7 +11,7 @@ class Participant: """ ## The Ip Address of a participant. When the participant is local, this contains 0.0.0.0 - self.ip_addres = ip_address + self.ip_address = ip_address ## The port number for UDP communication with the participant. This is 0 for isolated participants. self.port = port ## The network Id to identify the participant. @@ -21,7 +21,7 @@ class Participant: ## The things managed by this participant self.things = set({ None }) - def Add(self, thing, check_id): + def Add(self, thing, check_id = True): """! Add a new thing for this participant. @param thing The thing to add @param check_id When true, the thing ID of the thing is checked. If it is 0, a new thing Id will be assigned. diff --git a/Thing.py b/Thing.py index a0b4635..e095fd8 100644 --- a/Thing.py +++ b/Thing.py @@ -22,6 +22,12 @@ class Thing: def __init__(self, owner = None, network_id = 0, thing_id = 0, type = Type.Undetermined, parent = None, name = None): """! Create a new thing """ + ## The parent thing + self.parent = None + if parent is not None: + owner = parent.owner + self.parent = parent + ## The participant owning this thing self.owner = owner ## The network ID of this thing @@ -32,11 +38,6 @@ class Thing: ## The type of the thing self.type = type - ## The parent thing - self.parent = 0 - if parent is not None: - self.parent_id = parent.id - ## The name of the thing self.name = name ## An URL pointing to the location where a model of the thing can be found @@ -52,7 +53,7 @@ class Thing: self.angular_velocity: Spherical = Spherical.zero self.pose_updated = 0x00 # the bits indicate which fields have been updated - + self.owner.Add(self) def update(self, currentTime): pass diff --git a/Things/TouchSensor.py b/Things/TouchSensor.py index 7e4ffd6..c0a867c 100644 --- a/Things/TouchSensor.py +++ b/Things/TouchSensor.py @@ -6,7 +6,7 @@ class TouchSensor(Thing): def __init__(self, owner = None, parent = None): """! Create a touch sensor """ - super().__init__(owner, parent) + super().__init__(owner = owner, parent = parent) ## Value which is true when the sensor is touching something, false otherwise self.touched_somthing = False