任务状态(Task States)

本文介绍了µC/OS-II操作系统中任务的五种状态:睡眠态、就绪态、运行态、等待状态及中断服务态。详细阐述了各种状态间的转换条件和操作函数,有助于理解实时操作系统的基本原理。

睡眠态(DORMANT)——指任务驻留在程序空间,还没有交给µC/OS-II来管理。把任务交给µC/OS-II,是通过调用下述2个函数之一:OSTaskCreate()OSTaskCreateExt()来实现的。这些调用只是用于告诉µC/OS-II,任务的起始地址在哪里;任务建立时,用户给任务赋予的优先级是多少;任务要使用多少栈空间等。

就绪态(READY)——任务一旦建立,这个任务就进入了就绪态,准备运行。任务的建立可以是在多任务运行开始之前,也可以动态地由一个运行着地任务建立。如果多任务已经启动,且一个任务是被另一个任务建立的,而新建立的任务优先级高于建立它的任务的优先级,则这个刚刚建立的任务将立即得到CPU的使用权。一个任务可以通过调用OSTaskDel()返回到睡眠态,或通过调用该函数让另一个任务进入睡眠态。

运行态(RUNNING)——调用OSStart()可以启动多任务。OSStart()函数只能在启动时调用一次,该函数运行用户初始化代码中已经建立的、进入就绪态的优先级最高的任务。优先级最高的任务就这样进入了运行态。任何时刻只能有一个任务处于运行态。就绪的任务只有当所有优先级高于这个任务的任务都转为等待状态,或者是被删除了,才能进入运行态。

等待状态(WAITING)——正在运行的任务可以通过调用以下2个函数之一:OSTimeDly()OSTimeDlyHMSM(),将自身延迟一段时间。这个任务于是进入等待状态,一直到函数中定义的延迟时间到。这2个函数会立即强制执行任务切换,让下一个优先级最高的、并进入了就绪态的任务运行。等待的时间过去以后,系统服务函数OSTimeTick()使延迟了的任务进入就绪态。而正在运行的任务可能需要等待某一事件的发生,可以通过调用以下函数之一实现:OSFlagPend()OSSemPend()OSMutexPend()OSMboxPend()OSQPend()。如果该事件并未发生,调用上述函数的任务就进入了等待状态,直到等待的事件发生了。当任务因等待事件而被挂起时,下一个优先级最高的任务立即得到了CPU的使用权。当事件发生了或等待超时使,被挂起的任务就进入就绪态。事件发生的报告可能来自另一个任务,也可能来自中断服务子程序。

中断服务态(ISR)——正在运行的任务是可以被中断的,除非该任务将中断关闭,或者µC/OS-II将中断关闭。被中断了的任务于是进入了中断服务态。相应中断时,正在执行的任务被挂起,中断服务子程序得到了CPU的使用权。中断服务子程序可能会报告一个或多个事件的发生,而使一个或多个任务进入就绪态。在这种情况下,从中断服务子程序返回之前,µC/OS-II要判定被中断的任务是否还是就绪态任务中优先级最高的。如果中断服务子程序使另一个优先级更高的任务进入就绪态,则新进入就绪态的这个优先级更高的任务将得以运行;否则,原来被众多拉的任务将继续运行。

当所有的任务都在等待事件的发生或等待延迟时间的结束时,µC/OS-II执行被称为空闲任务(idle task)的内部任务,即OSTaskIdle()

import numpy as np import matplotlib.pyplot as plt import pandas as pd from scipy.spatial.distance import euclidean from shapely.geometry import Polygon, Point, LineString import random from datetime import datetime import os import math # -------------------------- 从Excel读取任务参数 -------------------------- EXCEL_PATH = "output.xlsx" try: task_df = pd.read_excel(EXCEL_PATH) required_columns = [ "任务类别", "任务持续时间", "跟踪距离", "移动任务", "航速", "航向", "点位X轴坐标", "点位Y轴坐标", "时间" # 新增需求:增加任务开始时间列 ] missing_cols = [col for col in required_columns if col not in task_df.columns] if missing_cols: raise ValueError(f"Excel文件缺少必需列:{', '.join(missing_cols)},请检查列名是否匹配模板") # 读取所有任务参数 TASK_TYPES = task_df["任务类别"].tolist() TASK_DURATIONS = task_df["任务持续时间"].astype(float).tolist() TASK_TRACKING_DIST = task_df["跟踪距离"].astype(float).tolist() MOVING_TASKS = task_df["移动任务"].astype(bool).tolist() MOVING_SPEEDS = task_df["航速"].astype(float).tolist() MOVING_COURSES = task_df["航向"].astype(float).tolist() TASK_LOCATIONS = list(zip( task_df["点位X轴坐标"].astype(float).tolist(), task_df["点位Y轴坐标"].astype(float).tolist() )) TASK_LOCATIONS = [(round(x, 2), round(y, 2)) for x, y in TASK_LOCATIONS] TASK_START_TIMES = task_df["时间"].astype(float).tolist() # 新增:任务开始时间 TOTAL_TASKS_FROM_EXCEL = len(TASK_TYPES) # 筛选必须执行的任务(S1, S2, S3)和可选任务(S4) REQUIRED_TASK_IDS = [ idx for idx, task_type in enumerate(TASK_TYPES) if task_type in ['S1', 'S2', 'S3'] ] OPTIONAL_TASK_IDS = [ idx for idx, task_type in enumerate(TASK_TYPES) if task_type == 'S4' ] print(f"成功从Excel读取{TOTAL_TASKS_FROM_EXCEL}个任务的参数") print(f"必须执行的任务(S1,S2,S3)ID:{REQUIRED_TASK_IDS}") print(f"可选执行的任务(S4)ID:{OPTIONAL_TASK_IDS}") if not REQUIRED_TASK_IDS: print("警告:未检测到必须执行的任务(S1,S2,S3)") except FileNotFoundError: raise FileNotFoundError(f"未找到Excel文件:{EXCEL_PATH},请检查文件路径是否正确") except Exception as e: raise Exception(f"读取Excel失败:{str(e)}") # -------------------------- 基础参数设置 -------------------------- plt.rcParams['font.sans-serif'] = ['SimHei'] plt.rcParams['axes.unicode_minus'] = False # 解决负号显示问题 SHIP_SPEEDS = [20, 24, 26, 30] # 节 SHIP_START_POINTS = [(187, 175), (169, 112), (50, 88), (73, 214)] # 4艘舰艇初始位置 EXIT_POLYGON = Polygon([(194.0, 177.6), (173.4, 106.9), (42.5, 81.2), (68.1, 220.7), (144.6, 211.5)]) Cruise_line = [(187.05, 175.1), (168.65, 112.1), (50, 88.75), (73, 214.05), (142.45, 205.75)] cruise_polygon = Polygon(Cruise_line) cruise_boundary = LineString(cruise_polygon.exterior.coords) SHIP_Handling_radius = [5, 3, 1, 1] # 处置半径 SHIP_Handling_amount = [6, 5, 3, 2] # 处置数量 # 周期检查点(ABCD点) - 新增需求 CHECK_POINTS = { 'A': (187.05, 175.1), 'B': (168.65, 112.1), 'C': (50, 88.75), 'D': (73, 214.05) } CHECK_POINT_ORDER = ['A', 'B', 'C', 'D'] # 检查点顺序 CYCLE_DURATION = 12 # 约束周期:12小时 # 任务优先级和响应时间约束 - 新增需求 TASK_PRIORITIES = { 'S1': 1, # 最高优先级 'S2': 2, 'S3': 3, 'S4': 4 # 最低优先级 } MAX_RESPONSE_TIMES = { 'S1': 5, # 小时 'S2': 6, 'S3': 6, 'S4': 24 } # 算法参数 KNOTS_TO_KMH = 1 NAUTICAL_TO_KM = 1 PENALTY_FACTOR = 0.5 # 约束不满足时的适应度惩罚系数 # 舰艇航迹配置(颜色、线型、标记,4艘舰艇各不同) SHIP_TRAJECTORY_CONFIG = [ {"color": "#1f77b4", "line_style": "-", "init_marker": "D", "task_marker": "o", "label": "舰艇1"}, {"color": "#ff7f0e", "line_style": "--", "init_marker": "D", "task_marker": "s", "label": "舰艇2"}, {"color": "#2ca02c", "line_style": "-.", "init_marker": "D", "task_marker": "^", "label": "舰艇3"}, {"color": "#d62728", "line_style": ":", "init_marker": "D", "task_marker": "p", "label": "舰艇4"} ] # == == == == == 新增:周期检查点约束辅助函数 == == == == == def get_time_cycles(total_time): """获取所有时间周期""" if total_time <= 0: return [] cycle_count = int(np.ceil(total_time / CYCLE_DURATION)) return [[cycle * CYCLE_DURATION, (cycle + 1) * CYCLE_DURATION] for cycle in range(cycle_count)] def check_checkpoint_constraint(ship_tasks, total_time): """检查每12小时必须经过ABCD点的约束""" cycles = get_time_cycles(total_time) constraint_result = { "总周期数": len(cycles), "周期详情": [f"{cycle[0]}-{cycle[1]}h" for cycle in cycles], "舰艇检查点检查": {} } unmet_count = 0 for ship_idx in range(len(ship_tasks)): ship_task_history = [] # 收集舰艇的所有位置和时间点 for task in ship_tasks[ship_idx]: ship_task_history.append({ "时间": task["舰艇出发出发时刻(小时)"], "位置": task["舰艇出发坐标(x,y)"] }) ship_task_history.append({ "时间": task["处置任务开始时刻(小时)"], "位置": task["处置置任务开始坐标(x,y)"] }) ship_task_history.append({ "时间": task["处置任务结束时刻(小时)"], "位置": task["处置任务结束坐标(x,y)"] }) # 按时间排序 ship_task_history.sort(key=lambda x: x["时间"]) cycle_check = [] for cycle_idx, (cycle_start, cycle_end) in enumerate(cycles): # 检查该周期内是否经过所有检查点 visited_checkpoints = set() # 检查任务历史中的点 for record in ship_task_history: if cycle_start <= record["时间"] < cycle_end: pos = record["位置"] # 检查是否接近任何检查点(考虑一定的误差范围) for cp_name, cp_pos in CHECK_POINTS.items(): distance = calc_distance(pos, cp_pos) if distance < 0.5: # 0.5单位范围内视为经过 visited_checkpoints.add(cp_name) # 检查是否经过所有检查点 if visited_checkpoints == set(CHECK_POINT_ORDER): cycle_check.append(f"周期{cycle_idx + 1}({cycle_start}-{cycle_end}h):已经过所有检查点✅") else: missing_points = set(CHECK_POINT_ORDER) - visited_checkpoints cycle_check.append(f"周期{cycle_idx + 1}({cycle_start}-{cycle_end}h):缺少检查点{missing_points}❌") unmet_count += 1 constraint_result["舰艇检查点检查"][f"舰艇{ship_idx + 1}"] = cycle_check constraint_result["约束状态"] = f"共{unmet_count}个(舰艇-周期)对未满足检查点约束" return constraint_result, unmet_count # == == == == == 新增:任务中断中断管理 == == == == == class TaskInterruptManager: """任务中断管理器""" @staticmethod def check_pending_tasks(current_time, ship_positions, ship_available_times): """ 检查是否有需要立即处理的高优先级任务 返回需要中断当前任务的新任务ID列表 """ pending_tasks = [] for task_id in range(TOTAL_TASKS_FROM_EXCEL): task_type = TASK_TYPES[task_id] task_start_time = TASK_START_TIMES[task_id] # 如果任务已经超过最大响应时间,需要立即处理 if current_time > task_start_time + MAX_RESPONSE_TIMES[task_type]: # 检查是否有舰艇可以更快到达 for ship_idx in range(len(ship_positions)): if ship_available_times[ship_idx] <= current_time: # 计算舰艇到达任务点的时间 target_pos = get_target_position(task_id, current_time) distance = calc_distance(ship_positions[ship_idx], target_pos) travel_time = calc_travel_time(SHIP_SPEEDS[ship_idx], distance) # 如果能在剩余响应时间内到达,则需要处理 if travel_time <= MAX_RESPONSE_TIMES[task_type]: pending_tasks.append({ "task_id": task_id, "task_type": task_type, "priority": TASK_PRIORITIES[task_type], "ship_idx": ship_idx, "urgency": (current_time - task_start_time) / MAX_RESPONSE_TIMES[task_type] }) # 按优先级和紧急程度排序 pending_tasks.sort(key=lambda x: (x["priority"], x["urgency"]), reverse=True) return pending_tasks @staticmethod def can_interrupt(current_task, new_task): """ 判断是否可以中断当前任务以执行新任务 当前任务是S4且新任务优先级更高时可以中断 """ if current_task is None: return True if current_task["任务类型"] == 'S4' and TASK_PRIORITIES[new_task["task_type"]] < TASK_PRIORITIES['S4']: return True return False # == == == == == 原有辅助函数(保持不变) == == == == == def calc_course(from_pos, to_pos): dx = to_pos[0] - from_pos[0] dy = to_pos[1] - from_pos[1] if dx == 0 and dy == 0: return 0.0 math_angle = np.arctan2(dy, dx) course = (90 - np.degrees(math_angle)) % 360 return round(course, 2) def get_closest_cruise_point(end_pos): end_point = Point(end_pos) proj_dist = cruise_boundary.project(end_point) closest_point = cruise_boundary.interpolate(proj_dist) closest_pos = (round(closest_point.x, 2), round(closest_point.y, 2)) boundary_vertices = list(cruise_boundary.coords)[:-1] min_x = min(v[0] for v in boundary_vertices) max_x = max(v[0] for v in boundary_vertices) min_y = min(v[1] for v in boundary_vertices) max_y = max(v[1] for v in boundary_vertices) cx, cy = closest_pos if not (min_x - 1e-6 <= cx <= max_x + 1e-6 and min_y - 1e-6 <= cy <= max_y + 1e-6): vertex_dists = [euclidean(end_pos, v) for v in boundary_vertices] closest_idx = np.argmin(vertex_dists) closest_pos = boundary_vertices[closest_idx] return closest_pos def calc_end_course_to_cruise(end_pos): closest_pos = get_closest_cruise_point(end_pos) return calc_course(end_pos, closest_pos) def get_target_position(task_id, t): if not MOVING_TASKS[task_id]: return TASK_LOCATIONS[task_id] x0, y0 = TASK_LOCATIONS[task_id] speed_kmh = MOVING_SPEEDS[task_id] * KNOTS_TO_KMH course_rad = np.deg2rad(MOVING_COURSES[task_id]) dx = speed_kmh * t * np.sin(course_rad) dy = speed_kmh * t * np.cos(course_rad) return (round(x0 + dx, 2), round(y0 + dy, 2)) def is_target_exited(task_id, t): if not MOVING_TASKS[task_id]: return False pos = get_target_position(task_id, t) return not EXIT_POLYGON.contains(Point(pos)) def calc_distance(pos1, pos2): return round(euclidean(pos1, pos2), 2) def calc_travel_time(ship_speed, distance): if distance == 0: return 0.0 speed_kmh = ship_speed * KNOTS_TO_KMH return round(distance / speed_kmh, 2) def calc_time_in_polygon(init_point, speed, direction_angle, polygon_vertices): """ 计算移动点从多边形外进入、再离开的总时间(简化验证版) :param init_point: 初始点坐标(元组):(x0, y0) :param speed: 移动速度(正数) :param direction_angle: 移动方向角(度,与x轴正方向夹角) :param polygon_vertices: 多边形顶点列表:[(x1,y1), ..., (xn,yn)] :return: 总时间,无有效交点时返回0 """ # 提取初始坐标 init_x, init_y = init_point # 1. 初始化多边形和轨迹 polygon = Polygon(polygon_vertices) theta = math.radians(450 - direction_angle) vx = speed * math.cos(theta) vy = speed * math.sin(theta) # 生成足够长的轨迹线段 end_x = init_x + vx * 1e6 end_y = init_y + vy * 1e6 trajectory = LineString([(init_x, init_y), (end_x, end_y)]) # 2. 计算轨迹与多边形边界的交点 intersection = trajectory.intersection(polygon.boundary) if intersection.is_empty: return 0.0 # 无交点 # 3. 提取并排序交点(按到初始点的距离) if intersection.geom_type == "Point": intersections = [intersection] elif intersection.geom_type == "MultiPoint": intersections = list(intersection.geoms) else: return 0.0 # 非点类型交点视为无效 # 按轨迹顺序排序(确保进入点在前,离开点在后) intersections.sort(key=lambda p: math.hypot(p.x - init_x, p.y - init_y)) # 4. 取前两个交点计算距离(假设存在两个有效交点) if len(intersections) < 2: leave_point = intersections[0] distance = math.hypot(leave_point.x - init_x, leave_point.y - init_y) else: enter_point, leave_point = intersections[0], intersections[1] distance = math.hypot(init_x - leave_point.x, init_y - leave_point.y) return round(distance / speed, 6) # == == == == == 优先级调度算法核心 == == == == == class PriorityScheduler: def __init__(self, num_ships=4): self.num_ships = num_ships self.total_tasks = TOTAL_TASKS_FROM_EXCEL self.required_tasks = REQUIRED_TASK_IDS.copy() self.optional_tasks = OPTIONAL_TASK_IDS.copy() self.interrupt_manager = TaskInterruptManager() print(f"任务划分:必须执行任务{self.required_tasks},可选执行任务{self.optional_tasks}") print(f"任务优先级:S1(1) > S2(2) > S3(3) > S4(4)") print(f"最大响应时间:S1({MAX_RESPONSE_TIMES['S1']}h)、S2({MAX_RESPONSE_TIMES['S2']}h)、" f"S3({MAX_RESPONSE_TIMES['S3']}h)、S4({MAX_RESPONSE_TIMES['S4']}h)") print(f"周期检查点:每{CYCLE_DURATION}小时必须经过{CHECK_POINT_ORDER}点") def schedule_tasks(self): """ 基于优先级的任务调度算法 1. 按时间顺序处理任务 2. 高优先级任务优先分配 3. 支持任务中断 4. 满足响应时间约束 5. 满足周期检查点约束 """ # 舰艇状态初始化 ship_states = [] for i in range(self.num_ships): ship_states.append({ "position": SHIP_START_POINTS[i], "available_time": 0.0, "current_task": None, # 当前执行的任务(可能被中断) "completed_tasks": [], "interrupted_tasks": [], "checkpoint_history": [] }) # 任务执行记录 task_execution_records = [[] for _ in range(self.num_ships)] required_tasks_completed = set() optional_tasks_completed = set() current_time = 0.0 max_simulation_time = 100.0 # 最大模拟时间 # 创建任务事件队列(按开始时间排序) task_events = [] for task_id in range(TOTAL_TASKS_FROM_EXCEL): task_events.append({ "task_id": task_id, "task_type": TASK_TYPES[task_id], "priority": TASK_PRIORITIES[TASK_TYPES[task_id]], "start_time": TASK_START_TIMES[task_id], "is_required": task_id in self.required_tasks }) # 按开始时间和优先级排序 task_events.sort(key=lambda x: (x["start_time"], x["priority"])) # 主调度循环 while current_time < max_simulation_time: # 1. 检查是否有需要立即处理的紧急任务(响应时间即将超时) pending_tasks = self.interrupt_manager.check_pending_tasks( current_time, [state["position"] for state in ship_states], [state["available_time"] for state in ship_states] ) # 2. 处理紧急任务 for pending_task in pending_tasks: self.handle_emergency_task(pending_task, current_time, ship_states, task_execution_records, required_tasks_completed, optional_tasks_completed) # 3. 处理新到达的任务 new_tasks = [event for event in task_events if event["start_time"] <= current_time and event["task_id"] not in required_tasks_completed and event["task_id"] not in optional_tasks_completed and not any(state["current_task"] and state["current_task"]["任务编号"] == event["task_id"] for state in ship_states)] # 按优先级排序新任务 new_tasks.sort(key=lambda x: (x["priority"], x["start_time"])) # 分配新任务 for task_event in new_tasks: # 为任务找到最合适的舰艇 best_ship_idx = self.find_best_ship_for_task(task_event["task_id"], current_time, ship_states) if best_ship_idx is not None: # 检查是否需要中断当前任务 if ship_states[best_ship_idx]["current_task"] is not None: current_task = ship_states[best_ship_idx]["current_task"] if self.interrupt_manager.can_interrupt(current_task, task_event): # 中断当前任务 self.interrupt_current_task(best_ship_idx, current_time, ship_states, task_execution_records) # 分配新任务 if ship_states[best_ship_idx]["current_task"] is None: self.assign_task(best_ship_idx, task_event["task_id"], current_time, ship_states, task_execution_records, required_tasks_completed, optional_tasks_completed) # 4. 检查周期性检查点 self.check_periodic_checkpoints(current_time, ship_states) # 5. 更新时间 next_event_time = self.get_next_event_time(ship_states, task_events, current_time, max_simulation_time) if next_event_time == current_time: break # 没有更多事件 # 6. 处理在时间推进过程中完成的任务 self.process_completed_tasks(current_time, next_event_time, ship_states, task_execution_records, required_tasks_completed, optional_tasks_completed) current_time = next_event_time # 计算调度结果指标 metrics = self.calculate_metrics(required_tasks_completed, optional_tasks_completed, task_execution_records, current_time) return task_execution_records, metrics def handle_emergency_task(self, emergency_task, current_time, ship_states, task_execution_records, required_tasks_completed, optional_tasks_completed): """处理紧急任务""" ship_idx = emergency_task["ship_idx"] task_id = emergency_task["task_id"] # 如果舰艇正在执行任务,检查是否可以中断 if ship_states[ship_idx]["current_task"] is not None: current_task = ship_states[ship_idx]["current_task"] if self.interrupt_manager.can_interrupt(current_task, emergency_task): # 中断当前任务 self.interrupt_current_task(ship_idx, current_time, ship_states, task_execution_records) # 分配紧急任务 if ship_states[ship_idx]["current_task"] is None: self.assign_task(ship_idx, task_id, current_time, ship_states, task_execution_records, required_tasks_completed, optional_tasks_completed) def interrupt_current_task(self, ship_idx, current_time, ship_states, task_execution_records): """中断当前任务""" current_task = ship_states[ship_idx]["current_task"] if current_task is None: return # 更新任务状态 current_task["任务状态"] = "已中断" current_task["实际结束时刻(小时)"] = current_time current_task["已完成时间比例"] = (current_time - current_task["处置任务开始时刻(小时)"]) / current_task[ "任务耗时(小时)"] # 记录中断的任务 ship_states[ship_idx]["interrupted_tasks"].append(current_task) # 更新舰艇状态 ship_states[ship_idx]["current_task"] = None ship_states[ship_idx]["available_time"] = current_time def find_best_ship_for_task(self, task_id, current_time, ship_states): """为任务找到最合适的舰艇""" task_type = TASK_TYPES[task_id] task_start_time = TASK_START_TIMES[task_id] best_ship_idx = None best_score = float('inf') for ship_idx in range(self.num_ships): state = ship_states[ship_idx] # 如果舰艇不可用,跳过 if state["available_time"] > current_time + MAX_RESPONSE_TIMES[task_type]: continue # 计算舰艇到达任务点的时间 target_pos = get_target_position(task_id, max(current_time, state["available_time"])) distance = calc_distance(state["position"], target_pos) travel_time = calc_travel_time(SHIP_SPEEDS[ship_idx], distance) # 计算响应时间 actual_start_time = max(current_time, state["available_time"]) + travel_time response_time = actual_start_time - task_start_time # 如果超过最大响应时间,跳过 if response_time > MAX_RESPONSE_TIMES[task_type]: continue # 计算评分(考虑响应时间、舰艇优先级等) score = response_time * TASK_PRIORITIES[task_type] if score < best_score: best_score = score best_ship_idx = ship_idx return best_ship_idx def assign_task(self, ship_idx, task_id, current_time, ship_states, task_execution_records, required_tasks_completed, optional_tasks_completed): """分配任务给舰艇""" state = ship_states[ship_idx] task_type = TASK_TYPES[task_id] task_start_time = TASK_START_TIMES[task_id] # 计算出发时间(舰艇可用时间和任务开始时间的最大值) depart_time = max(current_time, state["available_time"], task_start_time) # 计算航行时间和任务开始时间 ship_speed = SHIP_SPEEDS[ship_idx] depart_pos = state["position"] target_pos = get_target_position(task_id, depart_time) distance = calc_distance(depart_pos, target_pos) travel_time = calc_travel_time(ship_speed, distance) task_start_time_actual = depart_time + travel_time # 计算响应时间 response_time = task_start_time_actual - task_start_time # 如果超过最大响应时间,不分配(仅对必须执行的任务) if task_type in ['S1', 'S2', 'S3'] and response_time > MAX_RESPONSE_TIMES[task_type]: return False # 计算任务执行时间 if task_type in ['S2', 'S3']: # S2/S3任务需要跟踪目标移动 travel_dist = calc_distance(depart_pos, TASK_LOCATIONS[task_id]) travel_time = calc_travel_time(ship_speed, travel_dist) # 计算追踪时间(目标移动指定距离所需时间) tracking_time = TASK_TRACKING_DIST[task_id] / MOVING_SPEEDS[task_id] # 任务开始时间 = 出发时间 + 航行时间 task_start_time_actual = depart_time + travel_time exit_time = calc_time_in_polygon(target_pos, MOVING_SPEEDS[task_id], MOVING_COURSES[task_id], EXIT_POLYGON) # 任务结束时间 = 开始时间 + 追踪时间 task_end_time = task_start_time_actual + exit_time - travel_time # 到达任务点位置 task_start_pos = get_target_position(task_id, task_start_time_actual) # 任务结束位置 = 目标在结束时刻的位置 task_end_pos = get_target_position(task_id, task_end_time) # 任务总耗时 task_duration = exit_time - task_start_time_actual else: # S1/S4任务 task_duration = TASK_DURATIONS[task_id] task_end_time = task_start_time_actual + task_duration task_start_pos = target_pos task_end_pos = get_target_position(task_id, task_end_time) # 创建任务详情 task_detail = { "舰艇编号": ship_idx + 1, "任务编号": task_id, "任务类型": task_type, "任务优先级": TASK_PRIORITIES[task_type], "最大响应时间": MAX_RESPONSE_TIMES[task_type], "实际响应时间": round(response_time, 2), "舰艇速度()": ship_speed, "舰艇出发时刻(小时)": round(depart_time, 2), "舰艇出发坐标(x,y)": depart_pos, "舰艇出发航向(°)": calc_course(depart_pos, task_start_pos), "处置任务开始时刻(小时)": round(task_start_time_actual, 2), "处置任务开始坐标(x,y)": task_start_pos, "处置任务结束时刻(小时)": round(task_end_time, 2), "处置任务结束坐标(x,y)": task_end_pos, "任务结束后航向(°)": None, "任务耗时(小时)": round(task_duration, 2), "任务状态": "执行中" } # 更新舰艇状态 state["current_task"] = task_detail state["available_time"] = task_end_time # 添加到执行记录 task_execution_records[ship_idx].append(task_detail) return True def check_periodic_checkpoints(self, current_time, ship_states): """检查周期性检查点""" # 检查是否需要前往检查点 for ship_idx in range(self.num_ships): state = ship_states[ship_idx] # 如果舰艇当前没有任务且不在检查点附近 if state["current_task"] is None: current_cycle = int(current_time / CYCLE_DURATION) next_checkpoint_time = (current_cycle + 1) * CYCLE_DURATION # 检查是否需要前往下一个检查点 time_until_next_checkpoint = next_checkpoint_time - current_time if time_until_next_checkpoint < 1.0: # 1小时内需要到达检查点 # 找到最近的检查点 closest_cp = None min_distance = float('inf') for cp_name, cp_pos in CHECK_POINTS.items(): distance = calc_distance(state["position"], cp_pos) if distance < min_distance: min_distance = distance closest_cp = cp_name # 如果距离检查点较远,规划前往检查点的任务 if min_distance > 1.0: # 距离超过1单位 travel_time = calc_travel_time(SHIP_SPEEDS[ship_idx], min_distance) if travel_time <= time_until_next_checkpoint: # 创建前往检查点的任务 checkpoint_task = { "舰艇编号": ship_idx + 1, "任务编号": -1, # 特殊任务编号 "任务类型": "检查点任务", "任务优先级": 5, # 低于所有其他任务 "最大响应时间": time_until_next_checkpoint, "实际响应时间": 0, "舰艇速度()": SHIP_SPEEDS[ship_idx], "舰艇出发时刻(小时)": round(current_time, 2), "舰艇出发坐标(x,y)": state["position"], "舰艇出发航向(°)": calc_course(state["position"], CHECK_POINTS[closest_cp]), "处置任务开始时刻(小时)": round(current_time, 2), "处置任务开始坐标(x,y)": state["position"], "处置任务结束时刻(小时)": round(current_time + travel_time, 2), "处置任务结束坐标(x,y)": CHECK_POINTS[closest_cp], "任务结束后航向(°)": None, "任务耗时(小时)": round(travel_time, 2), "任务状态": "执行中" } # 更新舰艇状态 state["current_task"] = checkpoint_task state["available_time"] = current_time + travel_time def get_next_event_time(self, ship_states, task_events, current_time, max_simulation_time): """获取下一个事件的时间""" # 舰艇可用时间 ship_available_times = [state["available_time"] for state in ship_states] # 未处理任务的开始时间 unprocessed_task_times = [] for event in task_events: task_id = event["task_id"] # 检查任务是否已经完成或正在执行 task_completed = any(task_id in state["completed_tasks"] for state in ship_states) task_running = any(state["current_task"] and state["current_task"]["任务编号"] == task_id for state in ship_states) if not task_completed and not task_running and event["start_time"] > current_time: unprocessed_task_times.append(event["start_time"]) # 周期检查点时间 next_cycle_start = ((int(current_time / CYCLE_DURATION) + 1) * CYCLE_DURATION) # 所有可能的事件时间 all_event_times = ship_available_times + unprocessed_task_times + [next_cycle_start, max_simulation_time] # 找到最近的事件时间 next_event_time = min([t for t in all_event_times if t > current_time]) return next_event_time def process_completed_tasks(self, current_time, next_event_time, ship_states, task_execution_records, required_tasks_completed, optional_tasks_completed): """处理在时间推进过程中完成的任务""" for ship_idx in range(self.num_ships): state = ship_states[ship_idx] # 如果舰艇有当前任务任务在这个时间段内完成 if state["current_task"] is not None: task_end_time = state["current_task"]["处置任务结束时刻(小时)"] if current_time < task_end_time <= next_event_time: # 任务完成 current_task = state["current_task"] current_task["任务状态"] = "已完成" # 更新任务完成状态 task_id = current_task["任务编号"] if task_id != -1: # 不是检查点任务 task_type = TASK_TYPES[task_id] if task_type in ['S1', 'S2', 'S3']: required_tasks_completed.add(task_id) elif task_type == 'S4': optional_tasks_completed.add(task_id) # 记录完成的任务 state["completed_tasks"].append(task_id) # 更新舰艇状态 state["position"] = current_task["处置任务结束坐标(x,y)"] state["current_task"] = None state["available_time"] = task_end_time def calculate_metrics(self, required_tasks_completed, optional_tasks_completed, task_execution_records, total_time): """计算调度结果指标""" # 1. 必须执行的任务是否全部完成 required_all_completed = len(required_tasks_completed) == len(self.required_tasks) # 2. S4任务完成数量 s4_completed = len([t for t in optional_tasks_completed if TASK_TYPES[t] == 'S4']) # 3. 检查约束 checkpoint_constraint_result, unmet_checkpoint_count = check_checkpoint_constraint(task_execution_records, total_time) # 4. 响应时间约束检查 response_time_violations = 0 for task_id in required_tasks_completed: task_type = TASK_TYPES[task_id] task_start_time = TASK_START_TIMES[task_id] # 找到任务的执行记录 for ship_tasks in task_execution_records: for task in ship_tasks: if task["任务编号"] == task_id: actual_start_time = task["处置任务开始时刻(小时)"] response_time = actual_start_time - task_start_time if response_time > MAX_RESPONSE_TIMES[task_type]: response_time_violations += 1 break else: continue break # 5. 计算适应度(S4任务完成数量) if not required_all_completed: fitness = 0.0 else: # 基础适应度 = S4任务完成数量 base_fitness = s4_completed # 约束惩罚 constraint_penalty = (PENALTY_FACTOR ** (unmet_checkpoint_count + response_time_violations)) # 最终适应度 fitness = base_fitness * constraint_penalty return { "fitness": fitness, "s4_completed": s4_completed, "required_completed": len(required_tasks_completed), "required_total": len(self.required_tasks), "checkpoint_violations": unmet_checkpoint_count, "response_time_violations": response_time_violations, "total_time": total_time, "checkpoint_constraint_result": checkpoint_constraint_result } def decode_schedule(self, task_execution_records): """解码调度计划,生成详细的任务执行记录""" # 完成所有任务后更新航向 for ship_idx in range(self.num_ships): tasks = task_execution_records[ship_idx] num_tasks = len(tasks) for i in range(num_tasks): current_task = tasks[i] current_end_pos = current_task["处置任务结束坐标(x,y)"] if i == num_tasks - 1: end_course = calc_end_course_to_cruise(current_end_pos) else: next_task = tasks[i + 1] if next_task["任务编号"] == -1: # 检查点任务 end_course = calc_course(current_end_pos, next_task["处置任务开始坐标(x,y)"]) else: next_task_id = next_task["任务编号"] next_depart_time = current_task["处置任务结束时刻(小时)"] next_task_start_pos = get_target_position(next_task_id, next_depart_time) if MOVING_TASKS[ next_task_id] else TASK_LOCATIONS[next_task_id] end_course = calc_course(current_end_pos, next_task_start_pos) current_task["任务结束后航向(°)"] = end_course return task_execution_records # == == == == == 主程序== == == == == if __name__ == "__main__": # 创建优先级调度器 scheduler = PriorityScheduler(num_ships=4) # 执行调度 print("\n开始优先级调度...") ship_tasks, metrics = scheduler.schedule_tasks() # 解码调度计划 ship_tasks = scheduler.decode_schedule(ship_tasks) # 统计任务完成情况 required_completed = metrics["required_completed"] required_total = metrics["required_total"] s4_completed = metrics["s4_completed"] s4_total = len(OPTIONAL_TASK_IDS) # 输出结果 print("\n" + "=" * 80) print("优先级调度完成!") print(f"Excel总任务数: {TOTAL_TASKS_FROM_EXCEL}") print(f"必须执行任务(S1,S2,S3):{required_completed}/{required_total}") print(f"可选执行任务(S4):{s4_completed}/{s4_total}") print(f"最佳适应度: {metrics['fitness']:.2f}") print(f"检查点约束违反次数: {metrics['checkpoint_violations']}") print(f"响应时间约束违反次数: {metrics['response_time_violations']}") print(f"总完成时间: {metrics['total_time']:.2f} 小时") print("=" * 80) # 输出检查点约束详细结果 print("\n【周期检查点约束检查结果】") if metrics["checkpoint_constraint_result"]: for key, value in metrics["checkpoint_constraint_result"].items(): if isinstance(value, dict): print(f" {key}:") for task_key, task_value in value.items(): print(f" {task_key}:") for item in task_value: print(f" - {item}") else: print(f" {key}: {value}") print("=" * 80) # 导出Excel all_tasks = [] for ship in ship_tasks: all_tasks.extend(ship) if all_tasks: df = pd.DataFrame(all_tasks) column_order = [ "舰艇编号", "任务编号", "任务类型", "任务优先级", "最大响应时间", "实际响应时间", "舰艇速度()", "舰艇出发时刻(小时)", "舰艇出发坐标(x,y)", "舰艇出发航向(°)", "处置任务开始时刻(小时)", "处置任务开始坐标(x,y)", "处置任务结束时刻(小时)", "处置任务结束坐标(x,y)", "任务结束后航向(°)", "任务耗时(小时)", "任务状态" ] # 确保所有列都存在 for col in column_order: if col not in df.columns: df[col] = None df = df[column_order] timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") excel_filename = f"优先级调度舰艇任务分配详情_{timestamp}.xlsx" try: with pd.ExcelWriter(excel_filename, engine="openpyxl") as writer: # 任务分配详情 df.to_excel(writer, sheet_name="任务分配详情", index=False) # 任务完成统计 stats_data = [ {"统计项目": "总任务数", "数值": TOTAL_TASKS_FROM_EXCEL}, {"统计项目": "必须执行任务(S1,S2,S3)", "数值": len(REQUIRED_TASK_IDS)}, {"统计项目": "必须执行任务完成数", "数值": required_completed}, {"统计项目": "可选任务(S4)", "数值": len(OPTIONAL_TASK_IDS)}, {"统计项目": "可选任务完成数(S4)", "数值": s4_completed}, {"统计项目": "S4任务完成率", "数值": f"{s4_completed / len(OPTIONAL_TASK_IDS) * 100:.1f}%" if OPTIONAL_TASK_IDS else "0%"}, {"统计项目": "总完成时间(小时)", "数值": round(metrics["total_time"], 2)}, {"统计项目": "检查点约束违反次数", "数值": metrics["checkpoint_violations"]}, {"统计项目": "响应时间约束违反次数", "数值": metrics["response_time_violations"]} ] stats_df = pd.DataFrame(stats_data) stats_df.to_excel(writer, sheet_name="任务完成统计", index=False) # 检查点约束结果 if metrics["checkpoint_constraint_result"]: constraint_data = [] for key, value in metrics["checkpoint_constraint_result"].items(): if isinstance(value, list) and key == "周期详情": for i, cycle in enumerate(value): constraint_data.append( {"约束项": "周期详情", "周期序号": i + 1, "周期范围": cycle, "备注": ""}) elif isinstance(value, dict) and key == "舰艇检查点检查": for ship_key, ship_cycles in value.items(): for cycle_idx, cycle_check in enumerate(ship_cycles): cycle_range = metrics["checkpoint_constraint_result"]["周期详情"][cycle_idx] status = "已满足" if "✅" in cycle_check else "未满足" constraint_data.append({ "约束项": ship_key, "周期序号": cycle_idx + 1, "周期范围": cycle_range, "约束状态": status, "详细信息": cycle_check.split(":")[1] }) else: constraint_data.append( {"约束项": key, "周期序号": "", "周期范围": "", "约束状态": "", "详细信息": value}) constraint_df = pd.DataFrame(constraint_data) constraint_df.to_excel(writer, sheet_name="检查点约束结果", index=False) print(f"\nExcel表格已生成:{excel_filename}") print(f"文件路径:{os.path.abspath(excel_filename)}") print(f"表格包含3个工作表:") print(f" 1. 任务分配详情:所有任务的执行信息") print(f" 2. 任务完成统计:任务完成情况汇总") print(f" 3. 检查点约束结果:周期检查点约束的详细检查结果") except Exception as e: print(f"\n导出Excel失败:{str(e)}") print("请确保已安装依赖库:pip install pandas openpyxl shapely") # 绘制任务执行甘特图 plt.figure(figsize=(15, 8)) colors = {'S1': '#ff4444', 'S2': '#ff8800', 'S3': '#ffcc00', 'S4': '#00cc44', '检查点任务': '#8888ff'} y_positions = range(1, len(ship_tasks) + 1) for i, (ship_idx, tasks) in enumerate(zip(y_positions, ship_tasks)): for task in tasks: start_time = task["处置任务开始时刻(小时)"] duration = task["任务耗时(小时)"] task_type = task["任务类型"] task_id = task["任务编号"] # 检查点任务特殊处理 if task_type == "检查点任务": label = "检查点" else: label = f'{task_type}-{task_id}' if task_id != -1 else "检查点" plt.barh(ship_idx, duration, left=start_time, color=colors.get(task_type, '#888888'), alpha=0.7, height=0.6) # 添加任务标签 plt.text(start_time + duration / 2, ship_idx, label, ha='center', va='center', fontsize=8, fontweight='bold') # 添加检查点垂直线 cycles = get_time_cycles(metrics["total_time"]) for cycle_start, cycle_end in cycles: plt.axvline(x=cycle_start, color='gray', linestyle='--', alpha=0.5) plt.text(cycle_start, len(ship_tasks) + 0.5, f'周期{int(cycle_start / 12) + 1}开始', rotation=90, ha='center', va='bottom', fontsize=8, color='gray') plt.yticks(y_positions, [f'舰艇{i}' for i in range(1, len(ship_tasks) + 1)]) plt.xlabel('时间(小时)') plt.ylabel('舰艇编号') plt.title('舰艇任务执行甘特图') plt.grid(True, alpha=0.3) # 添加图例 legend_elements = [plt.Rectangle((0, 0), 1, 1, color=color, alpha=0.7, label=task_type) for task_type, color in colors.items()] plt.legend(handles=legend_elements, loc='upper right') plt.tight_layout() plt.savefig(f'task_gantt_chart_{timestamp}.png', dpi=300, bbox_inches='tight') plt.close() print(f"任务执行甘特图已保存:task_gantt_chart_{timestamp}.png") print("\n所有结果文件已生成完成!") 纠正上述代码
最新发布
10-21
这个是我的字段@Data @EqualsAndHashCode(callSuper = true) @TableName("ml_imc_config") public class MlImcConfig extends BaseEntity { @Serial private static final long serialVersionUID = 1L; /** * id */ private Long id; /** * 任务名称 */ private String taskName; /** * 状态(1.图片上传 2.检测中 3.报告完成 4.已完成) */ private TaskState statusCode; /** * 任务执行耗时(), */ private Long executionSeconds; /** * 像素倍率 */ private String magnificationType; /** * 图片 */ private String picture; /** * 租户id */ private String tenantId ; /** * 创建时间 */ private Date createTime ; /** * 删除标志(0代表存在 1代表删除) */ @TableLogic private String delFlag; }/** * 状态枚举 */ public enum TaskState { UPLOADING, // 图片上传状态 DETECTING, // 检测状态 REPORTING, // 报告生成状态 COMPLETED // 完成状态 }public enum TaskEvent { UPLOAD_COMPLETE, // 图片上传完成 DETECTION_COMPLETE, // 检测完成 REPORT_GENERATED // 报告生成完成 } @Override public void configure(StateMachineStateConfigurer<TaskState, TaskEvent> states) throws Exception { states .withStates() .initial(TaskState.UPLOADING) //初始状态 .states(EnumSet.allOf(TaskState.class)); //进入所有状态 } @Override public void configure(StateMachineTransitionConfigurer<TaskState, TaskEvent> transitions) throws Exception { transitions // 图片上传完成后进入检测状态 .withExternal() //外部转换 一个状态切换到另一个状态 .source(TaskState.UPLOADING) //起始状态 .target(TaskState.DETECTING) //转换目标 .event(TaskEvent.UPLOAD_COMPLETE) //触发事件 // 检测完成后进入报告生成状态 .and().withExternal() .source(TaskState.DETECTING) .target(TaskState.REPORTING) .event(TaskEvent.DETECTION_COMPLETE) // 报告生成完成后进入结束状态 .and().withExternal() .source(TaskState.REPORTING) .target(TaskState.COMPLETED) .event(TaskEvent.REPORT_GENERATED); }这个是我的状态机的配置 这个是我的添加的用法 @Override public Boolean insertByBo(MlImcConfigBo bo) { // TASK_IMC_ 年月日流水号 String key = PREFIX + new SimpleDateFormat("yyyyMMdd").format(new Date()); // 使用 incr 对 Redis 中的 key 进行自增 Long increment = redisTemplate.opsForValue().increment(key, 1); // 固定四位长度字符串 String formattedSeq = String.format("%04d", increment); String name = key + "_" + formattedSeq; bo.setTaskName(name); //初始化实体并设置初始状态 MlImcConfig add = MapstructUtils.convert(bo, MlImcConfig.class); add.setStatusCode(TaskState.UPLOADING); validEntityBeforeSave(add); boolean flag = baseMapper.insert(add) > 0; if (flag) { bo.setId(add.getId()); //状态机 StateMachine<TaskState, TaskEvent> stateMachine = stateMachineFactory.getStateMachine(); stateMachine.getExtendedState().getVariables().put("id", add.getId()); stateMachine.getExtendedState().getVariables().put("task", add); stateMachine.start(); // 启动状态机 } return flag; }我的状态机使用对嘛
06-19
<think>嗯,用户这次的问题是关于数据库或系统如何管理调度任务状态,结合了之前讨论的内存分配主题。用户可能是个系统架构师或DBA,需要实际落地的解决方案。 注意到用户特别强调要参考站内引用,但引用[1]是关于任务调度系统设计的,引用[2]讲的是DBMS管理界面,和当前问题关联度不高。不过引用[1]提到的“任务状态管理”正好是用户当前问题的核心。 用户上次问的是内存分配,这次转向任务状态管理,说明ta可能在搭建分布式系统。需要重点解释状态持久化机制,因为这是数据库介入任务调度的关键。 从技术深度看,用户应该具备专业知识,可以展开讲ACID实现细节。但要注意把OLTP和OLAP场景分开说明,因为用户上次特别区分过这两类用户的内存配置。 突然想到个技术盲点:是否需要解释最终一致性和强一致性的选择?不过用户没提分布式事务,先聚焦核心状态机管理比较稳妥。 在回复结构上,计划分四块:先讲状态存储机制(核心),再说状态转移控制(重点),接着是容错处理(必备),最后给监控建议(实用)。每部分都要带具体数据库实现示例,像上次那样用SQL语句展示会更直观。 特别要注意数学公式的规范表达,比如状态机转移概率公式必须用$p_{ij}$格式。上次用户没指出问题,但这次系统指令特别强调了LaTeX格式。 用户可能还会追问如何优化高频状态更新,这涉及到WAL和缓冲池配置,正好衔接上次讨论的内存分配话题。不过当前回复先聚焦状态管理本身,在“最佳实践”部分埋个伏笔就行。 最后生成的问题要引导到分布式场景,因为引用[1]提到这是用户系统的特性。可以问“跨节点状态同步”这类具体问题。</think>在数据库或系统层面管理调度任务状态,主要通过**状态机持久化**、**分布式协调**和**容错机制**实现。以下是具体实现方法: --- ### 一、核心状态管理机制 #### 1. **状态机持久化存储** ```sql -- 创建任务状态表(MySQL示例) CREATE TABLE task_states ( task_id VARCHAR(36) PRIMARY KEY, job_name VARCHAR(50) NOT NULL, current_state ENUM('PENDING', 'RUNNING', 'SUCCESS', 'FAILED', 'RETRYING') DEFAULT 'PENDING', retry_count INT DEFAULT 0, checkpoint JSON, -- 存储中间状态快照 last_updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) ENGINE=InnoDB; ``` - **状态流转逻辑**: $S_{t+1} = f(S_t, E)$ 其中 $S_t$ 为当前状态,$E$ 为事件(如任务完成/超时)[^1] - 通过数据库事务保证状态更新原子性 #### 2. **状态转移控制** ```python # 状态转移伪代码(基于引用[1]设计) def update_task_state(task_id, new_state): with db
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值