def update_allocation_metrics(self, allocation_time): allocation_info = self.auctioneer.winning_bid.get_allocation_info() task = Task.get_task(allocation_info.new_task.task_id) self.performance_tracker.update_allocation_metrics(task, allocation_time) if allocation_info.next_task: task = Task.get_task(allocation_info.next_task.task_id) self.performance_tracker.update_allocation_metrics(task, only_constraints=True)
def get_next_task(self, task): task_last_node = self.stn.get_task_node_ids(task.task_id)[-1] if self.stn.has_node(task_last_node + 1): next_task_id = self.stn.nodes[task_last_node + 1]['data'].task_id try: next_task = Task.get_task(next_task_id) except DoesNotExist: self.logger.warning("Task %s is not in db", next_task_id) next_task = Task.create_new(task_id=next_task_id) return next_task
def check_termination_test(self): unallocated_tasks = Task.get_tasks_by_status( TaskStatusConst.UNALLOCATED) allocated_tasks = Task.get_tasks_by_status(TaskStatusConst.ALLOCATED) preempted_tasks = Task.get_tasks_by_status(TaskStatusConst.PREEMPTED) planned_tasks = Task.get_tasks_by_status(TaskStatusConst.PLANNED) dispatched_tasks = Task.get_tasks_by_status(TaskStatusConst.DISPATCHED) ongoing_tasks = Task.get_tasks_by_status(TaskStatusConst.ONGOING) with switch_collection(TaskStatus, TaskStatus.Meta.archive_collection): completed_tasks = Task.get_tasks_by_status( TaskStatusConst.COMPLETED) canceled_tasks = Task.get_tasks_by_status(TaskStatusConst.CANCELED) aborted_tasks = Task.get_tasks_by_status(TaskStatusConst.ABORTED) self.logger.info("Unallocated: %s", len(unallocated_tasks)) self.logger.info("Allocated: %s", len(allocated_tasks)) self.logger.info("Planned: %s ", len(planned_tasks)) self.logger.info("Dispatched: %s", len(dispatched_tasks)) self.logger.info("Ongoing: %s", len(ongoing_tasks)) self.logger.info("Completed: %s ", len(completed_tasks)) self.logger.info("Preempted: %s ", len(preempted_tasks)) self.logger.info("Canceled: %s", len(canceled_tasks)) self.logger.info("Aborted: %s", len(aborted_tasks)) tasks = completed_tasks + preempted_tasks if len(tasks) == len(self.tasks): self.logger.info("Terminating test") self.logger.info("Allocations: %s", self.allocations) self.terminated = True
def task_status_cb(self, msg): payload = msg['payload'] timestamp = TimeStamp.from_str( msg["header"]["timestamp"]).to_datetime() task_status = TaskStatus.from_payload(payload) if self.robot_id == task_status.robot_id: task = Task.get_task(task_status.task_id) self.logger.debug("Received task status %s for task %s", task_status.task_status, task.task_id) self.logger.debug("Sending task status %s for task %s", task_status.task_status, task.task_id) self.api.publish(msg, groups=["TASK-ALLOCATION"]) if task_status.task_status == TaskStatusConst.ONGOING: self.update_timetable(task, task_status.task_progress, timestamp) elif task_status.task_status == TaskStatusConst.COMPLETED: self.logger.debug("Completing execution of task %s", task.task_id) self.task = None task.update_status(task_status.task_status)
def get_earliest_task(self): task_id = self.stn.get_earliest_task_id() if task_id: try: task = Task.get_task(task_id) return task except DoesNotExist: self.logger.warning("Task %s is not in db or its first node is not the start node", task_id)
def get_r_time_previous_task(self, insertion_point, node_type, earliest=True): task_id = self.stn.get_task_id(insertion_point - 1) previous_task = Task.get_task(task_id) return self.dispatchable_graph.get_time(previous_task.task_id, node_type, earliest)
def previous_task_is_frozen(self, insertion_point): task_id = self.stn.get_task_id(insertion_point - 1) previous_task = Task.get_task(task_id) if previous_task.status.status in [ TaskStatusConst.DISPATCHED, TaskStatusConst.ONGOING ]: return True return False
def to_attrs(cls, dict_repr): attrs = super().to_attrs(dict_repr) tasks = list() for task_id, task_dict in attrs.get("tasks").items(): tasks.append( Task.from_payload(task_dict, constraints=TaskConstraints, request=TransportationRequest)) attrs.update(tasks=tasks) return attrs
def get_tasks_status(robot_id): tasks_status = collections.OrderedDict() with switch_collection(Task, Task.Meta.archive_collection): tasks = Task.get_tasks_by_robot(robot_id) with switch_collection(TaskStatus, TaskStatus.Meta.archive_collection): for task in tasks: task_status = TaskStatus.objects.get({"_id": task.task_id}) if task_status.status == TaskStatusConst.COMPLETED: tasks_status[task.task_id] = task_status return tasks_status
def receive_msg_cb(self, msg_content): msg = self.convert_zyre_msg_to_dict(msg_content) if msg is None: return msg_type = msg['header']['type'] payload = msg['payload'] if msg_type == 'TASK': task = Task.from_payload(payload) if self.robot_id in task.assigned_robots: self.logger.debug("Received task %s", task.task_id) self.task = task
def start_test_cb(self, msg): self.simulator_interface.stop() initial_time = msg["payload"]["initial_time"] self.logger.info("Start test at %s", initial_time) tasks = Task.get_tasks_by_status(TaskStatusConst.UNALLOCATED) for robot_id in self.auctioneer.robot_ids: RobotPerformance.create_new(robot_id=robot_id) for task in tasks: self.add_task_plan(task) TaskPerformance.create_new(task_id=task.task_id) self.simulator_interface.start(initial_time) self.auctioneer.allocate(tasks)
def task_status_cb(self, msg): payload = msg['payload'] timestamp = TimeStamp.from_str( msg["header"]["timestamp"]).to_datetime() task_status = TaskStatus.from_payload(payload) if self.robot_id == task_status.robot_id: task = Task.get_task(task_status.task_id) self.logger.debug("Received task status %s for task %s", task_status.task_status, task.task_id) if task_status.task_status == TaskStatusConst.ONGOING: self._update_timetable(task, task_status.task_progress, timestamp) task.update_status(task_status.task_status)
def merge_temporal_graph(previous_graph, new_graph): tasks = list() new_task_ids = new_graph.get_tasks() scheduled_tasks = [ task.task_id for task in Task.get_tasks_by_status(TaskStatusConst.SCHEDULED) if task ] ongoing_tasks = [ task.task_id for task in Task.get_tasks_by_status(TaskStatusConst.ONGOING) if task ] for i, task_id in enumerate(new_task_ids): if task_id in scheduled_tasks or task_id in ongoing_tasks: # Keep current version of task tasks.append(previous_graph.get_task_graph(task_id)) else: # Use new version of task tasks.append(new_graph.get_task_graph(task_id)) # Get type of previous graph merged_graph = previous_graph.__class__() for task_graph in tasks: merged_graph.add_nodes_from(task_graph.nodes(data=True)) merged_graph.add_edges_from(task_graph.edges(data=True)) for i in merged_graph.nodes(): if i != 0 and merged_graph.has_node( i + 1) and not merged_graph.has_edge(i, i + 1): merged_graph.add_constraint(i, i + 1) return merged_graph
def get_task(self, position): """ Returns the task in the given position :param position: (int) position in the STN :return: (Task) task """ task_id = self.stn.get_task_id(position) if task_id: try: return Task.get_task(task_id) except DoesNotExist: self.logger.warning("Task %s is not in db", task_id) raise DoesNotExist else: raise TaskNotFound(position)
def announce_tasks(self): tasks = list(self.tasks_to_allocate.values()) earliest_task = Task.get_earliest_task(tasks) closure_time = earliest_task.pickup_constraint.earliest_time - self.closure_window if not self.is_valid_time(closure_time) and self.alternative_timeslots: # Closure window should be long enough to allow robots to bid (tune if necessary) closure_time = self.get_current_time() + self.closure_window elif not self.is_valid_time( closure_time) and not self.alternative_timeslots: self.logger.warning( "Task %s cannot not be allocated at its given temporal constraints", earliest_task.task_id) earliest_task.update_status(TaskStatusConst.PREEMPTED) self.tasks_to_allocate.pop(earliest_task.task_id) return self.changed_timetable.clear() for task in tasks: if not task.hard_constraints: self.update_soft_constraints(task) self.round = Round(self.robot_ids, self.tasks_to_allocate, n_tasks=len(tasks), closure_time=closure_time, alternative_timeslots=self.alternative_timeslots, simulator=self.simulator) earliest_admissible_time = TimeStamp() earliest_admissible_time.timestamp = self.get_current_time( ) + timedelta(minutes=1) task_announcement = TaskAnnouncement(tasks, self.round.id, self.timetable_manager.ztp, earliest_admissible_time) self.logger.debug("Starting round: %s", self.round.id) self.logger.debug("Number of tasks to allocate: %s", len(tasks)) msg = self.api.create_message(task_announcement) self.logger.debug("Auctioneer announces tasks %s", [task.task_id for task in tasks]) self.round.start() self.api.publish(msg, groups=['TASK-ALLOCATION'])
def run(self): try: self.api.start() while True: try: tasks = Task.get_tasks_by_robot(self.robot_id) if self.schedule_execution_monitor.task is None: self.schedule_execution_monitor.process_tasks(tasks) self.executor.run() except DoesNotExist: pass self.api.run() except (KeyboardInterrupt, SystemExit): self.logger.info("Terminating %s robot ...", self.robot_id) self.api.shutdown() self.executor.shutdown() self.logger.info("Exiting...")
def task_status_cb(self, msg): while self.deleting_task: time.sleep(0.1) self.processing_task = True payload = msg['payload'] timestamp = TimeStamp.from_str( msg["header"]["timestamp"]).to_datetime() task_status = TaskStatus.from_payload(payload) task_progress = task_status.task_progress task = Task.get_task(task_status.task_id) self.logger.debug("Received task status %s for task %s by %s", task_status.task_status, task_status.task_id, task_status.robot_id) if task_status.task_status == TaskStatusConst.ONGOING: self._update_progress(task, task_progress, timestamp) self.update_timetable(task, task_status.robot_id, task_progress, timestamp) self._update_task_schedule(task, task_progress, timestamp) task.update_status(task_status.task_status) elif task_status.task_status == TaskStatusConst.COMPLETED: self.logger.debug("Adding task %s to tasks to remove", task.task_id) self.tasks_to_remove.append((task, task_status.task_status)) elif task_status.task_status == TaskStatusConst.UNALLOCATED: self.re_allocate(task) elif task_status.task_status == TaskStatusConst.PREEMPTED: if task.status.status == TaskStatusConst.PREEMPTED: self.logger.warning("Task %s is already preempted", task_status.task_id) return try: self._remove_task(task, task_status.task_status) except TaskNotFound: return self.processing_task = False
def load_tasks_to_db(dataset_module, dataset_name, **kwargs): dataset_dict = load_yaml_file_from_module(dataset_module, dataset_name + '.yaml') initial_time = kwargs.get('initial_time', datetime.now()) tasks_dict = dataset_dict.get('tasks') ordered_tasks = collections.OrderedDict(sorted(tasks_dict.items())) tasks = list() for task_id, task_info in ordered_tasks.items(): earliest_pickup_time, latest_pickup_time = reference_to_initial_time( task_info.get("earliest_pickup_time"), task_info.get("latest_pickup_time"), initial_time) request = TransportationRequest( request_id=generate_uuid(), pickup_location=task_info.get('pickup_location'), delivery_location=task_info.get('delivery_location'), earliest_pickup_time=earliest_pickup_time, latest_pickup_time=latest_pickup_time, hard_constraints=task_info.get('hard_constraints')) request.save() duration = InterTimepointConstraint() pickup = TimepointConstraint( earliest_time=request.earliest_pickup_time, latest_time=request.latest_pickup_time) temporal = TransportationTemporalConstraints(pickup=pickup, duration=duration) constraints = TransportationTaskConstraints( hard=request.hard_constraints, temporal=temporal) task = TransportationTask.create_new(task_id=task_id, request=request.request_id, constraints=constraints) tasks.append(task) return tasks
def allocate_to_robot(self, task_id): allocation_info = self.bid_placed.get_allocation_info() self.timetable.add_stn_task(allocation_info.new_task) if allocation_info.next_task: self.timetable.add_stn_task(allocation_info.next_task) self.timetable.stn = allocation_info.stn self.timetable.dispatchable_graph = allocation_info.dispatchable_graph self.timetable.store() self.logger.debug("Robot %s allocated task %s", self.robot_id, task_id) self.logger.debug("STN: \n %s", self.timetable.stn) self.logger.debug("Dispatchable graph: \n %s", self.timetable.dispatchable_graph) tasks = [task for task in self.timetable.get_tasks()] self.logger.debug("Tasks allocated to robot %s:%s", self.robot_id, tasks) task = Task.get_task(task_id) task.update_status(TaskStatusConst.ALLOCATED) task.assign_robots([self.robot_id])
def get_smallest_bid(bids): """ Get the bid with the smallest cost among all bids. :param bids: list of bids :return: the bid with the smallest cost """ smallest_bid = None for bid in bids: # Do not consider bids for tasks that were dispatched after the bid computation task = Task.get_task(bid.task_id) if task.status.status in [ TaskStatusConst.DISPATCHED, TaskStatusConst.ONGOING ]: continue if smallest_bid is None or\ bid < smallest_bid or\ (bid == smallest_bid and bid.task_id < smallest_bid.task_id): smallest_bid = copy.deepcopy(bid) return smallest_bid
def get_previous_task(self, task): task_first_node = self.stn.get_task_node_ids(task.task_id)[0] if task_first_node > 1 and self.stn.has_node(task_first_node - 1): prev_task_id = self.stn.nodes[task_first_node - 1]['data'].task_id prev_task = Task.get_task(prev_task_id) return prev_task
def remove_task_cb(self, msg): payload = msg['payload'] remove_task = RemoveTaskFromSchedule.from_payload(payload) task = Task.get_task(remove_task.task_id) self._remove_task(task, remove_task.status)
def task_cb(self, msg): payload = msg['payload'] task = Task.from_payload(payload) if self.robot_id in task.assigned_robots: self.logger.debug("Received task %s", task.task_id) task.update_status(TaskStatusConst.DISPATCHED)