Veins Module 浅析2 -- connectionManager 作用与实现
1. Gates and Connections
在官方文档 4.6 节 Accessing Gates and Connections 有对 gates 的具体介绍,在这里简单摘录下比较关键的。
Omnet 中使用 cGate 来表示模块的 gates,如下是一些常用的调用函数
1 | cGate *outGate = gate("out"); // 提取名为 “out” 对应的 gate 的 interface |
2. connectionManager 基础结构
目录位于 veins/base/connectionManager
文件夹下
2.1 nicGrid
: 保存所有连接
我们从最核心的部分开始看,BaseConnectionManager.h 文件夹中 nicGrid
变量,它承载了所有的连接,其定义如下
1 | /** @brief Type for 1-dimensional array of NicEntries.*/ |
nicGrid
由 NicEntries 变量作为基类型组成的三维的 Vector,可以定义三维空间中任意的物体连接,在 BaseConnectionManager 中大多数的成员函数都是基于它来展开的,如 getCellEntries
。
而连接的对象统一用 NicEntry 作为接口,也就是说如果想要使用 connectionManager 来进行管理,就必须包含 NicEntry 这个接口模块。在展开说 NicEntry 的组成之前,先来看下 Veins 是如何把要连接的 NicEntry 对象接入到 nicGrid 中来的,这要从车辆的位置移动状态变化开始说起。
Veins 中 BaseMobility 模块联系着 Sumo 与 Omnet,通过 TraCI 来获取车辆位置更新数据。其内部包含信号 mobilityStateChangedSignal,用来广播车辆位置的变动。如下所示
1 | /** @brief Store the category of HostMove */ |
而其他需要获取位置变动的模块则 subscribe 这个信号,通过回调函数得知其变动
1 | // ChannelAccess |
跟踪这个订阅可以发现其位于 ChannelAccess 模块的 receiveSignal 函数中
1 | void ChannelAccess::receiveSignal(cComponent* source, simsignal_t signalID, cObject* obj, cObject* details) |
ChannelAccess
则是 BasePhyLayer 的父类,每个调用该栈的模块都会包含它,变量 cc
则是 BaseConnectionManager 功能指针,即所以需要建立连接的模块都会包含此,在 ChannelAccess
的初始化中可以看到其声明
1 | // void ChannelAccess::initialize(int stage) |
利用 BaseConnectionManager 指针便可以实现将当前模块注册到 nicGrid 中进行管理(BaseConnectionManager::updateNicPos
)或者更新位置数据(BaseConnectionManager::registerNic
)。
最后可以看到在registerNicExt
函数中将其加入了 nicGrid
1 | void BaseConnectionManager::registerNicExt(int nicID) |
2.2 GridCoord
: 如何判断两个物体是否在一个位置上
GridCoord 的作用是将原本浮点数的坐标转为整形,乍一看损失了很多精度,但这个过程是很有必要的,简言之就是避免因为过高精度导致物体重叠情况发生。举个例子,假如使用浮点数来表示位置,第一次物体出现在(0.000001, 0.00) 位置,第二次则出现在(0.000501,0.01)位置。这里不是很严谨(一般小数点6位是不会因为浮点数表达发生变化的)但能够简单说明问题,那就是这里其实是同一个位置,只是因为浮点数在传递或者存储或者转换等一系列过程中可能会出现变化,导致位置的判断出现问题。
在 Veins ConnectionManager 中所有位置的表示都是通过 GridCoord 来查询和表示的,这样规范了数据的表达也避免了可能出现的数值转换问题。
(PS:即使浮点数转换不会存在问题,针对浮点数的统计和判断相比整形很耗时,而且在 Veins 中整形已经可以满足需求了)
3. 建立连接
将其加入 nicGrid
后,并不是说就完成了连接建立过程,对于 Omnet 而言这仅仅只是上层,还没有从 cGate
层面来建立连接,下面就要从 NicEntry
入手,看下加入 nicGrid 是如何建立连接的,以及后面解除连接是什么样的。先来看如何将其 register(建立 Omnetpp 层面的连接),然后说下如何 updatePos
,这里就需要提到 NicEntryDebug
和 NicEntryDirect
类了,其共同的基类为 NicEntry
。
3.1 如何只与一定范围内的节点建立连接
现实世界的通信一定要有范围,在 Veins 中定义 maxInterfDist
来限制通信的范围,下面来看下这个变量是如何用的。
最主要的函数是 BaseConnectionManager 中的 isInRange
,其在
1 | /** |
3.2 sendDirct
含义
3.3 如何在 Omnet 层面动态建立连接
NicEntry 提供了几个接口函数供后续子类根据需要派生
1 | /** @brief Connect two nics */ |