State_solve

本函数功能:对装甲板的4个状态进行处理(TRACKING,DETECTING,LOSING,MISSING)

ArmorTrack::State_solve(bool match) {
    /** DETECTING TRACKING状态的过渡 */
    if (tracker_state == DETECTING) {
        // DETECTING
        if (match) {                                // 匹配次数到达阈值则开始跟踪
            find_aim_number++;                      // 锁定目标次数++
            if (find_aim_number > find_threshold) {
                find_aim_number = 0;                // 清零
                tracker_state = TRACKING;           // 设置为跟踪状态
            }
        } else {  //没有目标,跳过该部分
            find_aim_number = 0;                    // 清零
            tracker_state = MISSING;                // 将状态重置为没有目标状态
        }
    }
    /** TRACKING 跟踪状态 */
    else if (tracker_state == TRACKING) {
        // TRACKING
        if (!match) {                               // 未匹配则丢失
            tracker_state = LOSING;                 // 丢失状态
            lost_aim_number++;                      // 丢失目标次数++
        }
    }
    /** LOSING 丢失状态 */
    else if (tracker_state == LOSING) {
        if (!match) {                             // 未匹配则累加丢失次数
            lost_aim_number++;
            if (lost_aim_number > lost_threshold) { // 超过丢失阈值,将跟踪器设置未没有目标
                lost_aim_number = 0;
                tracker_state = MISSING;            // 将状态重置为没有目标状态
            }
        } else {
            tracker_state = TRACKING;               // 匹配到目标则设置回跟踪状态
            lost_aim_number = 0;                    // 丢失次数清零
        }
    }
}

在这个函数里面,我们实现对状态的转换,这里就不得不引入一下 "状态机" 的概念和设计理念了

首先先解释什么是“状态”( State ):

现实事物是有不同状态的,例如一个自动门,就有 open 和 closed 两种状态。我们通常所说的状态机是有限状态机,也就是被描述的事物的状态的数量是有限个,例如自动门的状态就是两个 open 和 closed ,如图:


状态机,也就是 State Machine ,不是指一台实际机器,而是指一个数学模型

状态机是有限状态自动机的简称,是现实事物运行规则抽象而成的一个数学模型

下面是状态机的四大概念:

第一个是 State ,状态。一个状态机至少要包含两个状态。例如上面自动门的例子,有 open 和 closed 两个状态。
第二个是 Event ,事件。事件就是执行某个操作的触发条件或者口令。对于自动门,“按下开门按钮”就是一个事件。
第三个是 Action ,动作。事件发生以后要执行动作。例如事件是“按开门按钮”,动作是“开门”。编程的时候,一个 Action一般就对应一个函数。
第四个是 Transition ,变换。也就是从一个状态变化为另一个状态。例如“开门过程”就是一个变换。

简单的来说就是,每一个状态有对应的执行函数和逻辑,根据条件判断是否要进行状态切换

这样做的好处是逻辑清晰,可以专注于当前状态层的实现,最后只需要写好状态的切换便可以将各个状态连接在一起,可以有效减少代码的耦合性


本函数的判断逻辑非常简单,需要特别注意的是 DETECTING 状态,这是一个比较特殊的状态

/** 跟踪状态 */
enum TrackerState {
    MISSING,            // 没有目标,跳过该部分
    DETECTING,          // 还未开始跟踪,作为跟踪第一帧的切换,初始化好卡尔曼
    LOSING,             // 处于丢失状态,还会保留预测
    TRACKING,           // 处于跟踪状态
};

如果当前图片中有在 Initial() 中已经锁定了的装甲板ID,那么match便是True,视为当前帧锁定成功

这个时候 find_aim_number++ 进行自增,当达到了设置的阈值 find_threshold 时候便会切换状态进入 TRACKING

    /** DETECTING TRACKING状态的过渡 */
    if (tracker_state == DETECTING) {
        // DETECTING
        if (match) {                                // 匹配次数到达阈值则开始跟踪
            find_aim_number++;                      // 锁定目标次数++
            if (find_aim_number > find_threshold) {
                find_aim_number = 0;                // 清零
                tracker_state = TRACKING;           // 设置为跟踪状态
            }
        } else {  //没有目标,跳过该部分
            find_aim_number = 0;                    // 清零
            tracker_state = MISSING;                // 将状态重置为没有目标状态
        }
    }

TRACKING 状态的逻辑也简单,如果当前帧没能识别到锁定的ID (假设是1),就会进入 LOSING 状态,同时 lost_aim_number 自增

    /** TRACKING 跟踪状态 */
    else if (tracker_state == TRACKING) {
        // TRACKING
        if (!match) {                               // 未匹配则丢失
            tracker_state = LOSING;                 // 丢失状态
            lost_aim_number++;                      // 丢失目标次数++
        }
    }

接下来便看 LOSING 状态

    /** LOSING 丢失状态 */
    else if (tracker_state == LOSING) {
        if (!match) {                             // 未匹配则累加丢失次数
            lost_aim_number++;
            if (lost_aim_number > lost_threshold) { // 超过丢失阈值,将跟踪器设置未没有目标
                lost_aim_number = 0;
                tracker_state = MISSING;            // 将状态重置为没有目标状态
            }
        } else {
            tracker_state = TRACKING;               // 匹配到目标则设置回跟踪状态
            lost_aim_number = 0;                    // 丢失次数清零
        }
    }

进入了LOSING 状态,并且持续了 lost_threshold 次,也就是持续了一段时间都未能找到之前锁定的ID(1),就会进入MISSING状态

在 MISSING 状态下,所有的东西都就重置,包括锁定的装甲板ID,这个时候就会重复一次所有的流程,在 Initial() 里面重新锁定一个装甲板ID

如果在此期间又出现锁定的装甲板ID,便会重新回到 TRACKING 状态,并将 lost_aim_number 清空


上面就是整个状态切换的流程图

results matching ""

    No results matching ""