目录
0 前言
利用VTD作为虚拟仿真软件,并对场景中的信号灯数据进行解析提取。
关于场景的搭建可参照官方的ScenarioEditorRevM.pdf文档,本文建立在场景已搭建成功的基础上。
1 RDB总线介绍
VTD将所有的数据分类别存储至自定义的结构体中,并在RDB总线上进行传输。当要取出某种数据时,则需要连接RDB总线,对其上的数据流进行筛选,筛选出我们所需要的结构体数据,而后再进行进一步的解析。
RDB总线通过tcp连接。成功安装VTD后,在 /Develop /Communication /RDBClientSample/ 目录下找到ExampleConsole.cpp,是官方所给的RDB总线解析的源码示例。
连接RDB总线以及提取数据流的功能已经写好了,我们需要做的就是在parseRDBMessageEntry函数中筛选出我们所需要的数据所在的结构体,而后再做进一步的解析,如下所示:
void parseRDBMessageEntry( const double & simTime, const unsigned int & simFrame, RDB_MSG_ENTRY_HDR_t* entryHdr )
{
if ( !entryHdr )
return;
int noElements = entryHdr->elementSize ? ( entryHdr->dataSize / entryHdr->elementSize ) : 0;
if ( !noElements ) // some elements require special treatment
{
switch ( entryHdr->pkgId )
{
case RDB_PKG_ID_START_OF_FRAME:
fprintf( stderr, "void parseRDBMessageEntry: got start of frame\n" );
break;
case RDB_PKG_ID_END_OF_FRAME:
fprintf( stderr, "void parseRDBMessageEntry: got end of frame\n" );
break;
default:
return;
break;
}
return;
}
unsigned char ident = 6;
char* dataPtr = ( char* ) entryHdr;
dataPtr += entryHdr->headerSize;
while ( noElements-- )
{
bool printedMsg = true;
switch ( entryHdr->pkgId )
{
case RDB_PKG_ID_OBJECT_STATE:
handleRDBitem( simTime, simFrame, *( ( RDB_OBJECT_STATE_t* ) dataPtr ), entryHdr->flags & RDB_PKG_FLAG_EXTENDED );
break;
case RDB_PKG_ID_TRAFFIC_LIGHT:
handleTrafficLight(simTime, simFrame, *( ( RDB_TRAFFIC_LIGHT_t* ) dataPtr ), entryHdr->flags & RDB_PKG_FLAG_EXTENDED);
break;
default:
printedMsg = false;
break;
}
dataPtr += entryHdr->elementSize;
}
}
当要提取信号灯数据时,只需要在switch case中添加信号灯结构体对应PKG_ID的判断,并触发自己的自定义处理函数。
关于结构体以及相应的PKG_ID定义,可通过打开/Doc/RDB_HTML/下的annotated.html进行HTML导引查看,如下所示:
在html中可以很直观的通过结构体名找到自己所要提取的数据所在结构体,继而按照结构体定义自定义解析函数,而后在上述parseRDBMessageEntry中添加相应PKG_ID的case判断,并触发自定义的解析函数。
2 TrafficLight结构体解读
2.1 RDB_TRAFFIC_LIGHT_t
关于信号灯的数据均在RDB_TRAFFIC_LIGHT_t中,该结构体也是我们进行数据解析的入口,其共有两个成员变量:base和ext。其中base是信号灯的基础信息(详细定义见2.1);ext为信号灯的一些扩展信息(详细定义见2.2)。
2.2 RDB_TRAFFIC_LIGHT_BASE_t
—— information about a traffic light (state) ——
int32_t | id | unique ID of the traffic light |
float | state | current state (normalized) |
uint32_t | stateMask | current state mask (light mask, e.g. for gfx) |
如上所示为RDB_TRAFFIC_LIGHT_BASE_t 结构体的定义,其中:
- id为当前信号灯的id;
- state为当前信号灯处于一段循环周期(如绿-黄-红循环变换)中的哪一阶段,简单地说,就是处于当前信号灯循环周期内的哪一时间点,其大小为0.0…1.0,可用于判断当前灯光的剩余时间;
- stateMask为当前信号灯的灯光状态,0x100000为绿灯,0x1000000为黄灯,0x10000000为红灯。
2.3 RDB_TRAFFIC_LIGHT_EXT_t
—— extended information about a traffic light (phases, state details) ——
int32_t | ctrlId | ID of the traffic light’s controller |
float | cycleTime | duration of a complete cycle of all phases |
uint16_t | noPhases | number of phases provided by this traffic light |
uint32_t | dataSize | total size of phase data following the package |
this package is followed immediately by “dataSize” bytes of data, containing “noPhases” phase information entries RDB_TRAFFIC_LIGHT_PHASE_t
如上所示为RDB_TRAFFIC_LIGHT_EXT_t结构体的定义,其中:
- ctrId为当前信号灯的控制id,信号灯所能变换的灯光便在controller里进行定义,如:红灯-stop等,未定义的灯光不会出现在信号灯的变换次序中;
- cycleTime为当前信号灯的循环周期时间,如13s,则当前信号灯完整变换所有定义的灯光共需13s,每隔13s进行重复变换;
- noPhases为当前信号灯所拥有的相位数(灯光数),若只有红绿黄灯,则其值为3;
- dataSize为该结构体后面所拥有的额外的字节数,即phase数组,其数据用来详细指示当前信号灯所拥有的灯光状态、各自的持续时间以及灯光变换顺序(ps: phase数组的顺序仅表征controller中所定义灯光的先后顺序,与灯光如何变换无关),在对其进行解析时,需要将RDB_TRAFFIC_LIGHT_t后面的数据地址给到RDB_TRAFFIC_LIGHT_PHASE_t指针,这样便可以按照RDB_TRAFFIC_LIGHT_PHASE_t结构体的定义来解析后续的数据。
2.4 RDB_TRAFFIC_LIGHT_PHASE_t
—— traffic light phase information entry ——
获取信号灯各相位的持续时间(红绿黄灯各自的持续时间)
float | duration | normalized duration of the phase, invalid phases will have duration 0.0 |
uint8_t | type | type of the phase RDB_TRLIGHT_PHASE |
uint8_t | spare [3] | spares for future use |
0 | RDB_TRLIGHT_PHASE_OFF | PHASE OFF |
1 | RDB_TRLIGHT_PHASE_STOP | PHASE STOP |
2 | RDB_TRLIGHT_PHASE_STOP_ATTN | STOP/ATTENTION |
3 | RDB_TRLIGHT_PHASE_GO | GO |
3 | RDB_TRLIGHT_PHASE_GO_EXCL | GO EXCLUSIVELY |
5 | RDB_TRLIGHT_PHASE_ATTN | ATTENTION |
6 | RDB_TRLIGHT_PHASE_BLINK | BLINK |
7 | RDB_TRLIGHT_PHASE_UNKNOWN | UNKNOWN |
如上所示为RDB_TRAFFIC_LIGHT_PHASE_t结构体的定义,注意这里的数据都是静态数据,即仅是用来指示说明而用,并不会随着灯光的变化而变化。其中:
- duration为当前灯光的持续时间,大小为0.0…1.0,与上面base.
- state的定义类似,为当前信号灯循环周期的占比,如0.3,则当前灯光持续时间占循环周期时间的1/3;
- type为当前的灯光种类,关于type的定义见下图;
- spare用于未来扩充使用。
3 总结
以上便是VTD中信号灯数据的提取及解析,由此可知,若想判断当前信号灯的状态以及所剩时间需要结合当前信号灯的状态state、信号灯各相位的持续时间duration、信号灯所有相位的循环周期cycletime以及各相位的变换顺序,其中除变换顺序外的数据,都可以直接从RDB总线中取得,但是变换顺序却无法直接获取,这里只能在场景定义时就将其严格按照标准灯光变换顺序来定义,如此对数据进行一定的处理转换后,便可用于填充CSAE SPAT消息集,后续再写如何用拿到的数据填充SPAT。