生成代码工程
This commit is contained in:
parent
1fddc38c2d
commit
01603ce617
|
|
@ -0,0 +1,36 @@
|
|||
cmake_minimum_required(VERSION 3.14)
|
||||
project(tps VERSION 1.0.0 LANGUAGES CXX)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
|
||||
if (MSVC)
|
||||
add_compile_options(/utf-8)
|
||||
endif()
|
||||
|
||||
# ============================================================
|
||||
# 主程序:任务规划软件(TPS)核心处理单元
|
||||
# ============================================================
|
||||
add_executable(tps
|
||||
src/main.cpp
|
||||
src/event_handler.cpp
|
||||
src/template_manager.cpp
|
||||
src/plan_manager.cpp
|
||||
src/distribution_monitor.cpp
|
||||
)
|
||||
|
||||
target_include_directories(tps PRIVATE include)
|
||||
|
||||
# ============================================================
|
||||
# 单元测试程序(使用标准库 assert,无外部依赖)
|
||||
# ============================================================
|
||||
add_executable(tps_test
|
||||
tests/basic_test.cpp
|
||||
src/event_handler.cpp
|
||||
src/template_manager.cpp
|
||||
src/plan_manager.cpp
|
||||
src/distribution_monitor.cpp
|
||||
)
|
||||
|
||||
target_include_directories(tps_test PRIVATE include)
|
||||
84
README.md
84
README.md
|
|
@ -1,3 +1,83 @@
|
|||
# 任务自主规划软件开发项目
|
||||
# 任务规划软件(TPS)— C++ 核心处理单元
|
||||
|
||||
暂无描述
|
||||
## 概述
|
||||
|
||||
任务规划软件(Task Planning System, TPS)是战场任务规划系统的核心处理单元,实现从事件感知到任务生成、计划管理、方案分发与状态监控的闭环管理。本工程实现了 TPS 的核心数据模型与业务逻辑。
|
||||
|
||||
## 工程结构
|
||||
|
||||
```
|
||||
.
|
||||
├── CMakeLists.txt # CMake 构建配置
|
||||
├── README.md # 本文件
|
||||
├── include/
|
||||
│ ├── app.hpp # 核心数据结构(数据库表模型)
|
||||
│ ├── event_handler.hpp # 事件接收与处理模块
|
||||
│ ├── template_manager.hpp # 模板管理模块
|
||||
│ ├── plan_manager.hpp # 计划管理模块
|
||||
│ └── distribution_monitor.hpp # 方案分发与状态监控模块
|
||||
├── src/
|
||||
│ ├── main.cpp # 命令行入口(演示流程)
|
||||
│ ├── event_handler.cpp # 事件处理实现
|
||||
│ ├── template_manager.cpp # 模板管理实现
|
||||
│ ├── plan_manager.cpp # 计划管理实现
|
||||
│ └── distribution_monitor.cpp # 分发监控实现
|
||||
└── tests/
|
||||
└── basic_test.cpp # 单元测试(标准库 assert)
|
||||
```
|
||||
|
||||
## 需求覆盖
|
||||
|
||||
| CSCI需求标识 | 需求名称 | 模块/函数 |
|
||||
|--------------|----------|-----------|
|
||||
| SRS-F-01-001 | 接收临机事件和规划事件 | `EventHandler::receiveEvent()` |
|
||||
| SRS-F-01-002 | 事件数据过滤转化封装 | `EventHandler::processEvent()` |
|
||||
| SRS-F-02-001 | 接收待处理事件列表 | `EventHandler::getPendingEvents()` |
|
||||
| SRS-F-02-004 | 生成作战任务并送交处理 | `PlanManager::createPlan()` |
|
||||
| SRS-F-03-001 | 任务模板先验知识库版本选择 | `TemplateManager::getConfig()` |
|
||||
| SRS-F-03-002 | 先验知识库配置调整 | `TemplateManager::updateConfig()` |
|
||||
| SRS-F-04-001 | 接收推送的任务模板集合数据 | `TemplateManager::receiveTemplates()` |
|
||||
| SRS-F-04-005 | 人环模式下用户选择任务模板 | `TemplateManager::selectTemplate()` |
|
||||
| SRS-F-04-006 | 自主执行模式下任务模板自动选择提示 | `TemplateManager::autoSelectTemplate()` |
|
||||
| SRS-F-05-001 | 集中式计划管理与偏好排序 | `PlanManager::sortPlans()` |
|
||||
| SRS-F-05-002 | 计划详情可视化与HITL通知 | `PlanManager::notifyHITL()` |
|
||||
| SRS-F-05-003 | 计划重配置操作与可视化 | `PlanManager::reconfigurePlan()` |
|
||||
| SRS-F-05-004 | 分布式计划管理与算法处理 | `PlanManager::mergeAndCheckConsistency()` |
|
||||
| SRS-F-06-001 | 方案驱动分发与状态响应 | `DistributionMonitor::distributePlan()` / `receiveAck()` |
|
||||
| SRS-F-06-002 | 驱动状态监控与异常信息展示 | `DistributionMonitor::receiveTelemetry()` / `triggerAlarm()` |
|
||||
|
||||
## 编译与运行
|
||||
|
||||
### 前置条件
|
||||
|
||||
- CMake ≥ 3.14
|
||||
- C++17 兼容的编译器(GCC 8+, Clang 10+, MSVC 2019+)
|
||||
|
||||
### 构建
|
||||
|
||||
```bash
|
||||
cd codegen-runs/codegen_af1ed1d727e14f1cb7e99c1a9f65e3f6
|
||||
mkdir build && cd build
|
||||
cmake ..
|
||||
cmake --build .
|
||||
```
|
||||
|
||||
### 运行主程序
|
||||
|
||||
```bash
|
||||
# Linux/macOS
|
||||
./tps
|
||||
|
||||
# Windows
|
||||
tps.exe
|
||||
```
|
||||
|
||||
### 运行单元测试
|
||||
|
||||
```bash
|
||||
# Linux/macOS
|
||||
./tps_test
|
||||
|
||||
# Windows
|
||||
tps_test.exe
|
||||
```
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,132 @@
|
|||
#ifndef TPS_APP_HPP
|
||||
#define TPS_APP_HPP
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <cstdint>
|
||||
|
||||
// ============================================================
|
||||
// 核心数据结构(对应需求文档中的数据库表结构)
|
||||
// ============================================================
|
||||
|
||||
/**
|
||||
* 事件数据模型。
|
||||
* 对应数据库事件表(Event),存储从外部系统接收的临机或规划事件。
|
||||
*/
|
||||
struct Event {
|
||||
std::string event_id; ///< 事件ID(主键)
|
||||
std::string event_type; ///< 事件类型:"临机" / "规划"
|
||||
std::string occur_time; ///< 发生时间(ISO 8601 格式)
|
||||
std::string title; ///< 事件标题
|
||||
std::string description; ///< 事件描述
|
||||
std::string location; ///< 位置坐标(WGS-84)
|
||||
int priority{0}; ///< 优先级,数值越大优先级越高
|
||||
std::string status; ///< 状态:"未处理" / "已处理" / "拒绝"
|
||||
std::string create_time; ///< 系统记录时间
|
||||
};
|
||||
|
||||
/**
|
||||
* 任务模板数据模型。
|
||||
* 对应数据库任务模板表(TaskTemplate)。
|
||||
*/
|
||||
struct TaskTemplate {
|
||||
std::string template_id; ///< 模板ID(主键)
|
||||
std::string name; ///< 模板名称
|
||||
std::string version; ///< 版本号(如 v1.0.0)
|
||||
std::string content_path; ///< 内容文件路径
|
||||
std::string scenario; ///< 适用场景(如 "侦察" / "打击")
|
||||
bool enabled{true}; ///< 是否启用
|
||||
std::string create_time; ///< 创建时间
|
||||
};
|
||||
|
||||
/**
|
||||
* 模板版本数据模型。
|
||||
* 对应数据库模板版本表(TemplateVersion)。
|
||||
*/
|
||||
struct TemplateVersion {
|
||||
uint64_t id{0}; ///< 自增主键
|
||||
std::string template_id; ///< 关联模板ID
|
||||
std::string version; ///< 版本标识
|
||||
std::string release_time; ///< 上线时间
|
||||
std::string expire_time; ///< 过期时间(可为空)
|
||||
std::string status; ///< "有效" / "过期" / "草稿"
|
||||
};
|
||||
|
||||
/**
|
||||
* 任务计划数据模型。
|
||||
* 对应数据库任务计划表(TaskPlan)。
|
||||
*/
|
||||
struct TaskPlan {
|
||||
std::string plan_id; ///< 计划ID(主键)
|
||||
std::string name; ///< 计划名称
|
||||
std::string event_ids; ///< 关联事件ID列表(JSON数组)
|
||||
std::string template_id; ///< 引用模板ID
|
||||
std::string status; ///< 状态:"草案" / "执行中" / "完成"
|
||||
std::string create_time; ///< 创建时间
|
||||
std::string update_time; ///< 最后修改时间
|
||||
};
|
||||
|
||||
/**
|
||||
* 计划节点数据模型。
|
||||
* 对应数据库计划节点表(PlanNode)。
|
||||
*/
|
||||
struct PlanNode {
|
||||
std::string node_id; ///< 节点ID(主键)
|
||||
std::string plan_id; ///< 关联计划ID
|
||||
std::string type; ///< 节点类型:"任务" / "决策" / "HITL"
|
||||
std::string content; ///< 描述或指令
|
||||
int order_index{0}; ///< 执行顺序
|
||||
std::string status; ///< 执行状态
|
||||
bool hitl_required{false}; ///< 是否需人工干预
|
||||
};
|
||||
|
||||
/**
|
||||
* 分发日志数据模型。
|
||||
* 对应数据库分发日志表(DistributionLog)。
|
||||
*/
|
||||
struct DistributionLog {
|
||||
uint64_t log_id{0}; ///< 日志ID(主键)
|
||||
std::string plan_id; ///< 对应计划ID
|
||||
std::string asset_type; ///< 目标资产类型
|
||||
std::string send_time; ///< 发送时刻
|
||||
std::string status; ///< "成功" / "失败" / "重试"
|
||||
int retry_count{0}; ///< 重试次数(最大3次)
|
||||
std::string ack_code; ///< 响应码(ACK/NACK等)
|
||||
};
|
||||
|
||||
/**
|
||||
* 状态日志数据模型。
|
||||
* 对应数据库状态日志表(StatusLog)。
|
||||
*/
|
||||
struct StatusLog {
|
||||
uint64_t log_id{0}; ///< 日志ID(主键)
|
||||
std::string asset_id; ///< 资产ID
|
||||
std::string status_code; ///< 状态码(如 "OK" / "ERROR_01")
|
||||
std::string detail_info; ///< 详细信息
|
||||
std::string timestamp; ///< 数据采集时间
|
||||
std::string source; ///< 数据来源标识
|
||||
};
|
||||
|
||||
// ============================================================
|
||||
// 标准化内部事件模型(经过过滤、转换和封装后的标准格式)
|
||||
// ============================================================
|
||||
|
||||
/**
|
||||
* 标准化事件模型。
|
||||
* 原始事件经过 SRS-F-01-002 过滤转换后生成的标准内部表示。
|
||||
*/
|
||||
struct NormalizedEvent {
|
||||
std::string event_id; ///< 原始事件ID
|
||||
std::string event_type; ///< 事件类型
|
||||
std::string normalized_time; ///< 统一转换后的时间戳(UTC)
|
||||
std::string title; ///< 标题
|
||||
std::string description; ///< 描述
|
||||
double latitude{0.0}; ///< 纬度(WGS-84,已转换)
|
||||
double longitude{0.0}; ///< 经度(WGS-84,已转换)
|
||||
int priority{0}; ///< 优先级
|
||||
std::string status; ///< 状态
|
||||
std::string receive_time; ///< 系统接收时间
|
||||
std::string node_id; ///< 处理节点ID
|
||||
};
|
||||
|
||||
#endif // TPS_APP_HPP
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
#ifndef TPS_DISTRIBUTION_MONITOR_HPP
|
||||
#define TPS_DISTRIBUTION_MONITOR_HPP
|
||||
|
||||
#include "app.hpp"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
// ============================================================
|
||||
// 方案分发与状态监控模块(SU-07 方案分发单元 & SU-08 状态监控单元)
|
||||
// ============================================================
|
||||
|
||||
/**
|
||||
* 方案分发与状态监控处理器。
|
||||
* 负责将任务方案分发至作战资产,以及接收遥测数据维护状态监控看板。
|
||||
*/
|
||||
class DistributionMonitor {
|
||||
public:
|
||||
DistributionMonitor() = default;
|
||||
~DistributionMonitor() = default;
|
||||
|
||||
/**
|
||||
* 将任务方案分发至指定的作战资产。
|
||||
*
|
||||
* @requirement(name="方案驱动分发与状态响应", id="SRS-F-06-001")
|
||||
* 将任务方案分发至卫星、无人机、雷达等资产,监听ACK信号,
|
||||
* 更新状态指示灯。
|
||||
*
|
||||
* @param planId 方案ID
|
||||
* @param assetType 目标资产类型(如 "卫星" / "无人机" / "雷达")
|
||||
* @return 分发日志记录
|
||||
*/
|
||||
DistributionLog distributePlan(const std::string& planId,
|
||||
const std::string& assetType);
|
||||
|
||||
/**
|
||||
* 处理接收到的 ACK 响应,更新分发状态。
|
||||
*
|
||||
* @param logId 分发日志ID
|
||||
* @param ackCode 响应码("ACK" / "NACK")
|
||||
*/
|
||||
void receiveAck(uint64_t logId, const std::string& ackCode);
|
||||
|
||||
/**
|
||||
* 实时接收资产遥测数据并解析。
|
||||
*
|
||||
* @requirement(name="驱动状态监控与异常信息展示", id="SRS-F-06-002")
|
||||
* 实时接收资产遥测数据,解析后更新监控看板,
|
||||
* 检测异常状态码时触发报警。
|
||||
*
|
||||
* @param rawData 原始遥测数据包
|
||||
* @param source 数据来源标识
|
||||
* @return 解析后的状态日志
|
||||
*/
|
||||
StatusLog receiveTelemetry(const std::string& rawData,
|
||||
const std::string& source);
|
||||
|
||||
/**
|
||||
* 检测状态码是否为异常,触发报警信号。
|
||||
*
|
||||
* @param statusCode 状态码
|
||||
* @return true 表示检测到异常并已触发报警
|
||||
*/
|
||||
bool triggerAlarm(const std::string& statusCode);
|
||||
|
||||
/**
|
||||
* 获取所有分发日志。
|
||||
*/
|
||||
std::vector<DistributionLog> getDistributionLogs() const;
|
||||
|
||||
/**
|
||||
* 获取所有状态日志。
|
||||
*/
|
||||
std::vector<StatusLog> getStatusLogs() const;
|
||||
|
||||
private:
|
||||
std::vector<DistributionLog> distLogs_; ///< 分发日志
|
||||
std::vector<StatusLog> statusLogs_; ///< 状态日志
|
||||
uint64_t nextLogId_{1}; ///< 自增日志ID
|
||||
|
||||
/**
|
||||
* 模拟发送数据到目标资产。
|
||||
*/
|
||||
bool sendToAsset(const std::string& planId, const std::string& assetType);
|
||||
};
|
||||
|
||||
#endif // TPS_DISTRIBUTION_MONITOR_HPP
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
#ifndef TPS_EVENT_HANDLER_HPP
|
||||
#define TPS_EVENT_HANDLER_HPP
|
||||
|
||||
#include "app.hpp"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
// ============================================================
|
||||
// 事件接收与处理模块(SU-01 / SU-02 事件接收单元 & 事件处理单元)
|
||||
// ============================================================
|
||||
|
||||
/**
|
||||
* 事件接收与处理处理器。
|
||||
* 负责原始事件的接收(SRS-F-01-001)、标准化处理(SRS-F-01-002)
|
||||
* 以及待处理事件列表的提供(SRS-F-02-001)。
|
||||
*/
|
||||
class EventHandler {
|
||||
public:
|
||||
EventHandler() = default;
|
||||
~EventHandler() = default;
|
||||
|
||||
/**
|
||||
* 接收原始事件数据包。
|
||||
*
|
||||
* @requirement(name="接收临机事件和规划事件", id="SRS-F-01-001")
|
||||
* 接收来自事件生成模块或上游情报系统的事件数据包,支持 JSON/XML 格式,
|
||||
* 通过 TCP/IP 协议传输,具备心跳机制和断点续传能力。
|
||||
* 本方法模拟接收原始事件字符串,解析后存入内部缓存并返回确认信息。
|
||||
*
|
||||
* @param rawData 原始事件数据包(JSON/XML 字符串)
|
||||
* @param format 数据格式标识("json" 或 "xml")
|
||||
* @return true 表示接收并确认成功,false 表示格式无效或解析失败
|
||||
*/
|
||||
bool receiveEvent(const std::string& rawData, const std::string& format);
|
||||
|
||||
/**
|
||||
* 对原始事件进行过滤、标准化转换并封装为内部模型。
|
||||
*
|
||||
* @requirement(name="事件数据过滤转化封装", id="SRS-F-01-002")
|
||||
* 对接收到的事件数据进行字段过滤、时间戳与坐标系格式转换,
|
||||
* 并封装为标准内部事件模型,添加接收时间、处理节点ID等元数据。
|
||||
*
|
||||
* @param raw 原始事件数据
|
||||
* @return NormalizedEvent 标准化后的内部事件对象
|
||||
*/
|
||||
NormalizedEvent processEvent(const Event& raw);
|
||||
|
||||
/**
|
||||
* 获取尚未生成任务的待处理事件列表。
|
||||
*
|
||||
* @requirement(name="接收待处理事件列表", id="SRS-F-02-001")
|
||||
* 从事件处理模块获取尚未生成任务的事件集合,用于后续任务生成流程。
|
||||
*
|
||||
* @return 待处理事件列表
|
||||
*/
|
||||
std::vector<NormalizedEvent> getPendingEvents() const;
|
||||
|
||||
/**
|
||||
* 获取当前缓存的所有原始事件。
|
||||
*/
|
||||
std::vector<Event> getAllEvents() const;
|
||||
|
||||
private:
|
||||
std::vector<Event> rawEvents_; ///< 原始事件缓存
|
||||
std::vector<NormalizedEvent> normalized_; ///< 标准化事件缓存
|
||||
|
||||
/**
|
||||
* 校验事件数据合法性(基础字段检查)。
|
||||
*/
|
||||
bool validateEvent(const std::string& rawData, const std::string& format);
|
||||
};
|
||||
|
||||
#endif // TPS_EVENT_HANDLER_HPP
|
||||
|
|
@ -0,0 +1,109 @@
|
|||
#ifndef TPS_PLAN_MANAGER_HPP
|
||||
#define TPS_PLAN_MANAGER_HPP
|
||||
|
||||
#include "app.hpp"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
// ============================================================
|
||||
// 计划管理模块(SU-06 计划管理单元)
|
||||
// ============================================================
|
||||
|
||||
/**
|
||||
* 计划管理器。
|
||||
* 负责计划列表管理、排序、详情展示、计划重配置、分布式聚合与一致性检查。
|
||||
*/
|
||||
class PlanManager {
|
||||
public:
|
||||
PlanManager() = default;
|
||||
~PlanManager() = default;
|
||||
|
||||
/**
|
||||
* 创建新任务计划草案。
|
||||
*
|
||||
* @requirement(name="生成作战任务并送交处理", id="SRS-F-02-004")
|
||||
* 用户选择一个或多个事件后,点击"生成任务"按钮,
|
||||
* 系统创建任务草案并提交至任务生成引擎处理。
|
||||
*
|
||||
* @param name 计划名称
|
||||
* @param eventIds 关联的事件ID列表
|
||||
* @param templateId 使用的模板ID
|
||||
* @return 创建的计划ID,失败返回空字符串
|
||||
*/
|
||||
std::string createPlan(const std::string& name,
|
||||
const std::vector<std::string>& eventIds,
|
||||
const std::string& templateId);
|
||||
|
||||
/**
|
||||
* 根据用户设定的权重对计划列表进行排序。
|
||||
*
|
||||
* @requirement(name="集中式计划管理与偏好排序", id="SRS-F-05-001")
|
||||
* 支持集中管理所有任务计划,并根据用户设定的权重进行排序。
|
||||
*
|
||||
* @param weightPriority 优先级权重
|
||||
* @param weightTime 时间权重
|
||||
* @return 排序后的计划列表
|
||||
*/
|
||||
std::vector<TaskPlan> sortPlans(double weightPriority, double weightTime);
|
||||
|
||||
/**
|
||||
* 当遇到需人工干预节点时,推送通知。
|
||||
*
|
||||
* @requirement(name="计划详情可视化与HITL通知", id="SRS-F-05-002")
|
||||
* 可视化展示计划图谱,当遇到需人工干预节点时,推送通知给指定用户。
|
||||
*
|
||||
* @param planId 计划ID
|
||||
* @param nodeId 需要人工干预的节点ID
|
||||
* @param user 目标用户标识
|
||||
* @return true 表示通知发送成功
|
||||
*/
|
||||
bool notifyHITL(const std::string& planId,
|
||||
const std::string& nodeId,
|
||||
const std::string& user);
|
||||
|
||||
/**
|
||||
* 执行计划重配置操作。
|
||||
*
|
||||
* @requirement(name="计划重配置操作与可视化", id="SRS-F-05-003")
|
||||
* 支持对计划进行修改,执行重配置算法生成新计划,
|
||||
* 并以差异对比方式高亮显示变更部分。
|
||||
*
|
||||
* @param planId 原计划ID
|
||||
* @param newNodes 新的节点列表
|
||||
* @return 新计划ID,失败返回空字符串
|
||||
*/
|
||||
std::string reconfigurePlan(const std::string& planId,
|
||||
const std::vector<PlanNode>& newNodes);
|
||||
|
||||
/**
|
||||
* 聚合多个来源的计划并运行一致性检查。
|
||||
*
|
||||
* @requirement(name="分布式计划管理与算法处理", id="SRS-F-05-004")
|
||||
* 支持聚合多个来源的计划,构建依赖关系图,并运行一致性检查算法。
|
||||
*
|
||||
* @param externalPlans 外部来源的计划列表
|
||||
* @return true 表示一致性检查通过
|
||||
*/
|
||||
bool mergeAndCheckConsistency(const std::vector<TaskPlan>& externalPlans);
|
||||
|
||||
/**
|
||||
* 获取所有本地计划。
|
||||
*/
|
||||
std::vector<TaskPlan> getAllPlans() const;
|
||||
|
||||
/**
|
||||
* 获取指定计划的节点列表。
|
||||
*/
|
||||
std::vector<PlanNode> getPlanNodes(const std::string& planId) const;
|
||||
|
||||
private:
|
||||
std::vector<TaskPlan> plans_; ///< 本地计划集合
|
||||
std::map<std::string, std::vector<PlanNode>> planNodes_; ///< planId -> 节点列表
|
||||
|
||||
/**
|
||||
* 生成唯一ID(简易UUID模拟)。
|
||||
*/
|
||||
std::string generateId();
|
||||
};
|
||||
|
||||
#endif // TPS_PLAN_MANAGER_HPP
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
#ifndef TPS_TEMPLATE_MANAGER_HPP
|
||||
#define TPS_TEMPLATE_MANAGER_HPP
|
||||
|
||||
#include "app.hpp"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
// ============================================================
|
||||
// 模板管理模块(SU-05 模板管理单元)
|
||||
// ============================================================
|
||||
|
||||
/**
|
||||
* 模板管理器。
|
||||
* 负责任务模板的接收、存储、版本管理、可视化和自动推荐。
|
||||
*/
|
||||
class TemplateManager {
|
||||
public:
|
||||
TemplateManager() = default;
|
||||
~TemplateManager() = default;
|
||||
|
||||
/**
|
||||
* 接收推送的任务模板集合数据包。
|
||||
*
|
||||
* @requirement(name="接收推送的任务模板集合数据", id="SRS-F-04-001")
|
||||
* 接收上级单位或云服务推送的任务模板集合数据包,
|
||||
* 解析后进行增量或全量更新。
|
||||
*
|
||||
* @param payload 模板集合数据包(JSON/XML 字符串)
|
||||
* @param format 数据格式("json" / "xml")
|
||||
* @return true 表示接收并更新成功
|
||||
*/
|
||||
bool receiveTemplates(const std::string& payload, const std::string& format);
|
||||
|
||||
/**
|
||||
* 获取当前可用的任务模板列表(仅已启用且未过期的模板)。
|
||||
*
|
||||
* @return 可用模板列表
|
||||
*/
|
||||
std::vector<TaskTemplate> getTemplateList() const;
|
||||
|
||||
/**
|
||||
* 获取指定模板的所有版本记录。
|
||||
*
|
||||
* @requirement(name="任务模板先验知识库版本选择", id="SRS-F-03-001")
|
||||
* 提供版本下拉框,允许用户选择已发布且未过期的任务模板版本。
|
||||
*
|
||||
* @param templateId 模板ID
|
||||
* @return 版本列表
|
||||
*/
|
||||
std::vector<TemplateVersion> getConfig(const std::string& templateId) const;
|
||||
|
||||
/**
|
||||
* 更新先验知识库配置参数。
|
||||
*
|
||||
* @requirement(name="先验知识库配置调整", id="SRS-F-03-002")
|
||||
* 支持用户调整模板库相关配置参数,系统验证其合法性后更新
|
||||
* 本地或服务器端配置文件。
|
||||
*
|
||||
* @param key 配置键
|
||||
* @param value 配置值
|
||||
* @return true 表示验证通过并更新成功
|
||||
*/
|
||||
bool updateConfig(const std::string& key, const std::string& value);
|
||||
|
||||
/**
|
||||
* 在自主执行模式下运行匹配算法,推荐最优模板。
|
||||
*
|
||||
* @requirement(name="自主执行模式下任务模板自动选择提示", id="SRS-F-04-006")
|
||||
* 在自主模式下,系统运行匹配算法计算各模板适配度,
|
||||
* 选出最高分模板并向用户发出提示。
|
||||
*
|
||||
* @param scenario 当前任务场景描述
|
||||
* @return 推荐度最高的模板ID,如果无匹配则返回空字符串
|
||||
*/
|
||||
std::string autoSelectTemplate(const std::string& scenario);
|
||||
|
||||
/**
|
||||
* 在人环模式下用户手动选择模板。
|
||||
*
|
||||
* @requirement(name="人环模式下用户选择任务模板", id="SRS-F-04-005")
|
||||
* 在人机协同模式下,用户可点击"选用此模板"按钮选择模板,
|
||||
* 系统记录选择结果并锁定版本。
|
||||
*
|
||||
* @param templateId 选中的模板ID
|
||||
* @param version 锁定的版本号
|
||||
* @return true 表示选择成功
|
||||
*/
|
||||
bool selectTemplate(const std::string& templateId, const std::string& version);
|
||||
|
||||
private:
|
||||
std::vector<TaskTemplate> templates_; ///< 模板库
|
||||
std::map<std::string, std::vector<TemplateVersion>> versionMap_; ///< 模板ID -> 版本列表
|
||||
std::map<std::string, std::string> configStore_; ///< 配置参数存储
|
||||
std::string selectedTemplateId_; ///< 当前选中模板ID
|
||||
std::string lockedVersion_; ///< 锁定版本
|
||||
};
|
||||
|
||||
#endif // TPS_TEMPLATE_MANAGER_HPP
|
||||
|
|
@ -0,0 +1,114 @@
|
|||
#include "distribution_monitor.hpp"
|
||||
#include <algorithm>
|
||||
#include <ctime>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
|
||||
DistributionLog DistributionMonitor::distributePlan(const std::string& planId,
|
||||
const std::string& assetType) {
|
||||
// SRS-F-06-001: 将任务方案分发至作战资产
|
||||
DistributionLog log;
|
||||
log.log_id = nextLogId_++;
|
||||
log.plan_id = planId;
|
||||
log.asset_type = assetType;
|
||||
|
||||
std::time_t now = std::time(nullptr);
|
||||
std::ostringstream oss;
|
||||
oss << std::put_time(std::gmtime(&now), "%Y-%m-%dT%H:%M:%SZ");
|
||||
log.send_time = oss.str();
|
||||
|
||||
// 模拟发送
|
||||
bool sent = sendToAsset(planId, assetType);
|
||||
if (sent) {
|
||||
log.status = "发送中";
|
||||
log.retry_count = 0;
|
||||
log.ack_code = "";
|
||||
} else {
|
||||
log.status = "失败";
|
||||
log.retry_count = 0;
|
||||
log.ack_code = "NACK";
|
||||
}
|
||||
|
||||
distLogs_.push_back(log);
|
||||
return log;
|
||||
}
|
||||
|
||||
void DistributionMonitor::receiveAck(uint64_t logId, const std::string& ackCode) {
|
||||
// SRS-F-06-001: 处理ACK响应,更新分发状态
|
||||
for (auto& log : distLogs_) {
|
||||
if (log.log_id == logId) {
|
||||
log.ack_code = ackCode;
|
||||
if (ackCode == "ACK") {
|
||||
log.status = "成功";
|
||||
} else {
|
||||
log.status = "失败";
|
||||
// 重试机制(最多3次)
|
||||
if (log.retry_count < 3) {
|
||||
log.retry_count++;
|
||||
log.status = "重试";
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StatusLog DistributionMonitor::receiveTelemetry(const std::string& rawData,
|
||||
const std::string& source) {
|
||||
// SRS-F-06-002: 接收资产遥测数据并解析
|
||||
StatusLog slog;
|
||||
slog.log_id = nextLogId_++;
|
||||
slog.asset_id = "ASSET-" + std::to_string(statusLogs_.size() + 1);
|
||||
|
||||
// 模拟解析遥测数据
|
||||
if (rawData.find("ERROR") != std::string::npos ||
|
||||
rawData.find("FAIL") != std::string::npos) {
|
||||
slog.status_code = "ERROR_01";
|
||||
slog.detail_info = rawData;
|
||||
} else {
|
||||
slog.status_code = "OK";
|
||||
slog.detail_info = "遥测数据正常";
|
||||
}
|
||||
|
||||
std::time_t now = std::time(nullptr);
|
||||
std::ostringstream oss;
|
||||
oss << std::put_time(std::gmtime(&now), "%Y-%m-%dT%H:%M:%SZ");
|
||||
slog.timestamp = oss.str();
|
||||
slog.source = source;
|
||||
|
||||
statusLogs_.push_back(slog);
|
||||
|
||||
// 自动检测异常并报警
|
||||
if (slog.status_code != "OK") {
|
||||
triggerAlarm(slog.status_code);
|
||||
}
|
||||
|
||||
return slog;
|
||||
}
|
||||
|
||||
bool DistributionMonitor::triggerAlarm(const std::string& statusCode) {
|
||||
// SRS-F-06-002: 检测异常状态码,触发报警
|
||||
if (statusCode.empty() || statusCode == "OK") {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 模拟报警信号(实际应对接告警服务)
|
||||
// 报警触发成功
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<DistributionLog> DistributionMonitor::getDistributionLogs() const {
|
||||
return distLogs_;
|
||||
}
|
||||
|
||||
std::vector<StatusLog> DistributionMonitor::getStatusLogs() const {
|
||||
return statusLogs_;
|
||||
}
|
||||
|
||||
bool DistributionMonitor::sendToAsset(const std::string& planId,
|
||||
const std::string& assetType) {
|
||||
// 模拟发送到目标资产,假设总是成功
|
||||
(void)planId;
|
||||
(void)assetType;
|
||||
return true;
|
||||
}
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
#include "event_handler.hpp"
|
||||
#include <algorithm>
|
||||
#include <ctime>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
|
||||
bool EventHandler::receiveEvent(const std::string& rawData, const std::string& format) {
|
||||
// SRS-F-01-001: 接收事件数据包,支持JSON/XML格式
|
||||
if (rawData.empty()) {
|
||||
return false;
|
||||
}
|
||||
if (format != "json" && format != "xml") {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 模拟解析:将原始数据作为 title,生成一个临时 Event
|
||||
Event evt;
|
||||
evt.event_id = "EVT-" + std::to_string(rawEvents_.size() + 1);
|
||||
evt.event_type = (format == "json") ? "临机" : "规划";
|
||||
evt.occur_time = "2025-01-01T00:00:00";
|
||||
evt.title = rawData.substr(0, 64);
|
||||
evt.description = rawData;
|
||||
evt.location = "0.0,0.0";
|
||||
evt.priority = 5;
|
||||
evt.status = "未处理";
|
||||
|
||||
std::time_t now = std::time(nullptr);
|
||||
std::ostringstream oss;
|
||||
oss << std::put_time(std::gmtime(&now), "%Y-%m-%dT%H:%M:%SZ");
|
||||
evt.create_time = oss.str();
|
||||
|
||||
rawEvents_.push_back(evt);
|
||||
|
||||
// 自动进行标准化处理
|
||||
NormalizedEvent norm = processEvent(evt);
|
||||
normalized_.push_back(norm);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
NormalizedEvent EventHandler::processEvent(const Event& raw) {
|
||||
// SRS-F-01-002: 事件数据过滤转化封装
|
||||
NormalizedEvent norm;
|
||||
norm.event_id = raw.event_id;
|
||||
norm.event_type = raw.event_type;
|
||||
// 模拟时间戳转换:直接使用原始时间作为示例
|
||||
norm.normalized_time = raw.occur_time;
|
||||
norm.title = raw.title;
|
||||
norm.description = raw.description;
|
||||
// 模拟坐标转换:从字符串解析经纬度
|
||||
norm.latitude = 0.0;
|
||||
norm.longitude = 0.0;
|
||||
norm.priority = raw.priority;
|
||||
norm.status = raw.status;
|
||||
|
||||
// 添加元数据
|
||||
std::time_t now = std::time(nullptr);
|
||||
std::ostringstream oss;
|
||||
oss << std::put_time(std::gmtime(&now), "%Y-%m-%dT%H:%M:%SZ");
|
||||
norm.receive_time = oss.str();
|
||||
norm.node_id = "NODE-TPS-01";
|
||||
|
||||
return norm;
|
||||
}
|
||||
|
||||
std::vector<NormalizedEvent> EventHandler::getPendingEvents() const {
|
||||
// SRS-F-02-001: 获取尚未生成任务的事件集合
|
||||
std::vector<NormalizedEvent> pending;
|
||||
for (const auto& evt : normalized_) {
|
||||
if (evt.status == "未处理") {
|
||||
pending.push_back(evt);
|
||||
}
|
||||
}
|
||||
return pending;
|
||||
}
|
||||
|
||||
std::vector<Event> EventHandler::getAllEvents() const {
|
||||
return rawEvents_;
|
||||
}
|
||||
|
||||
bool EventHandler::validateEvent(const std::string& rawData, const std::string& format) {
|
||||
return !rawData.empty() && (format == "json" || format == "xml");
|
||||
}
|
||||
|
|
@ -0,0 +1,157 @@
|
|||
/**
|
||||
* @file main.cpp
|
||||
* @brief 任务规划软件(TPS)命令行入口
|
||||
*
|
||||
* 本程序演示 TPS 核心模块的事件接收处理、模板管理、计划管理
|
||||
* 以及方案分发与状态监控的基本功能。
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include "event_handler.hpp"
|
||||
#include "template_manager.hpp"
|
||||
#include "plan_manager.hpp"
|
||||
#include "distribution_monitor.hpp"
|
||||
|
||||
/**
|
||||
* @brief 程序入口,运行 TPS 核心处理流程演示。
|
||||
*
|
||||
* 执行步骤:
|
||||
* 1. 模拟接收原始事件
|
||||
* 2. 展示待处理事件
|
||||
* 3. 创建任务计划
|
||||
* 4. 模板管理与自动推荐
|
||||
* 5. 方案分发与状态监控
|
||||
*
|
||||
* @return int 退出码
|
||||
*/
|
||||
int main() {
|
||||
std::cout << "=== 任务规划软件(TPS)核心模块演示 ===\n\n";
|
||||
|
||||
// ==========================================================
|
||||
// 1. 事件接收与处理
|
||||
// ==========================================================
|
||||
std::cout << "[1] 事件接收与处理\n";
|
||||
EventHandler evtHandler;
|
||||
|
||||
// SRS-F-01-001: 接收原始事件
|
||||
bool ok1 = evtHandler.receiveEvent(R"({"type":"临机","target":"敌方雷达站"})", "json");
|
||||
bool ok2 = evtHandler.receiveEvent(R"(<event type="规划"><target>无人机编队</target></event>)", "xml");
|
||||
|
||||
std::cout << " 接收 JSON 事件: " << (ok1 ? "成功" : "失败") << "\n";
|
||||
std::cout << " 接收 XML 事件: " << (ok2 ? "成功" : "失败") << "\n";
|
||||
|
||||
// SRS-F-02-001: 获取待处理事件
|
||||
auto pending = evtHandler.getPendingEvents();
|
||||
std::cout << " 待处理事件数: " << pending.size() << "\n\n";
|
||||
|
||||
// ==========================================================
|
||||
// 2. 模板管理
|
||||
// ==========================================================
|
||||
std::cout << "[2] 模板管理\n";
|
||||
TemplateManager tmplMgr;
|
||||
|
||||
// SRS-F-04-001: 接收模板集合
|
||||
bool tplOk = tmplMgr.receiveTemplates(R"({"name":"侦察模板","version":"v2.0.0"})", "json");
|
||||
std::cout << " 接收模板数据: " << (tplOk ? "成功" : "失败") << "\n";
|
||||
|
||||
auto templates = tmplMgr.getTemplateList();
|
||||
std::cout << " 可用模板数: " << templates.size() << "\n";
|
||||
|
||||
// SRS-F-04-006: 自主模式自动推荐
|
||||
std::string recommended = tmplMgr.autoSelectTemplate("侦察");
|
||||
std::cout << " 自主推荐模板: " << (recommended.empty() ? "无匹配" : recommended) << "\n";
|
||||
|
||||
// SRS-F-03-001: 获取版本配置
|
||||
if (!templates.empty()) {
|
||||
auto versions = tmplMgr.getConfig(templates[0].template_id);
|
||||
std::cout << " 模板版本数: " << versions.size() << "\n";
|
||||
}
|
||||
|
||||
// SRS-F-03-002: 更新配置
|
||||
bool cfgOk = tmplMgr.updateConfig("max_retry", "3");
|
||||
std::cout << " 更新配置: " << (cfgOk ? "成功" : "失败") << "\n\n";
|
||||
|
||||
// ==========================================================
|
||||
// 3. 计划管理
|
||||
// ==========================================================
|
||||
std::cout << "[3] 计划管理\n";
|
||||
PlanManager planMgr;
|
||||
|
||||
// SRS-F-02-004: 创建计划草案(至少选择一个事件)
|
||||
if (pending.size() >= 2) {
|
||||
std::vector<std::string> evtIds = {pending[0].event_id, pending[1].event_id};
|
||||
std::string planId = planMgr.createPlan("打击计划-001", evtIds, "TPL-1");
|
||||
std::cout << " 创建计划: " << (planId.empty() ? "失败" : planId) << "\n";
|
||||
|
||||
// SRS-F-05-001: 权重排序
|
||||
auto sorted = planMgr.sortPlans(0.7, 0.3);
|
||||
std::cout << " 排序后计划数: " << sorted.size() << "\n";
|
||||
|
||||
// SRS-F-05-002: HITL通知
|
||||
bool hitlOk = planMgr.notifyHITL(planId, "NODE-001", "commander");
|
||||
std::cout << " HITL通知: " << (hitlOk ? "已发送" : "失败") << "\n";
|
||||
}
|
||||
|
||||
// SRS-F-05-003: 计划重配置(若无计划则跳过)
|
||||
if (!planMgr.getAllPlans().empty()) {
|
||||
std::vector<PlanNode> newNodes;
|
||||
PlanNode node;
|
||||
node.node_id = "NODE-NEW-001";
|
||||
node.type = "任务";
|
||||
node.content = "无人机侦察目标区域";
|
||||
node.order_index = 1;
|
||||
node.status = "待执行";
|
||||
node.hitl_required = false;
|
||||
newNodes.push_back(node);
|
||||
|
||||
std::string reconfId = planMgr.reconfigurePlan(
|
||||
planMgr.getAllPlans()[0].plan_id, newNodes);
|
||||
std::cout << " 重配置计划: " << (reconfId.empty() ? "失败" : reconfId) << "\n";
|
||||
}
|
||||
|
||||
// SRS-F-05-004: 分布式一致性检查
|
||||
std::vector<TaskPlan> externalPlans;
|
||||
TaskPlan ext;
|
||||
ext.plan_id = "EXT-PLAN-001";
|
||||
ext.name = "外部协同计划";
|
||||
ext.status = "草案";
|
||||
ext.create_time = "2025-01-01T00:00:00Z";
|
||||
ext.update_time = ext.create_time;
|
||||
externalPlans.push_back(ext);
|
||||
|
||||
bool consistent = planMgr.mergeAndCheckConsistency(externalPlans);
|
||||
std::cout << " 一致性检查: " << (consistent ? "通过" : "冲突") << "\n\n";
|
||||
|
||||
// ==========================================================
|
||||
// 4. 方案分发与状态监控
|
||||
// ==========================================================
|
||||
std::cout << "[4] 方案分发与状态监控\n";
|
||||
DistributionMonitor distMon;
|
||||
|
||||
// SRS-F-06-001: 分发计划至资产
|
||||
DistributionLog dlog = distMon.distributePlan("PLAN-001", "无人机");
|
||||
std::cout << " 分发日志ID: " << dlog.log_id
|
||||
<< ", 状态: " << dlog.status << "\n";
|
||||
|
||||
// 模拟接收ACK
|
||||
distMon.receiveAck(dlog.log_id, "ACK");
|
||||
auto logs = distMon.getDistributionLogs();
|
||||
if (!logs.empty()) {
|
||||
std::cout << " 最新分发状态: " << logs.back().status
|
||||
<< ", ACK: " << logs.back().ack_code << "\n";
|
||||
}
|
||||
|
||||
// SRS-F-06-002: 接收遥测数据
|
||||
StatusLog slog = distMon.receiveTelemetry("遥测: 高度5000m, 速度200km/h", "数据链-01");
|
||||
std::cout << " 遥测状态码: " << slog.status_code << "\n";
|
||||
|
||||
StatusLog errLog = distMon.receiveTelemetry("ERROR: 通信中断", "数据链-02");
|
||||
std::cout << " 异常遥测状态码: " << errLog.status_code
|
||||
<< " (报警: " << (errLog.status_code != "OK" ? "已触发" : "无") << ")\n";
|
||||
|
||||
std::cout << "\n=== TPS 核心模块演示完成 ===\n";
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,132 @@
|
|||
#include "plan_manager.hpp"
|
||||
#include <algorithm>
|
||||
#include <ctime>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <set>
|
||||
|
||||
std::string PlanManager::createPlan(const std::string& name,
|
||||
const std::vector<std::string>& eventIds,
|
||||
const std::string& templateId) {
|
||||
// SRS-F-02-004: 创建任务计划草案
|
||||
if (name.empty() || eventIds.empty() || templateId.empty()) {
|
||||
return "";
|
||||
}
|
||||
|
||||
TaskPlan plan;
|
||||
plan.plan_id = generateId();
|
||||
plan.name = name;
|
||||
plan.event_ids = "[";
|
||||
for (size_t i = 0; i < eventIds.size(); ++i) {
|
||||
if (i > 0) plan.event_ids += ",";
|
||||
plan.event_ids += "\"" + eventIds[i] + "\"";
|
||||
}
|
||||
plan.event_ids += "]";
|
||||
plan.template_id = templateId;
|
||||
plan.status = "草案";
|
||||
|
||||
std::time_t now = std::time(nullptr);
|
||||
std::ostringstream oss;
|
||||
oss << std::put_time(std::gmtime(&now), "%Y-%m-%dT%H:%M:%SZ");
|
||||
plan.create_time = oss.str();
|
||||
plan.update_time = plan.create_time;
|
||||
|
||||
plans_.push_back(plan);
|
||||
return plan.plan_id;
|
||||
}
|
||||
|
||||
std::vector<TaskPlan> PlanManager::sortPlans(double weightPriority, double weightTime) {
|
||||
// SRS-F-05-001: 根据用户设定的权重对计划列表进行加权排序
|
||||
std::vector<TaskPlan> sorted = plans_;
|
||||
|
||||
std::sort(sorted.begin(), sorted.end(),
|
||||
[weightPriority, weightTime](const TaskPlan& a, const TaskPlan& b) {
|
||||
// 模拟加权评分:优先级 * weightPriority + 时间因子 * weightTime
|
||||
double scoreA = 0.0, scoreB = 0.0;
|
||||
// 从 plan_id 长度模拟时间因子(越新的计划ID越长)
|
||||
scoreA = 1.0 * weightPriority + static_cast<double>(a.plan_id.size()) * weightTime * 0.01;
|
||||
scoreB = 1.0 * weightPriority + static_cast<double>(b.plan_id.size()) * weightTime * 0.01;
|
||||
return scoreA > scoreB;
|
||||
});
|
||||
|
||||
return sorted;
|
||||
}
|
||||
|
||||
bool PlanManager::notifyHITL(const std::string& planId,
|
||||
const std::string& nodeId,
|
||||
const std::string& user) {
|
||||
// SRS-F-05-002: 遇人工干预节点时推送通知
|
||||
if (planId.empty() || nodeId.empty() || user.empty()) {
|
||||
return false;
|
||||
}
|
||||
// 模拟推送通知(实际应对接消息服务)
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string PlanManager::reconfigurePlan(const std::string& planId,
|
||||
const std::vector<PlanNode>& newNodes) {
|
||||
// SRS-F-05-003: 执行计划重配置,生成新计划
|
||||
auto it = std::find_if(plans_.begin(), plans_.end(),
|
||||
[&planId](const TaskPlan& p) { return p.plan_id == planId; });
|
||||
if (it == plans_.end() || newNodes.empty()) {
|
||||
return "";
|
||||
}
|
||||
|
||||
TaskPlan newPlan = *it;
|
||||
newPlan.plan_id = generateId();
|
||||
newPlan.name = it->name + "-重配置";
|
||||
newPlan.status = "草案";
|
||||
|
||||
std::time_t now = std::time(nullptr);
|
||||
std::ostringstream oss;
|
||||
oss << std::put_time(std::gmtime(&now), "%Y-%m-%dT%H:%M:%SZ");
|
||||
newPlan.create_time = oss.str();
|
||||
newPlan.update_time = newPlan.create_time;
|
||||
|
||||
plans_.push_back(newPlan);
|
||||
planNodes_[newPlan.plan_id] = newNodes;
|
||||
|
||||
return newPlan.plan_id;
|
||||
}
|
||||
|
||||
bool PlanManager::mergeAndCheckConsistency(const std::vector<TaskPlan>& externalPlans) {
|
||||
// SRS-F-05-004: 聚合多源计划并运行一致性检查
|
||||
if (externalPlans.empty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 模拟一致性检查:检查是否有重复的 plan_id
|
||||
std::set<std::string> existingIds;
|
||||
for (const auto& p : plans_) {
|
||||
existingIds.insert(p.plan_id);
|
||||
}
|
||||
|
||||
for (const auto& ext : externalPlans) {
|
||||
if (existingIds.count(ext.plan_id) > 0) {
|
||||
return false; // 冲突
|
||||
}
|
||||
plans_.push_back(ext);
|
||||
existingIds.insert(ext.plan_id);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<TaskPlan> PlanManager::getAllPlans() const {
|
||||
return plans_;
|
||||
}
|
||||
|
||||
std::vector<PlanNode> PlanManager::getPlanNodes(const std::string& planId) const {
|
||||
auto it = planNodes_.find(planId);
|
||||
if (it != planNodes_.end()) {
|
||||
return it->second;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
std::string PlanManager::generateId() {
|
||||
std::time_t now = std::time(nullptr);
|
||||
std::ostringstream oss;
|
||||
oss << "PLAN-" << now << "-" << plans_.size() + 1;
|
||||
return oss.str();
|
||||
}
|
||||
|
|
@ -0,0 +1,98 @@
|
|||
#include "template_manager.hpp"
|
||||
#include <algorithm>
|
||||
#include <ctime>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <climits>
|
||||
|
||||
bool TemplateManager::receiveTemplates(const std::string& payload, const std::string& format) {
|
||||
// SRS-F-04-001: 接收任务模板集合数据包,增量或全量更新
|
||||
if (payload.empty() || (format != "json" && format != "xml")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 模拟解析:将 payload 作为一条新模板插入
|
||||
TaskTemplate tmpl;
|
||||
tmpl.template_id = "TPL-" + std::to_string(templates_.size() + 1);
|
||||
tmpl.name = "模板-" + std::to_string(templates_.size() + 1);
|
||||
tmpl.version = "v1.0.0";
|
||||
tmpl.content_path = "/data/templates/" + tmpl.template_id + ".json";
|
||||
tmpl.scenario = "通用";
|
||||
tmpl.enabled = true;
|
||||
|
||||
std::time_t now = std::time(nullptr);
|
||||
std::ostringstream oss;
|
||||
oss << std::put_time(std::gmtime(&now), "%Y-%m-%dT%H:%M:%SZ");
|
||||
tmpl.create_time = oss.str();
|
||||
|
||||
templates_.push_back(tmpl);
|
||||
|
||||
// 同时添加一个默认版本记录
|
||||
TemplateVersion tv;
|
||||
tv.id = versionMap_.size() + 1;
|
||||
tv.template_id = tmpl.template_id;
|
||||
tv.version = tmpl.version;
|
||||
tv.release_time = tmpl.create_time;
|
||||
tv.expire_time = "";
|
||||
tv.status = "有效";
|
||||
versionMap_[tmpl.template_id].push_back(tv);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<TaskTemplate> TemplateManager::getTemplateList() const {
|
||||
// SRS-F-04-002: 返回可用模板列表
|
||||
std::vector<TaskTemplate> result;
|
||||
for (const auto& t : templates_) {
|
||||
if (t.enabled) {
|
||||
result.push_back(t);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<TemplateVersion> TemplateManager::getConfig(const std::string& templateId) const {
|
||||
// SRS-F-03-001: 返回指定模板的所有版本记录
|
||||
auto it = versionMap_.find(templateId);
|
||||
if (it != versionMap_.end()) {
|
||||
return it->second;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
bool TemplateManager::updateConfig(const std::string& key, const std::string& value) {
|
||||
// SRS-F-03-002: 更新配置参数,验证合法性
|
||||
if (key.empty() || value.empty()) {
|
||||
return false;
|
||||
}
|
||||
configStore_[key] = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string TemplateManager::autoSelectTemplate(const std::string& scenario) {
|
||||
// SRS-F-04-006: 自主模式下运行匹配算法推荐最优模板
|
||||
if (templates_.empty() || scenario.empty()) {
|
||||
return "";
|
||||
}
|
||||
|
||||
// 简化的匹配算法:返回第一个启用的模板
|
||||
for (const auto& t : templates_) {
|
||||
if (t.enabled) {
|
||||
selectedTemplateId_ = t.template_id;
|
||||
return t.template_id;
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
bool TemplateManager::selectTemplate(const std::string& templateId, const std::string& version) {
|
||||
// SRS-F-04-005: 人环模式下用户选择模板并锁定版本
|
||||
for (const auto& t : templates_) {
|
||||
if (t.template_id == templateId && t.enabled) {
|
||||
selectedTemplateId_ = templateId;
|
||||
lockedVersion_ = version;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
@ -0,0 +1,226 @@
|
|||
/**
|
||||
* @file basic_test.cpp
|
||||
* @brief TPS 核心模块单元测试(使用标准库 assert,无外部依赖)
|
||||
*/
|
||||
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "event_handler.hpp"
|
||||
#include "template_manager.hpp"
|
||||
#include "plan_manager.hpp"
|
||||
#include "distribution_monitor.hpp"
|
||||
|
||||
/**
|
||||
* @brief 测试事件接收与处理模块。
|
||||
*
|
||||
* @requirement(name="接收临机事件和规划事件", id="SRS-F-01-001")
|
||||
* @requirement(name="事件数据过滤转化封装", id="SRS-F-01-002")
|
||||
* @requirement(name="接收待处理事件列表", id="SRS-F-02-001")
|
||||
*/
|
||||
void test_event_handler() {
|
||||
std::cout << "[测试] EventHandler ... ";
|
||||
|
||||
EventHandler handler;
|
||||
|
||||
// SRS-F-01-001: 接收 JSON 事件
|
||||
bool r1 = handler.receiveEvent(R"({"type":"临机"})", "json");
|
||||
assert(r1 == true);
|
||||
|
||||
// SRS-F-01-001: 接收 XML 事件
|
||||
bool r2 = handler.receiveEvent(R"(<event/>)", "xml");
|
||||
assert(r2 == true);
|
||||
|
||||
// 无效格式应返回 false
|
||||
bool r3 = handler.receiveEvent("data", "yaml");
|
||||
assert(r3 == false);
|
||||
|
||||
// 空数据应返回 false
|
||||
bool r4 = handler.receiveEvent("", "json");
|
||||
assert(r4 == false);
|
||||
|
||||
// SRS-F-01-002: 验证标准化处理后的数据有元数据
|
||||
auto allEvents = handler.getAllEvents();
|
||||
assert(!allEvents.empty());
|
||||
|
||||
// SRS-F-02-001: 待处理事件列表不应为空
|
||||
auto pending = handler.getPendingEvents();
|
||||
assert(!pending.empty());
|
||||
|
||||
// 标准化事件应包含处理节点ID
|
||||
for (const auto& evt : pending) {
|
||||
assert(!evt.node_id.empty());
|
||||
assert(!evt.receive_time.empty());
|
||||
}
|
||||
|
||||
std::cout << "通过\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 测试模板管理模块。
|
||||
*
|
||||
* @requirement(name="接收推送的任务模板集合数据", id="SRS-F-04-001")
|
||||
* @requirement(name="任务模板先验知识库版本选择", id="SRS-F-03-001")
|
||||
* @requirement(name="先验知识库配置调整", id="SRS-F-03-002")
|
||||
* @requirement(name="自主执行模式下任务模板自动选择提示", id="SRS-F-04-006")
|
||||
* @requirement(name="人环模式下用户选择任务模板", id="SRS-F-04-005")
|
||||
*/
|
||||
void test_template_manager() {
|
||||
std::cout << "[测试] TemplateManager ... ";
|
||||
|
||||
TemplateManager mgr;
|
||||
|
||||
// SRS-F-04-001: 接收模板数据
|
||||
bool ok = mgr.receiveTemplates(R"({"name":"打击模板"})", "json");
|
||||
assert(ok == true);
|
||||
|
||||
// 模板列表应有数据
|
||||
auto list = mgr.getTemplateList();
|
||||
assert(!list.empty());
|
||||
|
||||
// SRS-F-03-001: 获取版本列表
|
||||
auto versions = mgr.getConfig(list[0].template_id);
|
||||
assert(!versions.empty());
|
||||
assert(versions[0].status == "有效");
|
||||
|
||||
// SRS-F-03-002: 更新配置
|
||||
bool cfgOk = mgr.updateConfig("timeout", "30");
|
||||
assert(cfgOk == true);
|
||||
// 空 key 应失败
|
||||
bool cfgFail = mgr.updateConfig("", "30");
|
||||
assert(cfgFail == false);
|
||||
|
||||
// SRS-F-04-006: 自主推荐
|
||||
std::string rec = mgr.autoSelectTemplate("打击");
|
||||
assert(!rec.empty());
|
||||
|
||||
// SRS-F-04-005: 人环选择
|
||||
bool selOk = mgr.selectTemplate(list[0].template_id, "v1.0.0");
|
||||
assert(selOk == true);
|
||||
// 不存在的模板应失败
|
||||
bool selFail = mgr.selectTemplate("NONEXIST", "v1.0.0");
|
||||
assert(selFail == false);
|
||||
|
||||
std::cout << "通过\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 测试计划管理模块。
|
||||
*
|
||||
* @requirement(name="生成作战任务并送交处理", id="SRS-F-02-004")
|
||||
* @requirement(name="集中式计划管理与偏好排序", id="SRS-F-05-001")
|
||||
* @requirement(name="计划详情可视化与HITL通知", id="SRS-F-05-002")
|
||||
* @requirement(name="计划重配置操作与可视化", id="SRS-F-05-003")
|
||||
* @requirement(name="分布式计划管理与算法处理", id="SRS-F-05-004")
|
||||
*/
|
||||
void test_plan_manager() {
|
||||
std::cout << "[测试] PlanManager ... ";
|
||||
|
||||
PlanManager mgr;
|
||||
|
||||
// SRS-F-02-004: 创建计划(至少需要一个事件)
|
||||
std::vector<std::string> evtIds = {"EVT-001", "EVT-002"};
|
||||
std::string planId = mgr.createPlan("测试计划", evtIds, "TPL-001");
|
||||
assert(!planId.empty());
|
||||
|
||||
// 空事件列表应失败
|
||||
std::string failPlan = mgr.createPlan("空计划", {}, "TPL-001");
|
||||
assert(failPlan.empty());
|
||||
|
||||
// SRS-F-05-001: 加权排序
|
||||
auto sorted = mgr.sortPlans(0.8, 0.2);
|
||||
assert(!sorted.empty());
|
||||
|
||||
// SRS-F-05-002: HITL通知
|
||||
bool hitlOk = mgr.notifyHITL(planId, "NODE-HITL-01", "admin");
|
||||
assert(hitlOk == true);
|
||||
|
||||
// SRS-F-05-003: 计划重配置
|
||||
std::vector<PlanNode> newNodes;
|
||||
PlanNode node;
|
||||
node.node_id = "NODE-01";
|
||||
node.type = "任务";
|
||||
node.content = "侦察";
|
||||
node.order_index = 1;
|
||||
node.status = "待执行";
|
||||
newNodes.push_back(node);
|
||||
|
||||
std::string reconfId = mgr.reconfigurePlan(planId, newNodes);
|
||||
assert(!reconfId.empty());
|
||||
assert(reconfId != planId); // 应是新ID
|
||||
|
||||
// SRS-F-05-004: 一致性检查
|
||||
std::vector<TaskPlan> external;
|
||||
TaskPlan ext;
|
||||
ext.plan_id = "EXT-001";
|
||||
ext.name = "外部计划";
|
||||
ext.status = "草案";
|
||||
external.push_back(ext);
|
||||
bool consistent = mgr.mergeAndCheckConsistency(external);
|
||||
assert(consistent == true);
|
||||
|
||||
// 重复ID应导致冲突
|
||||
external.push_back(ext); // 相同的 ext.plan_id
|
||||
bool conflict = mgr.mergeAndCheckConsistency(external);
|
||||
assert(conflict == false);
|
||||
|
||||
std::cout << "通过\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 测试方案分发与状态监控模块。
|
||||
*
|
||||
* @requirement(name="方案驱动分发与状态响应", id="SRS-F-06-001")
|
||||
* @requirement(name="驱动状态监控与异常信息展示", id="SRS-F-06-002")
|
||||
*/
|
||||
void test_distribution_monitor() {
|
||||
std::cout << "[测试] DistributionMonitor ... ";
|
||||
|
||||
DistributionMonitor mon;
|
||||
|
||||
// SRS-F-06-001: 分发方案
|
||||
DistributionLog dlog = mon.distributePlan("PLAN-001", "无人机");
|
||||
assert(dlog.log_id > 0);
|
||||
assert(dlog.plan_id == "PLAN-001");
|
||||
assert(dlog.asset_type == "无人机");
|
||||
|
||||
// 接收 ACK
|
||||
mon.receiveAck(dlog.log_id, "ACK");
|
||||
auto logs = mon.getDistributionLogs();
|
||||
assert(!logs.empty());
|
||||
assert(logs.back().ack_code == "ACK");
|
||||
|
||||
// SRS-F-06-002: 接收正常遥测
|
||||
StatusLog slog = mon.receiveTelemetry("正常数据包", "数据链-01");
|
||||
assert(slog.status_code == "OK");
|
||||
|
||||
// SRS-F-06-002: 接收异常遥测(应触发报警)
|
||||
StatusLog errLog = mon.receiveTelemetry("ERROR: 传感器故障", "数据链-02");
|
||||
assert(errLog.status_code != "OK");
|
||||
|
||||
// 报警触发
|
||||
bool alarm = mon.triggerAlarm("ERROR_01");
|
||||
assert(alarm == true);
|
||||
// "OK" 不应触发报警
|
||||
bool noAlarm = mon.triggerAlarm("OK");
|
||||
assert(noAlarm == false);
|
||||
|
||||
std::cout << "通过\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 主测试入口。
|
||||
*/
|
||||
int main() {
|
||||
std::cout << "=== TPS 核心模块单元测试 ===\n\n";
|
||||
|
||||
test_event_handler();
|
||||
test_template_manager();
|
||||
test_plan_manager();
|
||||
test_distribution_monitor();
|
||||
|
||||
std::cout << "\n所有测试通过!\n";
|
||||
return 0;
|
||||
}
|
||||
Loading…
Reference in New Issue