Files
RCS-3000/src/dispatch/graph_map.cpp
2026-01-09 15:01:58 +08:00

354 lines
11 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "graph_map.h"
#include <algorithm>
#include <cmath>
#include <queue>
// A*路径规划实现简化版不考虑其他AGV
std::vector<Path*> GraphMap::findPath(Point* start, Point* end, const std::vector<AGV*>& avoid_agvs) {
if (start == end) {
return {};
}
// 注意avoid_agvs参数保留以保持接口兼容性但不再使用
// 路径规划专注于找到理论最优路径,避让由资源管理器处理
// A*算法
struct Node {
Point* point;
Path* path_from_parent; // 到达这个点的路径
double g_score; // 从起点到当前点的实际代价
double f_score; // g_score + 启发式代价
Node(Point* p, Path* path, double g, double f)
: point(p), path_from_parent(path), g_score(g), f_score(f) {}
bool operator<(const Node& other) const {
return f_score > other.f_score; // 最小堆
}
};
std::priority_queue<Node> open_set;
std::unordered_map<Point*, Path*> came_from;
std::unordered_map<Point*, double> g_score;
// 初始化起点
open_set.emplace(start, nullptr, 0, start->distanceTo(*end));
g_score[start] = 0;
while (!open_set.empty()) {
Node current = open_set.top();
open_set.pop();
// 到达终点
if (current.point == end) {
std::vector<Path*> path_list;
Point* curr = end;
// 回溯构建路径
while (curr != start && came_from.find(curr) != came_from.end()) {
Path* path = came_from[curr];
path_list.insert(path_list.begin(), path);
curr = path->start == curr ? path->end : path->start;
}
return path_list;
}
// 探索相邻路径
const std::vector<Path*>& adj_paths = getAdjacentPaths(current.point);
for (Path* path : adj_paths) {
// 简化版:不再检查路径占用,由资源管理器处理
// 获取相邻节点
Point* neighbor = path->getOtherEnd(current.point);
if (!neighbor) {
continue;
}
// 计算代价
double tentative_g = current.g_score + path->length;
// 如果这是更好的路径或者首次访问
if (g_score.find(neighbor) == g_score.end() || tentative_g < g_score[neighbor]) {
came_from[neighbor] = path;
g_score[neighbor] = tentative_g;
// 计算启发式代价(到终点的直线距离)
double f_score = tentative_g + neighbor->distanceTo(*end);
open_set.emplace(neighbor, path, tentative_g, f_score);
}
}
}
// 无法找到路径
return {};
}
bool GraphMap::isPathAvailable(Path* path, const AGV* requester) {
std::lock_guard<std::mutex> lock(map_mutex_);
// 如果路径未被占用,则可用
if (!path->isOccupied()) {
return true;
}
// 如果被请求者自己占用,也认为可用(已在路上)
return path->occupied_by == requester;
}
void GraphMap::reservePath(Path* path, AGV* agv) {
std::lock_guard<std::mutex> lock(map_mutex_);
path->occupied_by = agv;
}
void GraphMap::releasePath(Path* path, AGV* agv) {
std::lock_guard<std::mutex> lock(map_mutex_);
if (path->occupied_by == agv) {
path->occupied_by = nullptr;
}
}
// K最短路径实现 (简化版Yen's算法变体)
std::vector<std::vector<Path*>> GraphMap::findKShortestPaths(
Point* start,
Point* end,
int K,
const std::vector<AGV*>& avoid_agvs
) {
std::vector<std::vector<Path*>> results;
if (K <= 0 || start == nullptr || end == nullptr || start == end) {
return results;
}
// 1. 找到最短路径 (使用标准A*)
std::vector<Path*> first_path = findPath(start, end, avoid_agvs);
if (first_path.empty()) {
return results; // 无法找到任何路径
}
results.push_back(first_path);
if (K == 1) {
return results;
}
// 2. 寻找K-1条备选路径 (通过边惩罚方法)
std::unordered_map<Path*, double> edge_penalties;
for (int k = 1; k < K; ++k) {
std::vector<Path*> best_alternative;
double best_cost = 1e9;
// 尝试惩罚前一条路径中的每条边,寻找替代方案
const std::vector<Path*>& prev_path = results[k-1];
// 随机选择一些偏离点来探索不同路径 (简化版)
// 完整Yen's算法会比较慢这里使用贪心偏离策略
for (size_t deviate_idx = 0; deviate_idx < prev_path.size() && deviate_idx < 3; ++deviate_idx) {
Path* banned_path = prev_path[deviate_idx];
// 临时增加这条边的代价
double original_penalty = edge_penalties[banned_path];
edge_penalties[banned_path] += 1000.0; // 大惩罚值
// 使用修改后的代价重新运行A*
std::vector<Path*> alternative = _findPathWithPenalties(start, end, edge_penalties, avoid_agvs);
// 恢复代价
edge_penalties[banned_path] = original_penalty;
if (!alternative.empty()) {
// 计算路径总长度
double total_length = 0.0;
for (Path* p : alternative) {
total_length += p->length;
}
// 检查是否与已有路径重复
bool is_duplicate = false;
for (const auto& existing : results) {
if (_arePathsSame(alternative, existing)) {
is_duplicate = true;
break;
}
}
if (!is_duplicate && total_length < best_cost) {
best_cost = total_length;
best_alternative = alternative;
}
}
}
if (best_alternative.empty()) {
break; // 无法找到更多路径
}
results.push_back(best_alternative);
}
return results;
}
// 带边惩罚的A*算法 (内部辅助函数)
std::vector<Path*> GraphMap::_findPathWithPenalties(
Point* start,
Point* end,
const std::unordered_map<Path*, double>& penalties,
const std::vector<AGV*>& avoid_agvs
) {
if (start == end) {
return {};
}
struct Node {
Point* point;
Path* path_from_parent;
double g_score;
double f_score;
Node(Point* p, Path* path, double g, double f)
: point(p), path_from_parent(path), g_score(g), f_score(f) {}
bool operator<(const Node& other) const {
return f_score > other.f_score;
}
};
std::priority_queue<Node> open_set;
std::unordered_map<Point*, Path*> came_from;
std::unordered_map<Point*, double> g_score;
open_set.emplace(start, nullptr, 0, start->distanceTo(*end));
g_score[start] = 0;
while (!open_set.empty()) {
Node current = open_set.top();
open_set.pop();
if (current.point == end) {
std::vector<Path*> path_list;
Point* curr = end;
while (curr != start && came_from.find(curr) != came_from.end()) {
Path* path = came_from[curr];
path_list.insert(path_list.begin(), path);
curr = path->start == curr ? path->end : path->start;
}
return path_list;
}
const std::vector<Path*>& adj_paths = getAdjacentPaths(current.point);
for (Path* path : adj_paths) {
Point* neighbor = path->getOtherEnd(current.point);
if (!neighbor) {
continue;
}
// 计算带惩罚的代价
double penalty = 0.0;
auto it = penalties.find(path);
if (it != penalties.end()) {
penalty = it->second;
}
double tentative_g = current.g_score + path->length + penalty;
if (g_score.find(neighbor) == g_score.end() || tentative_g < g_score[neighbor]) {
came_from[neighbor] = path;
g_score[neighbor] = tentative_g;
double f_score = tentative_g + neighbor->distanceTo(*end);
open_set.emplace(neighbor, path, tentative_g, f_score);
}
}
}
return {};
}
// 检查两条路径是否相同 (内部辅助函数)
bool GraphMap::_arePathsSame(const std::vector<Path*>& path1, const std::vector<Path*>& path2) {
if (path1.size() != path2.size()) {
return false;
}
for (size_t i = 0; i < path1.size(); ++i) {
if (path1[i] != path2[i]) {
return false;
}
}
return true;
}
// 计算路径特征
GraphMap::PathFeatures GraphMap::calculatePathFeatures(const std::vector<Path*>& path) {
PathFeatures features;
if (path.empty()) {
features.length = 0.0;
features.conflicts = 0;
features.avg_speed = 0.0;
features.smoothness = 0.0;
return features;
}
// 计算总长度和平均速度
double total_length = 0.0;
double total_speed = 0.0;
int conflicts = 0;
for (Path* p : path) {
total_length += p->length;
total_speed += p->max_speed;
if (p->isOccupied()) {
conflicts++;
}
}
features.length = total_length;
features.avg_speed = path.empty() ? 0.0 : total_speed / path.size();
features.conflicts = conflicts;
// 计算平滑度 (基于角度变化)
double curvature_changes = 0.0;
for (size_t i = 1; i < path.size() - 1; ++i) {
// 计算三个连续点形成的角度
Point* p1 = path[i-1]->start == path[i]->start ? path[i-1]->end : path[i-1]->start;
Point* p2 = path[i]->start;
Point* p3 = path[i+1]->end == path[i]->end ? path[i+1]->start : path[i+1]->end;
if (p1 && p2 && p3) {
// 计算向量
double v1x = p2->x - p1->x;
double v1y = p2->y - p1->y;
double v2x = p3->x - p2->x;
double v2y = p3->y - p2->y;
// 归一化
double norm1 = std::sqrt(v1x * v1x + v1y * v1y);
double norm2 = std::sqrt(v2x * v2x + v2y * v2y);
if (norm1 > 1e-6 && norm2 > 1e-6) {
v1x /= norm1;
v1y /= norm1;
v2x /= norm2;
v2y /= norm2;
// 点积
double dot = v1x * v2x + v1y * v2y;
dot = std::max(-1.0, std::min(1.0, dot)); // 裁剪到[-1, 1]
// 角度
double angle = std::acos(dot);
curvature_changes += angle;
}
}
}
features.smoothness = 1.0 / (1.0 + curvature_changes);
return features;
}