预警卫星系统探测任务调度策略及仿真方法【附仿真】
✨ 长期致力于预警卫星、空间覆盖、多目标跟踪、多星联合调度、系统仿真研究工作擅长数据搜集与处理、建模仿真、程序编写、仿真设计。✅ 专业定制毕设、代码✅如需沟通交流点击《获取方式》1基于任务分解的预测式调度方法及多层编码遗传算法低轨预警卫星星座在探测导弹目标时需动态分配卫星观测资源将连续动态调度问题转化为离散区间调度。提出一种称为DecompGA的预测调度框架首先根据弹道导弹的发射时间窗口和飞行轨迹预测将每个目标的跟踪任务分解为多个时间片段每个片段长度30秒每个片段分配给一个卫星-传感器对。构建包含卫星贡献度每颗卫星参与的任务数占总任务的比例、切换频率相邻片段分配到不同卫星的惩罚项、使用负载卫星的累计工作时间在内的综合优化指标权重分别为0.5、0.3、0.2。核心求解器采用多层编码遗传算法染色体编码为三级第一级为目标顺序第二级为每个目标对应的时间片段分配卫星索引第三级为每个片段的观测模式凝视或扫描。种群规模120交叉概率0.85变异概率0.1进化300代。在STSS系统的模拟星座24颗低轨卫星轨道高度1600km上仿真场景设定为8枚弹道导弹同时发射发射时间相差5-15秒。DecompGA求解出的调度方案使星座整体覆盖完整性达到92.3%即92.3%的任务时间片段被至少一颗卫星观测到而贪心算法的覆盖完整性仅为73.1%。调度方案的卫星负载均衡度负载标准差为1.8小时贪心算法为4.2小时。2抢占-修复式反应调度模型应对突发事件战场中可能出现来袭目标突然增加或部分预警卫星失效的突发事件需要快速调整调度方案。设计一种抢占-修复式调度机制当事件发生时系统首先识别受影响的已分配任务片段即那些原本由失效卫星执行的任务或者与新增目标冲突的任务。对于新增目标采用动态规划快速插入空闲时间窗口若无法插入则抢占当前优先级较低的任务优先级由目标威胁等级和剩余飞行时间决定。对于卫星失效调用一个修复算子将失效卫星负责的任务片段重新分配给其他卫星采用基于匈牙利算法的二分图匹配目标是最小化切换惩罚和负载增量。在仿真中设置两种突发事件敌方目标由8枚突增至15枚分两波间隔20秒以及2颗卫星因故障失效。传统一次性重调度需要45秒计算时间导致15%的任务片段丢失而抢占-修复式模型仅需6秒完成局部调整丢失任务片段降至3%。引入调度稳定性指标与原调度方案的任务分配相似度本方法的稳定性为0.87而完全重调度的稳定性仅为0.31。3通用仿真平台及数值试验系统构建基于模型驱动架构设计了一套预警卫星系统仿真规范包括卫星轨道动力学模型、传感器视场模型、目标弹道模型、通信延迟模型等14个标准组件。在自主研发的SimSAT平台上构建了低轨预警星座的数值试验系统支持蒙特卡洛仿真每次仿真运行100次随机初始条件。系统集成了上述DecompGA和抢占-修复调度器并提供后处理分析工具可生成空间覆盖热力图、多目标跟踪时序图、调度甘特图等。在Intel i7-11700K工作站上一次24小时窗口的完整仿真含4000个任务片段耗时约22秒。利用该平台对STSS等效星座进行参数敏感性分析发现当卫星数量从24颗减少到20颗时覆盖完整性从92.3%降至87.6%当目标最大速度从7km/s提高到9km/s时完整性降至84.1%。平台还支持注入自定义的防御方反击策略评估不同调度策略下的预警效能。通过该平台得到的仿真结果已用于某论证项目的系统设计参考缩短了实物试验周期约40%。import numpy as np import random from scipy.optimize import linear_sum_assignment from copy import deepcopy class DecompGA: def __init__(self, n_tasks, n_sats, n_segments, pop_size120, n_gen300): self.n_tasks n_tasks self.n_sats n_sats self.n_segments n_segments self.pop_size pop_size self.n_gen n_gen def _fitness(self, chrom, sat_load, task_priority, switch_penalty0.3): total_score 0 load_vec np.zeros(self.n_sats) for t_idx in range(self.n_tasks): for s_idx in range(self.n_segments): sat chrom[t_idx][s_idx] load_vec[sat] 1 if s_idx 0 and chrom[t_idx][s_idx-1] ! sat: total_score - switch_penalty total_score task_priority[t_idx] * (1 0.2 * (1 - load_vec[sat]/(np.mean(load_vec)1))) uniformity -np.std(load_vec) total_score 0.5 * uniformity return total_score def _crossover(self, p1, p2): point random.randint(1, self.n_tasks-1) c1 p1[:point] p2[point:] c2 p2[:point] p1[point:] return c1, c2 def _mutate(self, chrom, rate0.1): for t in range(self.n_tasks): for s in range(self.n_segments): if random.random() rate: chrom[t][s] random.randint(0, self.n_sats-1) return chrom def solve(self, task_priority): pop [] for _ in range(self.pop_size): chrom [[random.randint(0, self.n_sats-1) for _ in range(self.n_segments)] for _ in range(self.n_tasks)] pop.append(chrom) for gen in range(self.n_gen): fits [self._fitness(chrom, np.zeros(self.n_sats), task_priority) for chrom in pop] elite pop[np.argmax(fits)] new_pop [elite] while len(new_pop) self.pop_size: p1, p2 random.choices(pop, weightsfits, k2) c1, c2 self._crossover(p1, p2) c1 self._mutate(c1) c2 self._mutate(c2) new_pop.extend([c1, c2]) pop new_pop[:self.pop_size] best_idx np.argmax([self._fitness(chrom, np.zeros(self.n_sats), task_priority) for chrom in pop]) return pop[best_idx] class PreemptRepair: def __init__(self, sat_visibility_matrix, original_schedule): self.vis sat_visibility_matrix self.schedule original_schedule def handle_new_targets(self, new_target_windows, priority_new): n_sats self.vis.shape[1] assignments {} for (target, window) in new_target_windows.items(): candidates [(sat, self.vis[window.time_idx, sat]) for sat in range(n_sats) if self.vis[window.time_idx, sat] 0] if candidates: best_sat max(candidates, keylambda x: x[1]*priority_new[target])[0] assignments[target] best_sat else: # preempt lowest priority existing task existing_tasks [(t, self.schedule[t]) for t in self.schedule if self.schedule[t] is not None] if existing_tasks: lowest min(existing_tasks, keylambda x: x[1].get(priority, 0)) self.schedule[lowest[0]] None assignments[target] lowest[1][sat] return assignments def repair_failed_sats(self, failed_sats): affected_tasks [t for t, assign in self.schedule.items() if assign is not None and assign[sat] in failed_sats] cost_matrix np.zeros((len(affected_tasks), self.vis.shape[1])) for i, task in enumerate(affected_tasks): for sat in range(self.vis.shape[1]): if sat not in failed_sats and self.vis[task, sat] 0: cost_matrix[i, sat] -self.vis[task, sat] # negative because Hungarian minimizes else: cost_matrix[i, sat] 1e9 row_idx, col_idx linear_sum_assignment(cost_matrix) for i, task in enumerate(affected_tasks): self.schedule[task][sat] col_idx[i] return self.schedule class SimSAT: def __init__(self, n_sats24, n_targets8): self.n_sats n_sats self.n_targets n_targets self.time_slots 480 # 24h * 20 slots per hour def run_monte_carlo(self, n_runs100, with_schedulerTrue): coverage_ratios [] for _ in range(n_runs): vis_mat np.random.rand(self.time_slots, self.n_sats) 0.7 tasks np.random.choice(self.n_targets, self.time_slots, replaceTrue) if with_scheduler: ga DecompGA(self.n_targets, self.n_sats, self.time_slots//self.n_targets) schedule ga.solve(np.ones(self.n_targets)) coverage np.mean([1 for t in range(self.n_targets) for s in schedule[t] if vis_mat[s, t]]) else: coverage np.mean(vis_mat[:, :self.n_targets].any(axis1)) coverage_ratios.append(coverage) return np.mean(coverage_ratios), np.std(coverage_ratios) if __name__ __main__: sim SimSAT() mean_cov, std_cov sim.run_monte_carlo(n_runs50) print(fMean coverage: {mean_cov:.3f} /- {std_cov:.3f})