虚拟驾驶环境搭建(四)

龙云尧个人博客,转载请注明出处。

CSDN地址:http://blog.csdn.net/michael753951/article/details/75074051

个人blog地址:http://yaoyl.cn/huan-jing-da-jian-si-2/


障碍物移动的改进

在之前的版本中.我们的障碍物移动和场景移动放在同一个for循环中,虽然减少了代码的操作,但是很容易出现边界问题,程序运行中往往会出现障碍物骤现,或者障碍物还未抵达车前方便突然消失的情况,为了修改这出bug,我将重写这部分代码.

需求分析

无脑写代码的多数结果都是bug不断,并且写完后文就忘记前文.为了提高代码的清晰度和准确性,挺尸帮我们捋清思路,我们先通过写伪代码的方式整理一下我们的程序有哪些需求,以及粗略的实现方式.

需求

障碍物能够从左侧楼栋出现,到达路中央之后,将停留一小段时间(等待车撞上).

对这个过程进行分解分析,我们可以大致得到如下流程:

  • 障碍物出现的时机: 左侧有障碍物 & 距离上次消失已经有10s以上
  • 障碍静止时机: 已经达到路中间, 并且停留时间没有达到2s
  • 障碍物消失诗句时机: 停留2s之后,障碍物消失

伪代码

  • 首先判断障碍物是否已经消失,然后判断左侧是否有障碍物,然后检查消失时间是否已经达到10s,如果满足条件,就更新appear标志, 让障碍物开始移动
  • 开始步进障碍物, 直到达到边界, 此时更新appear_tmp, 更新appear标志, 记录下当前时间
  • 如果当前状态为静止, 并且停留时间还未到达2s,保持pos不变
  • 否则如果停留时间超过2s,就将appear更新为消失, 让障碍物消失, 同时用appear_tmp记录下消失的时间, 方便之后判断障碍物的出现时机

代码实现

 1    // 先获取左侧建筑情况
 2    int left_temp = building_left_flag;
 3    // bdw_appear有3个值, 0表示已经消失, 1表示正在进行移动, 2表示移动到边界,已经静止
 4    if(bdw_appear == 0) {
 5        if(left_temp >> 11 & 0b1 == 1) {
 6            time(&appear);
 7            // 如果距离上次出现已经5s,就更新记录,同时更新flag
 8            if(appear - appear_tmp >= 5){
 9                appear_tmp = appear;
10                bdw_appear = 1;
11            }
12        }
13    }else if(bdw_appear == 1){
14        glBindTexture(GL_TEXTURE_2D, texture[4]);
15        glLoadIdentity();
16        glTranslatef(child_run_len, -1.0f, -7.0f);
17        glCallList(children);
18        if(child_run_len >= -0.5) {
19            //child_run_len = -3.0f;
20            //bdw_appear = false;
21            // 刚移动到边界
22            if(bdw_appear == 1){
23                time(&appear_tmp);
24                child_pos = -7.0f;
25                bdw_appear = 2;
26            }
27            child_run_len = -0.5f;
28        }else{
29            // 小孩的速度恒定
30            child_run_len += 0.1f;
31        }
32    }else{
33        time(&appear);
34        // 如果距离上次出现已经5s,就更新记录,同时更新flag
35        if(appear - appear_tmp >= 2){
36            appear_tmp = appear;
37            child_run_len = -3.0f;
38            bdw_appear = 0;
39        }else{
40            glBindTexture(GL_TEXTURE_2D, texture[4]);
41            glLoadIdentity();
42            // 障碍物的pos还要加上run_len, 这样能够让障碍物在达到路中央静止之后, 和周围物体一起移动,产生向人靠近的感觉
43            glTranslatef(child_run_len, -1.0f, child_pos+run_len);
44            glCallList(children);
45        }
46    }

实现障碍物从两侧随机出现

为了和真实驾驶更加相似,我们不应该让障碍物只从单侧出现,而是因该让其两侧都有可能出现.因此,我们需要在原来的代码上进行进一步的修改.

需求分析

需求

首先我们暂时让不倒翁的出现有两种情况, 情况一, 从左侧出现, 情况二, 从两侧随机出现. 通过按键'c'来控制模式的转换(改变appear_mode的值).

因此, 当我们按下'c'键时, 需要对模式进行转换. 接下来在DrawGLScene中将根据appear_mode的值进行一系列操作. 如果appear_mode为默认的0, 就让障碍物从左侧出现, 如果appear_mode为1, 就让障碍物从两侧出现.

如果障碍物从两侧出现的话, 每次障碍物将要出现的时候, 我们需要用一个flag标志保存障碍物本次出现是从左侧出现还是右侧出现. 在绘制障碍物的时候, 我们将通过这个flag来判断物体是如何运动.

  • 障碍物出现的时机: 本身已经消失, 距离上次消失已经有10s以上, 决定好从哪一侧出现, 并且该侧有楼栋
  • 障碍物移动的时机: 本身已经出现, 根据上一步已经得到的flag判定是向左还是向右, 直到到临界点
  • 障碍物静止的时机: 已经达到路中间,并且停留时间并未超过2s
  • 障碍物消失的时机: 已经静止超过2s

伪代码

  • 首先我们需要在KeyPressed函数中, 添加按键'c'的控制事件, 另其对appear_mode进行修改.
  • 接下来在DrawGLScene中, 我们将对这个appear_mode进行判断. 如果appear_mode为0,就按照之前的代码执行. 如果appear_mode为1, 则进入两侧出现事件.
  • 当appear_mode为1时, 如果当前状态为消失, 如果当前已经消失10s以上, 则随机决定在哪应该出现障碍物, 然后检查该侧是否有楼栋, 如果有楼栋, 则保存裁决位置(左或者右), 同时更新当前状态为移动
  • 当appear_mode为1时, 当前状态为移动时, 根据裁决, 如果裁决决定从左侧出来, 则起点设置为左侧, 同时,不断增加child_run_len,直到到达边界; 如果裁决决定从右侧出来, 则起点设置为1.0f位置, 同时不断减小, 直到到达-0.5f位置停止.
  • 停止时, 将appear_mode设置为2, 记录开始时间, 在原地停留两秒之后, 消失.

代码实现

  1    int left_temp = building_left_flag;
  2    int right_temp = building_right_flag;
  3    if(appear_mode == 0) {
  4        // bdw_appear有3个值, 0表示已经消失, 1表示正在进行移动, 2表示移动到边界,已经静止
  5        if(bdw_appear == 0) {
  6            if(left_temp >> 11 & 0b1 == 1) {
  7                time(&appear);
  8                // 如果距离上次出现已经5s,就更新记录,同时更新flag
  9                if(appear - appear_tmp >= 5) {
 10                    appear_tmp = appear;
 11                    bdw_appear = 1;
 12                    child_run_len = -3.0f;
 13                }
 14            }
 15        } else if(bdw_appear == 1) {
 16            glBindTexture(GL_TEXTURE_2D, texture[4]);
 17            glLoadIdentity();
 18            glTranslatef(child_run_len, -1.0f, -7.0f);
 19            glCallList(children);
 20            if(child_run_len >= -0.5) {
 21                //child_run_len = -3.0f;
 22                //bdw_appear = false;
 23                // 刚移动到边界
 24                if(bdw_appear == 1) {
 25                    time(&appear_tmp);
 26                    child_pos = -7.0f;
 27                    bdw_appear = 2;
 28                }
 29                child_run_len = -0.5f;
 30            } else {
 31                // 小孩的速度恒定
 32                child_run_len += 0.1f;
 33            }
 34        } else {
 35            time(&appear);
 36            // 如果距离上次出现已经5s,就更新记录,同时更新flag
 37            if(appear - appear_tmp >= 2) {
 38                appear_tmp = appear;
 39                child_run_len = -3.0f;
 40                bdw_appear = 0;
 41            } else {
 42                glBindTexture(GL_TEXTURE_2D, texture[4]);
 43                glLoadIdentity();
 44                glTranslatef(child_run_len, -1.0f, child_pos+run_len);
 45                glCallList(children);
 46            }
 47        }
 48    }else if(appear_mode == 1) {
 49        if(bdw_appear == 0) {
 50            time(&appear);
 51            if(appear - appear_tmp >= 5){
 52                // 奇数为左侧, 偶数为右侧
 53                if(rand() & 0b1 == 1) {
 54                    if(left_temp >> 11 & 0b1 == 1) {
 55                        time(&appear);
 56                        appear_tmp = appear;
 57                        bdw_appear = 1;
 58                        left_or_right_flag = 1;
 59                        child_run_len = -3.0f;
 60                    }
 61                }else{
 62                    if(right_temp >> 11 & 0b1 == 1) {
 63                        time(&appear);
 64                        appear_tmp = appear;
 65                        bdw_appear = 1;
 66                        left_or_right_flag = 0;
 67                        child_run_len = 1.0f;
 68                    }
 69                }
 70            }
 71        } else if(bdw_appear == 1) {
 72            if(left_or_right_flag == 1){
 73                glBindTexture(GL_TEXTURE_2D, texture[4]);
 74                glLoadIdentity();
 75                glTranslatef(child_run_len, -1.0f, -7.0f);
 76                glCallList(children);
 77                if(child_run_len >= -0.5) {
 78                    //child_run_len = -3.0f;
 79                    //bdw_appear = false;
 80                    // 刚移动到边界
 81                    if(bdw_appear == 1) {
 82                        time(&appear_tmp);
 83                        child_pos = -7.0f;
 84                        bdw_appear = 2;
 85                    }
 86                    child_run_len = -0.5f;
 87                } else {
 88                    // 小孩的速度恒定
 89                    child_run_len += 0.1f;
 90                }
 91            }else{
 92                glBindTexture(GL_TEXTURE_2D, texture[4]);
 93                glLoadIdentity();
 94                glTranslatef(child_run_len, -1.0f, -7.0f);
 95                glCallList(children);
 96                if(child_run_len <= -0.5f) {
 97                    if(bdw_appear == 1) {
 98                        time(&appear_tmp);
 99                        child_pos = -7.0f;
100                        bdw_appear = 2;
101                    }
102                } else {
103                    child_run_len -= 0.1f;
104                }
105            }
106        } else {
107            time(&appear);
108            // 如果距离上次出现已经5s,就更新记录,同时更新flag
109            if(appear - appear_tmp >= 2) {
110                appear_tmp = appear;
111                child_run_len = -3.0f;
112                bdw_appear = 0;
113            } else {
114                glBindTexture(GL_TEXTURE_2D, texture[4]);
115                glLoadIdentity();
116                glTranslatef(child_run_len, -1.0f, child_pos+run_len);
117                glCallList(children);
118            }
119        }
120    }