async def car_routine(startt, startx, starty, manager): await asyncio.sleep(startt) car = Car(startx, starty) manager.cars.append(car) x, y = car.aDestX, car.aDestY cli = await CarWebsocket.create(base_url="ws://localhost:8765") # request a parking space await cli.send_parking_request(wsmodels.Location(float(x), float(y)), {}) car.drawing = True # Receive the parking allocation information space = await cli.receive(wsmodels.ParkingAllocationMessage) car.set_allocated_destination(space.lot.location.longitude, space.lot.location.latitude) await cli.send_parking_acceptance(space.lot.id) # TODO await confirmation of acceptance while True: # Send the location of the car at time intervals, while listening for deallocation if manager.stop_flag: break try: await asyncio.shield( asyncio.wait_for( cli.receive(wsmodels.ParkingCancellationMessage), 3)) except futures.TimeoutError: pass x, y = car.get_position(time.time()) await cli.send_location(wsmodels.Location(float(x), float(y)))
async def set_allocated_destination(self, lot, now): self.aDestX = lot.location.latitude self.aDestY = lot.location.longitude # now = time.time() # cut the last waypoint short to car's current place and time lat, long = self.get_position(now) add = get_route(wsmodels.Location(lat, long), lot.location, now, self.speed) if len(self.waypoints) > 1: if self.waypoints[-2].time < now: self.waypoints = self.waypoints[:-1] else: self.waypoints = self.waypoints[:-2] self.waypoints += add # self.waypoints[-1].time = now # # self.waypoints[-1].lat = lat # self.waypoints[-1].long = long # # self.waypoints += get_route(wsmodels.Location(lat, long), lot.location, now, self.speed) attempt = Attempt(self.waypoints[-1].time, 20, self) self.targetid = lot.id await self.manager.lotdict[lot.id].register(attempt)
async def hello(websocket, path): # receive a request m = await websocket.recv() print(m) # request = json.loads(request) # message = deserialize_ws_message(request) # send an allocation message = serialize_model( wsmodels.ParkingAllocationMessage( wsmodels.ParkingLot(1, "x", 1.0, wsmodels.Location(200.0, 300.0)))) await websocket.send(message) deallocation = wsmodels.ParkingCancellationMessage(1) while True: await websocket.recv() if random.randint(1, 10) == 1: await asyncio.sleep(1) await websocket.send(serialize_model(deallocation))
def __init__(self, starttime, loc, dest, manager): self.startX = loc.latitude self.startY = loc.longitude self.destX = dest.latitude self.destY = dest.longitude self.waypoints = [] self.drawing = True self.drawhozpos = True self.drawverpos = True self.drawup = True self.starttime = starttime self.bestLot = None self.tried = [] self.manager = manager self.first_attempt = None self.targetid = None closeness = 250 self.speed = 20 stupidity = 0.5 self.waypoints.append(Waypoint(starttime, self.startX, self.startY)) currentX = self.startX currentY = self.startY lasttime = time.time() while geodistance(currentX, currentY, self.destX, self.destY) > closeness: # pick a random place to go next, that is probably but not definitely closer to the destination mu = (currentX + self.destX) * 0.5 sigma = abs(currentX - self.destX) * stupidity newX = random.normalvariate(mu, sigma) mu = (currentY + self.destY) * 0.5 sigma = abs(currentY - self.destY) * stupidity newY = random.normalvariate(mu, sigma) p = self.manager.point_to_location( self.manager.random_car.randint(1, 9) * self.manager.height / 10, self.manager.random_car.randint(1, 9) * self.manager.width / 10) newX = p.longitude newY = p.latitude # distance = math.sqrt((currentX - newX)**2 + (currentY - newY)**2) distance = geodistance(currentX, currentY, newX, newY) duration = distance / self.speed self.waypoints += get_route(wsmodels.Location(currentX, currentY), wsmodels.Location(newX, newY), lasttime, self.speed) currentX = newX currentY = newY # self.waypoints.append(Waypoint(lasttime + duration, newX, newY)) lasttime += duration bestLot = None bestDistance = 10000000000000 # once close enough to the destination, find the nearest parking lot for ilot in manager.lots: currentDistance = geodistance(currentX, currentY, ilot.lot.location.latitude, ilot.lot.location.longitude) if currentDistance < bestDistance: bestDistance = currentDistance bestLot = ilot # drive to the closest lot duration = bestDistance / self.speed # arrival = lasttime + duration # self.waypoints.append(Waypoint(arrival, bestLot.lot.location.latitude, bestLot.lot.location.longitude)) self.waypoints += get_route(wsmodels.Location(currentX, currentY), bestLot.lot.location, lasttime, self.speed) self.bestLot = bestLot attempt = Attempt(self.waypoints[-1].time, 20, self) self.first_attempt = attempt self.tried.append(bestLot) self.targetid = bestLot.lot.id
async def run_tk(self, root, interval): w = tk.Canvas(root, width=self.width * 1.5, height=self.height) w.pack() last_interval = time.time() for i in range(11): w.create_rectangle(i * self.width * 0.1 - (self.width * 0.025), 0, i * self.width * 0.1 + (self.width * 0.025), self.height, fill="grey", width=0) for i in range(11): w.create_rectangle(0, i * self.height * 0.1 - (self.height * 0.025), self.width, i * self.height * 0.1 + (self.height * 0.025), fill="grey", width=0) w.create_line(0, i * self.height * 0.1, self.width, i * self.height * 0.1, fill="yellow", dash=(5, 5)) for i in range(10): w.create_line(i * self.width * 0.1, 0, i * self.width * 0.1, self.height, dash=(5, 5), fill="yellow") try: while not self.stop_flag: w.delete("ani") now = time.time() for car in self.cars: if car.drawing: x, y = self.loc_to_point( wsmodels.Location(*car.get_position(now))) if car.reallocated: fill = "red" else: fill = "blue" w.create_oval(x, y, x + 5, y + 5, width=0, fill=fill, tags="ani") for rogue in self.rogues: if rogue.drawing: if now > rogue.starttime: x, y = self.loc_to_point( wsmodels.Location(*rogue.get_position(now))) if rogue.drawup: if rogue.drawverpos: x -= 5 else: x += 5 else: if rogue.drawhozpos: y -= 5 else: y += 5 if x <= self.width: w.create_oval(x, y, x + 5, y + 5, width=0, fill='black', tags="ani") w.delete("outline") for simlot in self.lots: x, y = self.loc_to_point(simlot.lot.location) available = int(20 * simlot.available / simlot.lot.capacity) dxy = self.width * 0.05 offsetw = self.width * 0.025 offseth = self.height * 0.025 # shadow w.create_rectangle(x + available + offsetw, y + offseth - available + 4, x + available + dxy + offsetw, y + dxy + offseth - available, tags="outline", fill="#444444444444", stipple="gray75", width=0) w.create_polygon(x + available + offsetw, y + dxy + offseth - available - 2, x + available + dxy + offsetw, y + dxy + offseth - available - 2, x + offsetw + dxy, y + dxy + offseth, fill="#444444444444", tags="outline", width=0, stipple="gray75") # colourful bit if simlot.available == 0: red = "ffff" green = "0000" else: if simlot.available < simlot.lot.capacity * 0.5: red = "ffff" green = hex( int(65535 * 2 * (simlot.available / simlot.lot.capacity)))[2:] else: red = hex( int(65535 * 2 * (1 - (simlot.available / simlot.lot.capacity))) )[2:] green = "ffff" w.create_rectangle(x + self.width * 0.025, y + self.height * 0.025 - available, x + dxy + self.width * 0.025, y + dxy + self.height * 0.025, width=0, fill="#" + red + green + "0000", tags="ani") # outline of roof w.create_rectangle(x + self.width * 0.025, y + self.height * 0.025 - available, x + dxy + self.width * 0.025, y + dxy + self.height * 0.025 - available, tags="outline") #roof point if red != "0" and green != "0": darkred = hex( int(65535 * ( 1 - (simlot.available / simlot.lot.capacity))))[2:] darkgreen = hex( int(65535 * (simlot.available / simlot.lot.capacity)))[2:] else: darkred = "0000" darkgreen = "8888" dark = "#" + darkred + darkgreen + "0000" roofcenterx = x + offsetw + (dxy * 0.5) roofcentery = y + offseth + (dxy * 0.25) - available rooftopleftx = x + offsetw rooftoplefty = y + offseth - available rooftoprightx = x + dxy + offsetw rooftoprighty = y + offseth - available roofbottomrightx = x + dxy + offsetw roofbottomrighty = y + offseth - available + dxy roofbottomleftx = x + offsetw roofbottomlefty = y + offseth - available + dxy w.create_polygon(roofcenterx, roofcentery, rooftopleftx, rooftoplefty, rooftoprightx, rooftoprighty, fill=dark, tags="outline") w.create_polygon(roofcenterx, roofcentery, roofbottomrightx, roofbottomrighty, rooftoprightx, rooftoprighty, fill=dark, tags="outline") w.create_line(roofbottomleftx, roofbottomlefty, roofcenterx, roofcentery, tags="outline") w.create_line(roofbottomleftx, rooftoplefty, roofcenterx, roofcentery, tags="outline") w.create_line(roofbottomrightx, roofbottomlefty, roofcenterx, roofcentery, tags="outline") w.create_line(roofbottomrightx, rooftoplefty, roofcenterx, roofcentery, tags="outline") # outline of wall w.create_rectangle(x + self.width * 0.025, y + dxy + self.height * 0.025 - available, x + dxy + self.width * 0.025, y + dxy + self.height * 0.025, tags="outline") w.delete("graph") now = time.time() if now - last_interval >= 0.5: last_interval = now self.stats[Stats.LOTUTILITY].append( self.stats[Stats.LOTUTILITY][-1]) for g in range(len(self.graphs)): graph = self.graphs[g] graph.draw(w, self.width * 1.1, self.height * 0.1 + (g * 0.5 * self.height), self.width * 1.4, self.height * 0.4 + (g * 0.5 * self.height)) root.update() await asyncio.sleep(interval) root.destroy() except tk.TclError as e: if "application has been destroyed" not in e.args[0]: raise
def point_to_location(self, x: float, y: float) -> wsmodels.Location: """Assuming (0, 0) x/y maps to Location(0, 0), compute the Location for an arbitrary x, y point """ return wsmodels.Location(x / SCALE, y / SCALE)
async def car_routine(startt, start_loc, manager): await asyncio.sleep(startt) car_id = str(uuid4()) cli = await CarWebsocket.create( base_url=manager.app_url.replace('http', 'ws') + "/ws", user_id=car_id) car = Car(start_loc, manager, cli) manager.cars.append(car) # x, y = car.aDestX, car.aDestY destws = manager.point_to_location(random.randint(0, manager.width), random.randint(0, manager.height)) dest = restmodels.Location(destws.latitude, destws.longitude) # TODO this was originally setting everything to 0 - do this properly later # request a parking space logger.info(f'requesting allocation for car {car_id}') waiting = True while waiting and not manager.stop_flag: await cli.send_parking_request(dest, {}) car.drawing = True futs = [ cli.receive(wsmodels.ParkingAllocationMessage), cli.receive(wsmodels.ErrorMessage) ] (fut, ), *_ = await asyncio.wait(futs, return_when=asyncio.FIRST_COMPLETED) space = fut.result() logger.debug('got result: {}'.format(space)) if not isinstance(space, wsmodels.ErrorMessage): break await asyncio.sleep(1) if not manager.stop_flag: logger.info(f"allocation recieved: for car {car_id}: '{space._type}'") now = time.time() await car.set_allocated_destination(space.lot, now) await cli.send_parking_acceptance(space.lot.id) x, y = car.get_position(time.time()) await cli.send_location(wsmodels.Location(float(x), float(y))) if not manager.stop_flag: await cli.receive(wsmodels.ConfirmationMessage) logger.info("conf recieved") while not manager.stop_flag and not car.finished: # Send the location of the car at time intervals, while listening for deallocation try: deallocation = await asyncio.shield( asyncio.wait_for( cli.receive(wsmodels.ParkingDeallocationMessage), 3)) except futures.TimeoutError: deallocation = None if deallocation is not None and not car.finished: logger.info("Recieved deallocation") print("deallocated") car.reallocated = True waiting = True while waiting and not manager.stop_flag: await cli.send_parking_request(dest, {}) car.drawing = True futs = [ cli.receive(wsmodels.ParkingAllocationMessage), cli.receive(wsmodels.ErrorMessage) ] (fut, ), *_ = await asyncio.wait( futs, return_when=asyncio.FIRST_COMPLETED) space = fut.result() logger.debug('got result: {}'.format(space)) if not isinstance(space, wsmodels.ErrorMessage): break await asyncio.sleep(1) if not manager.stop_flag: logger.info( f"allocation recieved: for car {car_id}: '{space._type}'") now = time.time() await car.set_allocated_destination(space.lot, now) await cli.send_parking_acceptance(space.lot.id) logger.info(f'<Car {car_id}>: heartbeat ** send location') x, y = car.get_position(time.time()) # TODO this will probably change with the API await cli.send_location(wsmodels.Location(float(x), float(y)))