ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

数学建模国赛A题复现:多源融合定位与任务优化实战教程

数学建模国赛A题复现:多源融合定位与任务优化实战教程 数学建模国赛A题一直是很多队伍最重视也最容易拉开差距的题目。2025年国赛A题围绕移动机器人的多源融合定位与任务优化展开核心是让机器人利用轮式里程计、惯性测量单元、激光雷达、视觉等多种信息源在定位精度受限的环境里完成自定位、误差校正和任务路径优化。这篇复现教程会逐问拆解题目考核点给出数据建模、滤波融合、优化建模和论文写作的完整链路并用一套可以直接运行的 Python 示例代码把每一问的关键算法串起来。无论你是在准备 2026 年国赛还是想学习数模中的状态估计和优化建模方法这套思路都可以直接复用。需要说明的是竞赛题目的原始数据格式每年都会调整下面示例用于说明通用建模思路落地前要结合自己拿到的数据列名、单位和题目约束做适配。复现的价值不在于把官方赛题做过一遍而在于把“拿到题目后先怎么分析、再建什么模型、最后怎么写代码验证”这条主线固定下来。国赛A题通常信息量大题目正文里描述的场景、传感器参数、误差来源和数据表格往往是同一道题的多个侧面。如果只盯着代码忽略了对题目文字的结构化拆解很容易在第二问或第三问丢失重要约束条件。本文会按照“问题拆解 - 建模 - 代码实现 - 结果验证 - 论文呈现”的顺序逐问展开并在最后给出备赛阶段可以直接使用的检查清单。1. 先拆解2025国赛A题定位任务模型化先于写代码1.1 题目场景与三问常规结构国赛A题绝大多数情况是一道“综合性工程建模题”2025年A题选择的场景是移动机器人多源融合定位及任务优化。现实中的仓储机器人、巡检机器人、无人车都会遇到同类问题单一传感器在复杂环境下并不可靠轮式里程计会打滑惯性导航会漂移激光雷达在空旷区域特征稀疏视觉在光照变化时容易失效。多源融合定位要做的就是把多种传感器的观测数据按统计特性组合起来得到比任何单一传感器都更稳定、更精确的位置估计。从比赛题目结构来看A题一般会分成三到四个小问常见逻辑是第一问数据层。给出一组或几组传感器数据要求分析误差来源、统计误差分布、做数据预处理和时间对齐。这一问表面是数据处理实际考查的是对传感器误差模型的理解。第二问算法层。在数据基础上建立定位模型设计融合算法。这一问核心是状态估计典型解法包括最小二乘、扩展卡尔曼滤波、无迹卡尔曼滤波、粒子滤波以及基于因子图的优化方法。第三问应用层。把定位结果与任务优化结合例如在定位误差约束下规划机器人访问多个目标点的最优路径或评估某种部署方式对整个系统任务完成率的影响。这一问的关键是把定位不确定性与路径代价、时间代价、能耗代价统一成一个可求解的优化模型。针对这类结构备赛时的正确做法不是直接从代码开始敲而是先把题目文字里出现的物理量、变量、数据表、约束条件列一张表明确每一问的输入和输出。1.2 得分点在哪数据、模型、算法、验证四层从历年和近年优秀论文的评分取向看A题的得分点可以拆成四层层次考察内容常见失分点数据层数据读取、坐标变换、时间对齐、误差统计单位不统一、时间戳未对齐、数据读入后没有可视化检查模型层状态空间模型、观测模型、误差模型是否合理只套公式不解释状态量和观测量如何对应题目物理量算法层滤波器或优化算法实现是否正确、参数如何整定只调用库函数不说明参数取值依据没有不同算法对比验证层结果是否可视化、误差指标是否量化、灵敏度是否分析只有一张结果图没有误差表没有对噪声强度或参数变化的讨论这四个层次并不是线性关系而是相互支撑。数据层做不好模型层的滤波结果必然发散模型层做不好算法层再花哨也无法解释结果验证层做不好前面所有工作都很难转化为分数。1.3 复现路线先跑通最小链路再扩展备赛阶段不建议一上来就复现完整代码。更稳妥的顺序是先搭一个最小链路用一小段模拟数据或给定数据从“读数据 - 算误差 - 跑一个最简滤波 - 输出一张轨迹图”跑通然后再逐步加入坐标变换、异常值剔除、多算法对比、参数灵敏度分析。这条路线有三个好处。第一可以在早期暴露环境依赖问题避免比赛前一晚才发现某个库缺失。第二最小链路可以作为后续所有版本的“回归基线”修改算法后能对比性能是否提升。第三比赛现场时间紧张最小链路本身就可以作为第一版结果直接写入论文后续改进只是增量。2. 第一问复现传感器数据对齐、坐标变换与误差统计2.1 第一问在考什么第一问通常是让参赛者处理多源传感器数据回答三个问题数据是否可以用、误差有多大、误差是否符合某种分布。很多队伍在这一问只做了简单的画图导致后面第二问缺少误差模型支撑。实际上第一问的输出应当是一张“传感器误差清单”明确每种定位信息来源的精度水平并把它写进第二问的观测噪声矩阵。以移动机器人为例常见数据源包括轮式里程计输出相对位移短时精度高但长距离会产生累积误差。惯性测量单元包括加速度计和陀螺仪短时高频但存在积分漂移。超宽带UWB定位输出绝对坐标无累积误差但受遮挡和多径效应影响。激光雷达或视觉可提供局部地图和位姿关联精度受环境特征影响。第一问的数据预处理核心不是格式转换而是把不同传感器数据放到同一个时间和空间坐标系下比较。2.2 通用数据结构和预处理代码下面代码采用一个简化的 CSV 数据结构仅用于演示流程。实际题目中的数据列名可能是timestamp, enc_x, enc_y, imu_yaw, uwb_x, uwb_y, gt_x, gt_y你要先打印df.columns和df.head()查看再按实际列名适配。import pandas as pd import numpy as np import matplotlib.pyplot as plt # 读取原始数据 df pd.read_csv(sensor_data.csv) print(df.head()) print(df.columns.tolist()) print(df.isnull().sum()) # 去除重复时间戳按时间排序 df df.drop_duplicates(subset[timestamp]) df df.sort_values(timestamp).reset_index(dropTrue) # 时间戳单位统一为秒后续滤波需要固定时间步长 df[t] (df[timestamp] - df[timestamp].iloc[0]) / 1e9 print(数据时长: %.2f 秒, 数据点数: %d % (df[t].iloc[-1], len(df)))时间戳单位不统一是第一问最典型的坑。有的数据是 Unix 纳秒有的是毫秒还有的是从 0 开始的相对时间。统一时间轴后要检查时间间隔是否均匀如果不是均匀采样后面的卡尔曼滤波需要按实际时间步长更新不能直接假设固定dt。坐标变换也是常见考点。如果 UWB 给出的坐标是世界坐标而轮式里程计给出的是机器人局部累积位移那么必须先确认两者是否在同一坐标系下。若题目中里程计初始位置与 UWB 原点不一致需要先做平移对齐。# 假设置初始位置均为 (0, 0)将里程计相对位移转换成绝对坐标 # 如果题目给出了初始偏移则要加上偏移量 offset_x df[gt_x].iloc[0] - df[enc_x].iloc[0] offset_y df[gt_y].iloc[0] - df[enc_y].iloc[0] df[enc_abs_x] df[enc_x] offset_x df[enc_abs_y] df[enc_y] offset_y这段代码的关键在于不同传感器的“起点”未必相同。直接对原始坐标做误差比较会得到明显偏大的偏差这不是传感器误差而是坐标系原点不重合造成的。2.3 误差统计与可视化输出完成坐标对齐后分别计算里程计、UWB 相对真值的误差并输出均值、标准差和 RMSE。RMSE 是定位领域最常用的指标它同时衡量估计的偏差和波动。def eval_error(pred_x, pred_y, true_x, true_y): err np.sqrt((pred_x - true_x) ** 2 (pred_y - true_y) ** 2) rmse np.sqrt(np.mean(err ** 2)) mean_err np.mean(err) std_err np.std(err) max_err np.max(err) return {mean: mean_err, std: std_err, rmse: rmse, max: max_err} enc_metric eval_error(df[enc_abs_x], df[enc_abs_y], df[gt_x], df[gt_y]) uwb_metric eval_error(df[uwb_x], df[uwb_y], df[gt_x], df[gt_y]) result_df pd.DataFrame([enc_metric, uwb_metric], index[Encoder, UWB]) print(result_df.round(3))误差统计结果应该结合轨迹图一起看。绘制真实轨迹、里程计轨迹和 UWB 离散点能直观发现里程计的累积漂移方向和 UWB 的跳变位置。plt.figure(figsize(8, 6)) plt.plot(df[gt_x], df[gt_y], labelGround Truth, linewidth2) plt.plot(df[enc_abs_x], df[enc_abs_y], labelEncoder, linestyle--) plt.scatter(df[uwb_x][::20], df[uwb_y][::20], s8, labelUWB, alpha0.6) plt.xlabel(X (m)) plt.ylabel(Y (m)) plt.legend() plt.axis(equal) plt.savefig(trajectory_compare.png, dpi150)这张图在第一问论文里几乎是必备的。它能够直接说明两种信息来源的误差特征一个偏平滑但会累积漂移一个存在随机跳变但没有累积误差。2.4 运行结果与常见坑一个合理的运行结果是Encoder 的 RMSE 随着时间逐渐增大UWB 的 RMSE 相对稳定但存在尖峰。如果画图后发现 Encoder 轨迹与真值轨迹形态上已经完全不同说明不是简单噪声问题而是运动模型或坐标系配置有误。第一问常见坑如下问题现象可能原因处理方式误差很大且为固定偏差坐标系原点未对齐用初始真值减去初始测量值做平移误差随时间线性增大里程计累积误差属于正常现象说明需要后续融合误差曲线出现周期性尖峰时间戳未对齐使用了不同采样率数据重新检查时间同步做插值对齐统计结果的 RMSE 和均值差很多数据中有离群点绘制误差分布直方图决定是否剔除这一问的产出要能够回答“多源融合为什么必要”单一传感器要么有累积漂移要么有随机跳变无法同时满足长期稳定和短时平滑两个需求。这句话可以直接写进论文引言和模型假设部分。3. 第二问复现多源融合定位的状态估计模型与滤波代码3.1 为什么单传感器定位不够第一问的统计结果已经给出了答案。轮式里程计短期精度高但误差会通过积分不断累积UWB 提供绝对位置参考但跳变明显且在部分时刻可能缺失。把两者结合起来的自然思路是给两类信息分配权重运动过程由里程计推进绝对位置由 UWB 校正。这种思路在数学上对应状态估计问题。设定机器人状态向量为二维位置(x, y)和航向角yaw里程计给出预测UWB 给出观测校正。卡尔曼滤波是这类线性高斯系统的最优估计方法而实际机器人运动往往是非线性的所以更常用的是扩展卡尔曼滤波EKF或无迹卡尔曼滤波UKF。这里要明确一个概念融合不是简单加权平均。加权平均假设各传感器误差独立且恒定但实际上里程计误差随时间累积UWB 误差受环境遮挡影响动态权重变更合理的方式是把它们建模成噪声矩阵由滤波器在每一步根据协方差自动决定信任程度。3.2 状态向量、运动模型与观测模型设定状态向量x [px, py, vx, vy, yaw]^T其中px, py是平面位置vx, vy是速度yaw是航向角。运动模型使用线速度v和角速度w作为控制输入这一步与轮式里程计的输出对应。状态转移方程可以写成px_new px v * cos(yaw) * dt py_new py v * sin(yaw) * dt yaw_new yaw w * dt这段表达的含义是在没有新观测的时刻机器人按运动模型继续推演位置。实际题目中如果给出了陀螺仪航向角也可以直接把航向作为观测量输入减少累积误差。观测模型取决于第二问给出的测量信息。如果 UWB 直接给出平面坐标(zx, zy)那么观测方程是线性的zx px noise_u zy py noise_u观测噪声方差由第一问的 UWB 误差统计结果近似给出例如取 RMSE 的平方作为R对角元。3.3 扩展卡尔曼滤波完整实现以下是基于 Python NumPy 的一个最小 EKF 实现核心结构分五步预测、计算雅可比矩阵、更新协方差、计算卡尔曼增益、更新状态。import numpy as np class EKF: def __init__(self, dt, q_pos, q_yaw, r_uwb): self.dt dt self.x np.zeros(5) # [px, py, vx, vy, yaw] self.P np.eye(5) * 0.1 # 初始协方差 # 过程噪声协方差 Q self.Q np.diag([q_pos, q_pos, 0.05, 0.05, q_yaw]) # 观测噪声协方差 R self.R np.diag([r_uwb, r_uwb]) def predict(self, v, w): dt self.dt x self.x px, py, yaw x[0], x[1], x[4] # 状态预测 self.x[0] v * np.cos(yaw) * dt self.x[1] v * np.sin(yaw) * dt self.x[4] w * dt # 雅可比矩阵 F F np.eye(5) F[0, 4] -v * np.sin(yaw) * dt F[1, 4] v * np.cos(yaw) * dt # 协方差预测 self.P F self.P F.T self.Q def update(self, z): # 观测矩阵 H只观测 px, py H np.zeros((2, 5)) H[0, 0] 1.0 H[1, 1] 1.0 y z - H self.x S H self.P H.T self.R K self.P H.T np.linalg.inv(S) self.x self.x K y self.P (np.eye(5) - K H) self.P def run(self, v_list, w_list, uwb_obs): est_x, est_y [], [] for i, (v, w) in enumerate(zip(v_list, w_list)): self.predict(v, w) if uwb_obs[i] is not None: self.update(uwb_obs[i]) est_x.append(self.x[0]) est_y.append(self.x[1]) return np.array(est_x), np.array(est_y)这段代码中F矩阵来自非线性运动模型的线性化是 EKF 区别于标准卡尔曼滤波的关键。实际题目中如果运动模型更复杂例如加入了加速度状态量需要重新推导雅可比矩阵不能直接套用这里的F。3.4 Q、R矩阵调参和结果评估运行滤波后要像第一问一样计算融合结果的 RMSE并与单一传感器对比ekf EKF(dt0.1, q_pos0.01, q_yaw0.01, r_uwb0.05) est_x, est_y ekf.run(v_list, w_list, uwb_obs) fusion_err eval_error(est_x, est_y, df[gt_x], df[gt_y]) print(EKF RMSE:, fusion_err[rmse])Q和R是滤波器的核心超参数也是第二问论文中必须解释的部分。参数含义调大影响调小影响初始参考Q位置项对运动模型的信任程度滤波更依赖观测轨迹波动变大滤波更平滑但对突变响应慢取里程计噪声方差Q航向项航向角噪声大小航向更新更激进航向变化缓慢取陀螺仪噪声方差R对 UWB 观测的信任程度更信任运动模型轨迹平滑更信任观测跳变明显取第一问 UWB RMSE 平方调参没有固定公式但有一个可复现的流程先固定R为第一问统计结果然后从小到大扫描Q画出 RMSE 随Q变化的曲线。这个灵敏度分析图在论文中很有说服力说明你的参数不是随便拍的。如果融合后 RMSE 反而比单一传感器还差常见原因包括状态向量里缺少对系统偏差的估计例如里程计标定误差。时间步长dt与数据实际采样间隔不一致。R设置过小导致 UWB 的跳变直接进入最终结果。航向角单位是角度而不是弧度导致雅可比矩阵计算错误。4. 第三问复现带定位精度约束的任务路径优化建模与求解4.1 优化问题的目标、变量和约束第三问在 A 题里通常是“任务优化”它的难点不是算法本身而是把定位误差和任务路径结合成一个可求解的优化模型。以典型场景为例机器人在某个区域内需要从起点出发依次访问若干目标点最终返回起点。每个目标点有访问价值或时间窗口而机器人在运行过程中定位误差会不断累积只有经过某些校正区域时误差才能被降低。于是问题变成在满足定位精度上限的前提下如何设计访问顺序和路径使得总代价最小。这里的决策变量有两类。一类是目标点访问顺序属于组合优化另一类是路径选择在离散网格中属于路径规划问题。两类变量耦合在一起直接求解往往很困难因此国赛中的常见做法是分层建模先假设定位误差只在访问点之间累积然后对每个点对计算考虑定位代价的等效距离最后把问题转化为带权旅行商问题TSP或带时间窗的车辆路径问题VRPTW。4.2 数学规划模型设目标点编号为1, 2, ..., n地点 0 为起点。定义二进制变量x_ij 1表示从点 i 直接走到点 j目标函数为最小化总代价min sum_{i,j} c_ij * x_ij其中c_ij是点 i 到点 j 的等效代价它由两部分组成实际路径距离d_ij和定位误差惩罚项。定位误差惩罚项可以写成c_ij d_ij lambda * max(0, E_i delta(d_ij) - E_max)其中E_i是在点 i 处的累计定位误差delta(d_ij)是沿这段路径增加的误差lambda是惩罚系数E_max是任务允许的最大定位误差。约束条件包括每个目标点恰好访问一次sum_i x_ij 1, for all j 从每个点恰好离开一次sum_j x_ij 1, for all i 消除子回路约束u_j u_i 1 - n * (1 - x_ij)这个模型的关键在于c_ij不是固定不变的它依赖前序点的累计误差因此不能直接套标准 TSP 求解器。常见处理方法是迭代求解先用d_ij算一个初始路径然后根据该路径计算各点误差重新修正c_ij再求解重复若干次直到路径稳定。4.3 基于遗传算法的求解代码当 n 在 20 以内时可以用动态规划精确求解 TSP当 n 更大或者约束复杂时遗传算法是更实用的选择。下面给出一个基于 Python 的遗传算法框架用访问顺序编码染色体通过选择、交叉、变异搜索最优路径。import random import numpy as np def total_cost(path, cost_matrix): cost cost_matrix[0, path[0]] for i in range(len(path) - 1): cost cost_matrix[path[i], path[i 1]] cost cost_matrix[path[-1], 0] return cost def create_individual(n): path list(range(1, n 1)) random.shuffle(path) return path def mutate(path, p0.1): if random.random() p: i, j random.sample(range(len(path)), 2) path[i], path[j] path[j], path[i] return path def crossover(p1, p2): n len(p1) a random.randint(0, n - 1) b random.randint(a 1, n) child [None] * n child[a:b] p1[a:b] pos b for gene in p2: if gene not in child: if pos n: pos 0 child[pos] gene pos 1 return child def genetic_tsp(cost_matrix, pop_size200, generations500, seed42): random.seed(seed) n len(cost_matrix) - 1 pop [create_individual(n) for _ in range(pop_size)] for gen in range(generations): scored sorted(pop, keylambda p: total_cost(p, cost_matrix)) pop scored[:pop_size // 2] while len(pop) pop_size: p1 random.choice(scored[:pop_size // 2]) p2 random.choice(scored[:pop_size // 2]) child crossover(p1, p2) child mutate(child) pop.append(child) best min(pop, keylambda p: total_cost(p, cost_matrix)) return best, total_cost(best, cost_matrix)这段代码把路径优化问题当成标准求解器来用但要注意如果你的cost_matrix第三问中需要按定位误差动态更新那么不能只运行一次遗传算法而要在迭代框架内反复调用让路径与误差彼此收敛。运行方式如下best_path, best_cost genetic_tsp(cost_matrix) print(最优访问顺序:, best_path) print(最小等效代价:, best_cost)4.4 结果验证与轨迹可视化第三问的结果不能只给一个最优顺序还要解释为什么这个顺序最优。需要画两张图。第一张是访问顺序和路径轨迹图标注每个目标点编号和累计定位误差。第二张是迭代收敛曲线体现遗传算法在迭代中代价下降趋势证明优化过程有效。plt.plot(history_cost) plt.xlabel(Generation) plt.ylabel(Total Cost) plt.title(GA Convergence Curve) plt.savefig(ga_convergence.png, dpi150)如果最终路径中出现了明显的交叉或者误差惩罚项比路径距离还大说明lambda没有取好或者E_max过严。此时不要直接增大惩罚系数而是先绘制各目标点误差累积曲线确认误差累积模型是否合理。5. 论文写作把建模过程变成得分点5.1 模型假设和符号表A 题论文的评分老师通常快速浏览摘要、模型假设、模型建立和结果分析四部分。模型假设不能照抄题目也不能写“假设数据准确”这种废话。正确写法是每个假设都对应一个建模选择。例如假设 UWB 定位误差服从零均值高斯分布。这个假设让第二问可以使用卡尔曼滤波框架同时说明如果误差出现重尾需要改用 Huber 鲁棒滤波。假设机器人匀速运动且时间步长固定。这个假设简化了运动模型但要在灵敏度分析中说明当速度波动增大时模型的误差影响。假设任务访问点之间的路径为直线。如果实际环境有障碍物需要把障碍物约束加入路径规划层。符号表也是高分论文的标配。把所有变量统一整理成表格让评阅老师在 10 秒内看清你的模型结构。5.2 图、表、代码对应关系论文中的每一张图都要有“可读结论”。不要只放一张轨迹图而不解释图中的曲线代表什么。推荐的做法是“图 一段结论 一张误差对比表”。例如第一问可以这样组织轨迹对比图直观展示里程计漂移和 UWB 跳变。误差分布直方图展示误差近似高斯分布为滤波建模做铺垫。误差指标表列出 RMSE、均值、标准差作为第二问R矩阵的依据。第二问的图表应重点放在融合前后对比而不是只放滤波器的内部状态。5.3 灵敏度分析与模型评价灵敏度分析是 A 题论文拉开差距的关键部分。至少要回答三个问题当传感器噪声增大 20% 时定位误差如何变化当Q和R参数变化时融合结果是否稳定当任务目标点数量增加时优化算法耗时和结果质量如何变化灵敏度分析不需要做得很复杂关键是体现“我的模型对参数变化是稳健的或可知的”。例如下面的脚本可以扫描q_pos参数并输出 RMSE 变化for q in [0.001, 0.01, 0.1, 1.0]: ekf EKF(dt0.1, q_posq, q_yaw0.01, r_uwb0.05) est_x, est_y ekf.run(v_list, w_list, uwb_obs) rmse eval_error(est_x, est_y, df[gt_x], df[gt_y])[rmse] print(q_pos %.3f, RMSE %.4f % (q, rmse))这种实验在竞赛现场 10 分钟就能完成但它在论文里的价值非常高直接证明你的参数选择有依据。6. 常见问题排查从现象到根因6.1 数据读入和时间戳问题现象代码能运行但滤波轨迹和真实轨迹严重偏离或者误差统计结果不合理。排查顺序打印df.head()和df.dtypes确认列名和数据类型。检查时间戳单位确认是秒、毫秒还是纳秒。检查时间间隔均值确认dt设置是否合理。检查是否存在 NaN 或重复时间戳。用散点图画出原始观测确认数据本身没有位置反转。处理方式统一时间单位对缺失观测采用上一时刻有效值插值重复时间戳取最后一次记录。6.2 滤波发散或结果跳变现象EKF 运行到某一步后位置估计出现巨大跳变甚至飞离真值轨迹。可能原因和排查顺序R过小导致滤波器对观测过度信任UWB 的离群点直接拉偏位置。对策增大R或对 UWB 进行离群点剔除。雅可比矩阵F计算错误尤其是航向角导数和速度项。对策与数值差分对比验证雅可比矩阵。时间步长dt与数据采样间隔不匹配导致预测步长过大。对策按实际时间间隔逐点滤波而不是用固定步长。角度单位混用航向角在弧度与角度之间切换导致状态突变。对策全局统一使用弧度并在predict前后打印角度检查。6.3 优化算法不收敛现象遗传算法迭代很多代代价曲线仍然没有下降趋势或最终路径存在明显的交叉。排查顺序检查cost_matrix是否对称如果非对称要确认问题定义是否允许方向差异。检查交叉和变异算子是否破坏了“每个点访问一次”的约束。增大pop_size和generations观察收敛曲线是否改善。对比随机搜索的代价确认遗传算法确实优于随机方案。如果目标函数包含定位误差惩罚单独打印误差项和距离项确认惩罚项的尺度是否过大。6.4 代码复现时的环境问题国赛现场环境往往是团队自己准备的 Python 环境最容易出现的问题是版本不一致。python --version pip list | findstr numpy pip list | findstr pandas pip list | findstr matplotlib建议比赛前两天就固定环境版本并导出一份requirements.txtnumpy1.24.3 pandas2.0.3 matplotlib3.7.2 scipy1.10.1不要在现场升级大版本尤其是 numpy 和 scipy很多老代码在高版本下会出现 API 兼容问题。7. 备赛建议国赛A题的可执行复盘清单7.1 三天赛程怎么分配国赛时间是三天三夜A 题的工作量很大。建议按以下节奏分配时间段主要工作产出物第一天上午读题、查资料、拆解问题问题拆解表、变量表、初步假设第一天下午完成第一问数据处理和可视化误差统计表、轨迹对比图第二天全天完成第二问滤波模型与调参EKF/UKF 结果图、误差对比表第三天上午完成第三问优化建模与求解最优路径结果、收敛曲线第三天下午写论文、统一图表、检查摘要完整论文草稿第三天晚上检查脚本、补充灵敏度分析最终论文和代码提交这里的关键是第三天上午必须已经有完整结果不能等到最后 6 小时才开始写论文。论文写作是耗时的图和表的排版比想象中更费时。7.2 代码工程化与可复现性竞赛代码不需要软件工程级别完善但至少要保证“一条命令能跑通”。建议按下面结构组织project/ ├── data/ │ ├── raw/ # 原始数据不修改 │ └── processed/ # 预处理后的数据 ├── code/ │ ├── preprocessing.py │ ├── ekf.py │ ├── optimization.py │ └── main.py ├── figures/ # 论文用图 └── requirements.txt每个文件只做一件事main.py按顺序调用各模块。这样比赛后期改参数、补实验时不会把代码弄乱。7.3 从复现到原创如何形成自己的模型库复现一道国赛题只是第一步。备赛阶段更高效的做法是把每次复现中可复用的模块沉淀成自己的“数模工具箱”。比如数据对齐、误差评估、EKF、UKF、遗传算法 TSP 求解这些代码在后续比赛中大概率还能用。每次复盘问自己三个问题这一问有没有更优的建模方式例如第一问是否要加入鲁棒统计第二问是否改用因子图。我的结果如何更可信是画图更清楚还是误差表更完整还是灵敏度分析更有说服力。如果题目数据完全换掉这套流程能不能在 30 分钟内重新跑通如果能就说明你已经具备了稳定的解题链路。A 题不会考你背过的原题但一定会在“数据建模 状态估计 优化决策”这条主线上找突破口。把本文的流程完整复现一遍并整理出自己的代码模板比刷十套模拟题更有价值。
返回列表