毕业设计思路篇(二)之交通灯的初始化

灯如果不和「实际能走的几条路」对上号,仿真里就会出现明明没车挡路却永远红灯的鬼畜场面。

思路篇(一)CrossRoadJunctionRoad 建好之后,每个路口上已经挂了一个 TrafficLight m_CTrafficLight_Light,但里面的 roadIDtypestatus 都还是空的。这篇专门讲启动仿真前怎么遍历整张图,按路口岔路数量设灯型,并把各方向的入路、出路 id 填进 roadID[8]。后面 思路篇(五) 里车辆到路口会调 clockgetStatus(from, to),靠的就是这里对齐好的映射。

道路类型的设置

路口有几条「方向道路节点」,就大致能判断是 T 字还是十字路口(3 条 vs 4 条及以上)。类型影响相位切换表,所以先扫一遍图:


it->m_CTrafficLight_Light.setType(it->JunctionRoad.size());

根据路口道路条数,设置路灯类型(是 T 字路口还是 + 字路口)

setType 本身只存一个整数,真正的相位逻辑在 changeStatusclock 里根据 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 3roadID[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/) 转载或引用必须申明原指尖魔法屋来源及源地址!