| by YoungTimes | No comments

Waymo-自动驾驶长尾问题挑战

尽管Waymo已经在开放道路上积累超过10 Million Miles,Waymo的工程师们仍然发现有层出不穷的新自动驾驶场景待解决。

1、自动驾驶长尾场景举例

场景一:一个骑自行车的人手中拿着一个Stop Sign标识牌。我们不知道它何时会举起标识牌。无人车必须理解这种场景,即使他举起了Stop Sign标识牌,自动驾驶汽车也不应该停下来。

场景二: 迎面而来的车辆上装载的塑料管子撒了一地,自动驾驶汽车必须学会应对这种突发情况,并且避开它们对无人车行驶的影响。

场景三:由于道路施工等因素,路面布满锥桶。无人车必须正确识别这些场景,在布满路面锥桶的场景下实现合[……]

继续阅读

Read More
| by YoungTimes | No comments

Lanelets: 高效的自动驾驶地图表达方式

LaneLets是自动驾驶领域高精度地图的一种高效表达方式,它以彼此相互连接的LaneLets来描述自动驾驶可行驶区域,不仅可以表达车道几何,也可以完整表述车道拓扑,同时可以集成交通规则和人的驾驶习惯。

如上图所示,每个Lanelet由left bound和right bound组成,left/right bound有一系列点序列组成,因此可以以任意精度逼近任意车道形状。

1. 用于Routing的Lanelets Graph

为了能够基于Lanelets进行路径规划,我们可以构建Lanelets邻接图结构。当Lanelets A的左右边界的终点与Lanelets B的左[……]

继续阅读

Read More
| by YoungTimes | No comments

C++11多线程-如何用带参数的类成员函数作为线程启动函数

1、使用非静态类成员函数作为线程启动函数

假设存在如下Task类,它有一个名为execute()的非静态成员函数。

现在我们计划用Task的类的成员函数execute()函数作为线程的启动函数。由于execute()是静态函数,为了调用该函数,我们必须首先实例化一个Task对象。

然后,利用该对象创建线程启动函数。

由此,我们可以得到类的非静态成员函数作为线程启动函数的完整代码:

输出结果如下:

2、使用静态成员函数作为线程启动函数

由于静态函数不依赖于任何类对象,所以我们可以直接将静态成员函数作为线程启动函数,而不必传递对象指针。[……]

继续阅读

Read More
| by YoungTimes | No comments

c++编程之路-decltype关键字

1. decltype关键字的用途是什么

给定变量的名称或者表达式,decltype返回变量或者表达式的类型。如下所示:

2.decltype主要应用场景是模板函数

decltype在实际的开发中主要用于模板函数中,函数的返回值依赖于模板参数类型的情况。如下authAndAccess函数的返回值类型依赖于Container的元素类型。

此处的返回值auto并非类型推导的意思,而是C++ 11中的函数返回类型后置的表达方式,表明函数的返回类型在参数列表之后。函数返回类型后置的优势在于我们可以用函数的参数来指定返回值。

在c++ 14中auto关键字可以独立用[……]

继续阅读

Read More
| by YoungTimes | No comments

C++基础-如何在函数中传递原生数组的长度

1. 原生数组在C/C++中退化问题

在C/C++中数组不会按值传递,它传递第一个元素的指针,下列三个声明是等价的:

void func(int* a);

void func(int a[]);

void func(int a[10]);

对于编译器而言,所有的声明都被视为:

void func(int* a);

数组长度不是参数类型的一部分,函数不知道传递给它的数组的实际长度,当编译器对实参类型进行参数类型检查时,并不检查数组的长度。

2. 如何在函数中传递数组的长度

在很多情况下,我们需要知道数组的长度,怎么实现呢?

2.1 一种[……]

继续阅读

Read More
| by YoungTimes | No comments

为什么说自动驾驶“左转”很难?

想象一下,你驾驶一辆车,正打算从一个十字路口左转:

这条路没有交通信号灯或停车标志——你不仅需要在快速的车流中找到行驶空档,还要确保一旦这样做,右车道的车辆会与你相撞。

这种「无保护左转」(即没有交通信号灯或停车标识引导的左转)有多个形式,稍微不那么复杂的版本是:

当你在红绿灯处时,圆形绿灯(不是绿色箭头)示意让你前进,如果你想向左转,就必须在迎面而来的车流中找到一个空隙。

你可能没有注意到,一个看似简单的「左转」可能会引起一系列的问题。

比如,司机要转入的车道可能已经排起了长龙。

这时,到底该开始转弯还是等车队动起来后再转?或者是确定有空间能转入之后就立刻[……]

继续阅读

Read More
| by YoungTimes | No comments

自动驾驶Mapping-占位栅格图(Occupancy Grid Map)

前面文章《自动驾驶运动规划(Motion Planning)》中提到可以使用占位图(Occupancy Grid Map)表示自动驾驶行驶区域的哪些区域被障碍物(如静止的车辆、路中间的石墩子、树木、路肩等)占用,Motion Planning模块会通过查询占位地图避开这些道路障碍物,避免与它们碰撞,从而达到安全驾驶的目的。

1、占位栅格地图(Occupancy Grid Map)

如上图所示,将车辆行驶道路环境用网格(Cell)切分,并且每个网格(Cell)用二值数值0和1填充,0表示该网格(Cell)被占用,1表示该网格(Cell)没有被占用。

$m^{i} \in \[……]

继续阅读

Read More
| by YoungTimes | No comments

C/C++:如何定义和初始化二维数组

在C/C++中有很多定义数组的方式,在日常的应用中也会高频用到,今天一起看看有哪些定义和初始化二维数组的方式。

1、C/C++语言原始数组的方式

数组是C语言的原住民了,在第一代C语言中就已经出现了,在初学者的C/C++的入门书籍中也有详细的介绍。它对二维数组的定义如下:

col的值必须要指定,row的值可以不提供,而是根据初始化列表推断。

原生二维数组初始化既可以分行赋值,也可以连续赋值。

原生二维数组也支持部分赋值。

2、C++ std::array定义二维数组

C++11后标准库引入了更现代化的数组std::array,std::[……]

继续阅读

Read More
| by YoungTimes | No comments

C++11-右值引用作为函数参数

1、普通函数的右值引用参数

假设以右值引用为参数的普通函数的形式如下:

普通函数的右值引用可以接受哪些形式的实参:

1.1 常量表达式作为实参

形参为数值类型的常量的函数定义如下:

以数值常量为实参调用:

形参为字符串类型的常量的函数定义如下:

以字符串常量为实参调用:

1.2 匿名变量作为参数

形参为字符串类型的常量的函数定义如下:

使用匿名变量作为实参的函数调用如下:

1.3 move()语义

move()函数可以将左值转换为右值。

形参为字符串类型的常量的函数定义如下:

使[……]

继续阅读

Read More
| by YoungTimes | No comments

C++11–使用表驱动(Table-Driven)模式消除冗长的if-else和switch-case语句

在日常的代码编写中经常出现不同数据格式转换的场景,比如给定一个整数,将其与每周的星期名称映射起来,该如何实现呢?

常见的实现途径是通过if-else或者switch-case的方式来实现,如下代码所示:

这样的代码优势是简单,初学者也可以写出这样的代码;代码的问题在于:
1) 代码太长,逻辑重复冗余,复杂度高;
2) 可维护性低,当新增一个流程分支时就要添加一个判断语句。

1、简单的表驱动实现

如何解决写出更加优雅的代码来消除冗长的if-else/switch-case语句,表驱动法(Table-Driven Approach)是一种可选的方法。表驱动的方法是指把数据信[……]

继续阅读

Read More