working version with two robots

This commit is contained in:
Simon Pirkelmann 2020-09-09 18:12:12 +02:00
parent 280aee75ee
commit c98760a2c7

View File

@ -61,6 +61,26 @@ class Robot:
self.euler = None self.euler = None
self.ip = ip self.ip = ip
self.socket = socket.socket()
# variables for measurements
self.tms_0 = None
self.xm_0 = None
self.tms = None
self.xms = None
# currently active control
self.u1 = 0.0
self.u2 = 0.0
def connect(self):
# connect to robot
try:
self.socket.connect((self.ip, 1234)) # connect to robot
except socket.error:
print("could not connect to socket")
sys.exit(1)
def f_ode(t, x, u): def f_ode(t, x, u):
# dynamical model of the two-wheeled robot # dynamical model of the two-wheeled robot
@ -89,9 +109,9 @@ class RemoteController:
self.anim_stopped = False self.anim_stopped = False
#self.robots = [Robot(14, '192.168.1.103')] self.robots = [Robot(11, '192.168.1.101'), Robot(14, '192.168.1.103')]
#self.robots = [Robot(15, '192.168.1.102')] #self.robots = [Robot(15, '192.168.1.102')]
self.robots = [Robot(id, ip)] #self.robots = [Robot(id, ip)]
self.robot_ids = {} self.robot_ids = {}
for r in self.robots: for r in self.robots:
@ -99,20 +119,13 @@ class RemoteController:
self.valid_cmds = ['forward', 'backward', 'turn left', 'turn right'] self.valid_cmds = ['forward', 'backward', 'turn left', 'turn right']
# connect to robot
self.rc_socket = socket.socket()
#self.rc_socket = None
try:
for r in self.robots:
self.rc_socket.connect((r.ip, 1234)) # connect to robot
except socket.error:
print("could not connect to socket")
sys.exit(1)
# socket for movement commands # socket for movement commands
self.comm_socket = socket.socket() self.comm_socket = socket.socket()
self.comm_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self.comm_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
for robot in self.robots:
robot.connect()
#self.comm_socket.bind((socket.gethostname(), 1337)) #self.comm_socket.bind((socket.gethostname(), 1337))
self.comm_socket.bind(('', 1337)) self.comm_socket.bind(('', 1337))
self.comm_socket.listen(5) self.comm_socket.listen(5)
@ -124,11 +137,6 @@ class RemoteController:
self.ts = np.array([]) self.ts = np.array([])
self.xs = [] self.xs = []
# variables for measurements
self.tms_0 = None
self.xm_0 = None
self.tms = None
self.xms = None
# variable for mpc open loop # variable for mpc open loop
self.ol_x = None self.ol_x = None
@ -142,10 +150,6 @@ class RemoteController:
# pid parameters # pid parameters
self.controlling = False self.controlling = False
# currently active control
self.u1 = 0.0
self.u2 = 0.0
# animation # animation
self.fig = plt.figure() self.fig = plt.figure()
self.ax = self.fig.add_subplot(2,2,1) self.ax = self.fig.add_subplot(2,2,1)
@ -187,7 +191,7 @@ class RemoteController:
# integrator # integrator
self.r = scipy.integrate.ode(f_ode) self.r = scipy.integrate.ode(f_ode)
self.omega_max = 5.0 self.omega_max = 5.0
self.control_scaling = 0.2 self.control_scaling = 0.3
#self.omega_max = 13.32 #self.omega_max = 13.32
@ -289,21 +293,21 @@ class RemoteController:
# save measured position and angle for plotting # save measured position and angle for plotting
measurement = np.array([r.pos[0], r.pos[1], r.euler]) measurement = np.array([r.pos[0], r.pos[1], r.euler])
if self.tms_0 is None: if r.tms_0 is None:
self.tms_0 = time.time() r.tms_0 = time.time()
self.xm_0 = measurement r.xm_0 = measurement
self.mutex.acquire() self.mutex.acquire()
try: try:
self.tms = np.array([0.0]) r.tms = np.array([0.0])
self.xms = measurement r.xms = measurement
finally: finally:
self.mutex.release() self.mutex.release()
else: else:
self.mutex.acquire() self.mutex.acquire()
try: try:
self.tms = np.vstack((self.tms, time.time() - self.tms_0)) r.tms = np.vstack((r.tms, time.time() - r.tms_0))
self.xms = np.vstack((self.xms, measurement)) r.xms = np.vstack((r.xms, measurement))
finally: finally:
self.mutex.release() self.mutex.release()
@ -388,8 +392,8 @@ class RemoteController:
self.t = time.time() self.t = time.time()
elif event.key == pygame.K_DOWN: elif event.key == pygame.K_DOWN:
self.controlling = False self.controlling = False
if self.rc_socket: if self.robot_ids[robot_id].socket:
self.rc_socket.send('(0.0,0.0)\n') self.robot_ids[robot_id].socket.send('(0.0,0.0)\n')
elif event.key == pygame.K_0: elif event.key == pygame.K_0:
self.target = np.array([0,0,0]) self.target = np.array([0,0,0])
elif event.key == pygame.K_PLUS: elif event.key == pygame.K_PLUS:
@ -403,20 +407,20 @@ class RemoteController:
elif event.key == pygame.K_ESCAPE: elif event.key == pygame.K_ESCAPE:
print("quit!") print("quit!")
self.controlling = False self.controlling = False
if self.rc_socket: if self.robot_ids[robot_id].socket:
self.rc_socket.send('(0.0,0.0)\n') self.robot_ids[robot_id].socket.send('(0.0,0.0)\n')
self.anim_stopped = True self.anim_stopped = True
return return
elif event.key == pygame.QUIT: elif event.key == pygame.QUIT:
print("quit!") print("quit!")
self.controlling = False self.controlling = False
if self.rc_socket: if self.robot_ids[robot_id].socket:
self.rc_socket.send('(0.0,0.0)\n') self.robot_ids[robot_id].socket.send('(0.0,0.0)\n')
self.anim_stopped = True self.anim_stopped = True
return return
if self.mpc: if self.mpc:
x_pred = self.get_measurement_prediction() x_pred = self.get_measurement_prediction(robot_id)
tmpc_start = time.time() tmpc_start = time.time()
@ -424,9 +428,9 @@ class RemoteController:
angles_unwrapped = np.unwrap([x_pred[2], self.target[2]]) # unwrap angle to avoid jump in data angles_unwrapped = np.unwrap([x_pred[2], self.target[2]]) # unwrap angle to avoid jump in data
error_ang = np.abs(angles_unwrapped[0] - angles_unwrapped[1]) error_ang = np.abs(angles_unwrapped[0] - angles_unwrapped[1])
#print("error pos = ", error_pos) #print("error pos = ", error_pos)
print(" error_ang = {}, target = {}, angle = {}".format(error_ang, self.target[2], x_pred[2])) print("error_pos = {}, error_ang = {}".format(error_pos, error_ang))
if error_pos > 0.1 or error_ang > 0.35: if error_pos > 0.075 or error_ang > 0.35:
# solve mpc open loop problem # solve mpc open loop problem
res = self.ols.solve(x_pred, self.target) res = self.ols.solve(x_pred, self.target)
@ -461,28 +465,28 @@ class RemoteController:
for i in range(0, self.mstep): # option to use multistep mpc if len(range) > 1 for i in range(0, self.mstep): # option to use multistep mpc if len(range) > 1
u1 = us1[i] u1 = us1[i]
u2 = us2[i] u2 = us2[i]
if self.rc_socket: if self.robot_ids[robot_id].socket:
self.rc_socket.send('({},{})\n'.format(u1, u2)) self.robot_ids[robot_id].socket.send('({},{})\n'.format(u1, u2))
if i < self.mstep: if i < self.mstep:
time.sleep(self.dt) time.sleep(self.dt)
self.t = time.time() # save time the most recent control was applied self.t = time.time() # save time the most recent control was applied
def get_measurement_prediction(self): def get_measurement_prediction(self, robot_id):
# get measurement # get measurement
self.mutex.acquire() self.mutex.acquire()
try: try:
window = 3 window = 3
last_measurement = copy.deepcopy(self.xms[-window:]) last_measurement = copy.deepcopy(self.robot_ids[robot_id].xms[-window:])
#print("last_measurements = {}".format(last_measurement)) #print("last_measurements = {}".format(last_measurement))
#print("mean = {}".format(np.mean(last_measurement, axis=0))) #print("mean = {}".format(np.mean(last_measurement, axis=0)))
last_measurement = np.mean(last_measurement, axis=0) last_measurement = np.mean(last_measurement, axis=0)
last_time = copy.deepcopy(self.tms[-1]) last_time = copy.deepcopy(self.robot_ids[robot_id].tms[-1])
finally: finally:
self.mutex.release() self.mutex.release()
# prediction of state at time the mpc will terminate # prediction of state at time the mpc will terminate
self.r.set_f_params(np.array([self.u1 * self.omega_max, self.u2 * self.omega_max])) self.r.set_f_params(np.array([self.robot_ids[robot_id].u1 * self.omega_max, self.robot_ids[robot_id].u2 * self.omega_max]))
self.r.set_initial_value(last_measurement, last_time) self.r.set_initial_value(last_measurement, last_time)