2020-11-17 20:24:55 +00:00
|
|
|
import numpy as np
|
|
|
|
import time
|
|
|
|
|
|
|
|
from robot import ControlledRobot
|
|
|
|
from pid_controller import PIDController
|
2020-11-18 20:53:32 +00:00
|
|
|
from mpc_controller import MPCController
|
2020-11-17 20:24:55 +00:00
|
|
|
from event_listener import EventListener
|
|
|
|
|
|
|
|
|
2021-09-07 20:31:28 +00:00
|
|
|
class ControlCommander:
|
2020-11-22 14:57:53 +00:00
|
|
|
valid_controller_types = {'pid': PIDController,
|
|
|
|
'mpc': MPCController}
|
2020-11-17 20:24:55 +00:00
|
|
|
|
2020-11-22 14:57:53 +00:00
|
|
|
def __init__(self, id_ip_dict, controller_type='pid'):
|
|
|
|
"""
|
|
|
|
|
|
|
|
:param id_ip_dict: dictionary containing robot marker id and ip of the robot, e.g. { 12: '10.10.11.91' }
|
|
|
|
:param controller_type: string 'pid', 'mpc'; or dictionary with robot id and controller type string, e.g. { 12: 'mpc', 13: 'pid'}
|
|
|
|
"""
|
|
|
|
self.robots = {}
|
|
|
|
for id, ip in id_ip_dict.items():
|
|
|
|
self.robots[id] = ControlledRobot(id, ip)
|
|
|
|
|
|
|
|
for id, r in self.robots.items():
|
2020-11-17 20:24:55 +00:00
|
|
|
r.connect()
|
2020-11-18 20:53:32 +00:00
|
|
|
|
2020-11-22 14:57:53 +00:00
|
|
|
if type(controller_type) == dict:
|
|
|
|
for id, ctype in controller_type.items():
|
2021-09-07 20:31:28 +00:00
|
|
|
if ctype in ControlCommander.valid_controller_types:
|
|
|
|
self.robots[id].attach_controller(ControlCommander.valid_controller_types[ctype]())
|
2020-11-22 14:57:53 +00:00
|
|
|
else:
|
|
|
|
raise Exception(f"invalid controller type {ctype} specified for robot {id}. "
|
2021-09-07 20:31:28 +00:00
|
|
|
f"valid controller types are {list(ControlCommander.valid_controller_types.keys())}")
|
|
|
|
elif controller_type in ControlCommander.valid_controller_types:
|
2020-11-22 14:57:53 +00:00
|
|
|
for id, r in self.robots.items():
|
2021-09-07 20:31:28 +00:00
|
|
|
r.attach_controller(ControlCommander.valid_controller_types[controller_type]())
|
2020-11-22 14:57:53 +00:00
|
|
|
else:
|
|
|
|
raise Exception(f"invalid controller type {controller_type} specified. valid controller types are "
|
2021-09-07 20:31:28 +00:00
|
|
|
f"{list(ControlCommander.valid_controller_types.keys())}")
|
2020-11-17 20:24:55 +00:00
|
|
|
|
|
|
|
self.event_listener = EventListener(event_server=('127.0.0.1', 42424))
|
|
|
|
|
|
|
|
self.current_robot_index = 0
|
|
|
|
self.controlling = False
|
|
|
|
self.running = False
|
|
|
|
|
|
|
|
def run(self):
|
2020-11-22 14:57:53 +00:00
|
|
|
unconnected_robots = list(filter(lambda r: not r.connected, self.robots.values()))
|
2020-11-17 20:24:55 +00:00
|
|
|
if len(unconnected_robots) > 0:
|
|
|
|
print(f"warning: could not connect to the following robots: {unconnected_robots}")
|
|
|
|
return
|
|
|
|
|
|
|
|
all_detected = False
|
|
|
|
while not all_detected:
|
2020-11-22 14:57:53 +00:00
|
|
|
undetected_robots = list(filter(lambda r: None in r.get_measurement(), self.robots.values()))
|
2020-11-17 20:24:55 +00:00
|
|
|
all_detected = len(undetected_robots) == 0
|
|
|
|
if not all_detected:
|
|
|
|
print(f"warning: no measurements available for the following robots: {undetected_robots}")
|
|
|
|
time.sleep(0.5)
|
2021-09-09 22:43:02 +00:00
|
|
|
print("all robots detected -> starting control")
|
2020-11-17 20:24:55 +00:00
|
|
|
|
|
|
|
self.running = True
|
|
|
|
while self.running:
|
|
|
|
while not self.event_listener.event_queue.empty():
|
|
|
|
event = self.event_listener.event_queue.get()
|
|
|
|
self.handle_event(event)
|
|
|
|
|
|
|
|
def handle_event(self, event):
|
|
|
|
# handle events from opencv window
|
|
|
|
print("event: ", event)
|
2021-09-07 20:31:28 +00:00
|
|
|
if event[0] == 'click': # non-blocking move to target pos
|
2020-11-17 20:24:55 +00:00
|
|
|
target = event[1]
|
|
|
|
target_pos = np.array([target['x'], target['y'], target['angle']])
|
2020-11-22 14:57:53 +00:00
|
|
|
controlled_robot_id = list(self.robots.keys())[self.current_robot_index]
|
|
|
|
self.robots[controlled_robot_id].move_to_pos(target_pos)
|
2021-09-07 20:31:28 +00:00
|
|
|
elif event[0] == 'move_blocking': # blocking move to specified target position
|
|
|
|
target = event[1]
|
|
|
|
target_pos = np.array([target['x'], target['y'], target['angle']])
|
|
|
|
controlled_robot_id = list(self.robots.keys())[self.current_robot_index]
|
|
|
|
|
|
|
|
# initialize move and wait for the robot to reach the target position
|
|
|
|
self.robots[controlled_robot_id].move_to_pos(target_pos, blocking=True)
|
|
|
|
#time.sleep(0.5)
|
|
|
|
# send confirmation to the server which initiated the command
|
|
|
|
self.event_listener.send_reply("ack\n".encode())
|
2020-11-17 20:24:55 +00:00
|
|
|
elif event[0] == 'key':
|
|
|
|
key = event[1]
|
2021-09-06 22:21:51 +00:00
|
|
|
if key == 16777235: # arrow up
|
2020-11-17 20:24:55 +00:00
|
|
|
self.controlling = not self.controlling
|
|
|
|
if not self.controlling:
|
|
|
|
print("disable control")
|
2020-11-22 14:57:53 +00:00
|
|
|
for _, r in self.robots.items():
|
2020-11-17 20:24:55 +00:00
|
|
|
r.stop_control()
|
|
|
|
else:
|
|
|
|
print("enable control")
|
2020-11-22 14:57:53 +00:00
|
|
|
for _, r in self.robots.items():
|
2020-11-17 20:24:55 +00:00
|
|
|
r.start_control()
|
2021-09-06 22:21:51 +00:00
|
|
|
elif key == 16777236: # left
|
2020-11-17 20:24:55 +00:00
|
|
|
# switch controlled robot
|
|
|
|
self.current_robot_index = (self.current_robot_index + 1) % len(self.robots)
|
2020-11-22 14:57:53 +00:00
|
|
|
controlled_robot_id = list(self.robots.keys())[self.current_robot_index]
|
|
|
|
robot = self.robots[controlled_robot_id]
|
2020-11-17 20:24:55 +00:00
|
|
|
print(f"controlled robot: {robot.id}")
|
|
|
|
elif key == 113 or key == 27: # q or ESCAPE
|
|
|
|
print("quit!")
|
|
|
|
for r in self.robots:
|
|
|
|
r.stop_control()
|
|
|
|
self.running = False
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
2020-11-22 14:57:53 +00:00
|
|
|
id_ip_dict = {
|
|
|
|
#11: '10.10.11.88',
|
2021-09-09 22:43:02 +00:00
|
|
|
#12: '192.168.1.12',
|
2021-09-06 22:21:51 +00:00
|
|
|
13: '192.168.1.13',
|
|
|
|
#14: '10.10.11.89',
|
2020-11-22 14:57:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
# controller_type = {12: 'mpc', 13: 'pid'}
|
2021-09-09 22:43:02 +00:00
|
|
|
controller_type = 'mpc'
|
2020-11-22 14:57:53 +00:00
|
|
|
|
2021-09-07 20:31:28 +00:00
|
|
|
rc = ControlCommander(id_ip_dict, controller_type=controller_type)
|
2020-11-17 20:24:55 +00:00
|
|
|
rc.run()
|