毕业设计思路篇(二)之交通灯的初始化
灯如果不和「实际能走的几条路」对上号,仿真里就会出现明明没车挡路却永远红灯的鬼畜场面。
思路篇(一) 把 CrossRoad 和 JunctionRoad 建好之后,每个路口上已经挂了一个 TrafficLight m_CTrafficLight_Light,但里面的 roadID、type、status 都还是空的。这篇专门讲启动仿真前怎么遍历整张图,按路口岔路数量设灯型,并把各方向的入路、出路 id 填进 roadID[8]。后面 思路篇(五) 里车辆到路口会调 clock 和 getStatus(from, to),靠的就是这里对齐好的映射。
道路类型的设置
路口有几条「方向道路节点」,就大致能判断是 T 字还是十字路口(3 条 vs 4 条及以上)。类型影响相位切换表,所以先扫一遍图:
it->m_CTrafficLight_Light.setType(it->JunctionRoad.size());
根据路口道路条数,设置路灯类型(是 T 字路口还是 + 字路口)
setType 本身只存一个整数,真正的相位逻辑在 changeStatus、clock 里根据 type 分支。TrafficLight 类里还预留了 status[4][4] 表示方向间是否可通行,以及 emStatus 枚举当前是全红、某向绿灯等状态。
/**
* 交通灯类
*/
class TrafficLight {
public:
TrafficLight() {
for (int i = 0; i < 8; i++) {
roadID[i] = -1;
}
};
void changeStatus();
void clock(int time);
void setAllRed();
void setAllGreen();
bool getStatus(int from, int to);
/**
* 设置灯的类型, 是T字路口还是+字路口
* @param type
*/
void setType(int type) { this->type = type; };
//路口标号
// nLeftIn,nLeftOut,nDownIn,nDownOut,nRightIn,nRightOut,nUpIn,nUpOut;
int roadID[8];
//路口是否能走通
bool status[4][4] = {false};
int type;
//表示可通过的方向(目标方向)
//AllRED = 0,LeftGreen = 1,DownGreen = 2,RightGreen = 3,UpGreen = 4,UpDownGreen = 5,LeftRightGreen = 6,cross1 = 7,cross2 = 8
int emStatus = 0;
long long int time = 0;
};
构造函数里把 roadID 全置 -1,避免未赋值的道路 id 被当成 0 号路。getStatus(int from, int to) 的参数就是当前所在道路 id 和下一条要进入的道路 id,仿真循环里正好有这两个数。
对接各路口
JunctionRoad 的下标和东南西北不是写死的,而是按 思路篇(一) 里 addNode 插入顺序来的。初始化时要按约定把 JunctionRoad[k].inID/outID 拷进 roadID 固定槽位:注释里的 nLeftIn, nLeftOut, … nUpOut 共八个位置,对应四个方向的进出。
it->m_CTrafficLight_Light.roadID[4] = it->JunctionRoad[0].inID;
it->m_CTrafficLight_Light.roadID[5] = it->JunctionRoad[0].outID;
it->m_CTrafficLight_Light.roadID[0] = it->JunctionRoad[1].inID;
it->m_CTrafficLight_Light.roadID[1] = it->JunctionRoad[1].outID;
switch (it->JunctionRoad.size()) {
case 4:
it->m_CTrafficLight_Light.roadID[6] = it->JunctionRoad[3].inID;
it->m_CTrafficLight_Light.roadID[7] = it->JunctionRoad[3].outID;
//你是不是想说没有break?这里不需要break;
case 3:
it->m_CTrafficLight_Light.roadID[2] = it->JunctionRoad[2].inID;
it->m_CTrafficLight_Light.roadID[3] = it->JunctionRoad[2].outID;
}
这段 switch 故意不写 break:十字路口(size == 4)要先填 roadID[6/7](第四组方向),再落入 case 3 填 roadID[2/3];T 字路口只有 3 条岔路,直接进 case 3 即可。当时写的时候被同学质疑过,解释一遍就懂了——不是漏写,是复用同一段赋值。
对接顺序和 JunctionRoad[0..3] 在构图时怎么 addNode 强相关。如果 XML 导入顺序变了,这里可能要一起改,否则灯控的方向和真实边会对不上。我调试时曾在某个路口把 from/to 搞反,表现就是车永远等红灯,查了半天才发现是 roadID 槽位填错,不是 getStatus 算法本身的问题。
交通灯初始化完毕。下一步可以 预加载车辆路线,或者先跑 番外篇 生成 route.txt——取决于你手边有没有现成的路径文件。
版权声明: 本文首发于 指尖魔法屋-毕业设计思路篇(二)之交通灯的初始化(https://blog.thinkmoon.cn/post/121-graduation-design-traffic-notes-cplusplus/) 转载或引用必须申明原指尖魔法屋来源及源地址!