在原稿基础上添加部分:之前发这篇博客时只是粗略看了代码,并没有深入细究。经过这几天的开发,发现QualNet自带的移动模型,不论是随机路径点、组移动、文件设置路径点,都是在初始化阶段就已经把所有要经过的路径点和到达时刻计算好,存入目的地列表,然后在仿真中,根据相应时刻的到达,将节点移动到相应位置。在仿真过程中,无法添加新的路径点,即无法随心所欲地在中途修正节点的移动参数。 解决办法是,初始化设定节点都不移动,即不调用任何移动模型,然后在仿真过程中,如果需要移动节点时,自己设定目的地和到达时刻,把移动函数的代码复制过来,就可以实现。不需要插入目的地列表,也不需要从列表中取出目的地,当场设定、当场移动。
1 初始化节点位置
struct NodePositions {
NodeAddress nodeId;
int partitionId;
NodePlacementType nodePlacementType;
MobilityData* mobilityData;
};
节点位置数据结构包含节点id、节点所在分区id、节点放置类型、节点移动数据。在main函数中调用 MOBILITY_AllocateNodePositions()函数分配节点位置内存,读取用户配置文件,设置每个节点放置类型,再调用MOBILITY_PreInitialize()函数预先初始化移动数据。
void MOBILITY_AllocateNodePositions(
numNodes,
nodeIdArray,
&nodePositions,
&nodePlacementTypeCounts,
&nodeInput,
seedVal);
{
NodePositions* nodePositions =
(NodePositions*)MEM_malloc(sizeof(NodePositions) * numNodes);
int* nodePlacementTypeCounts =
(int*)MEM_malloc(sizeof(int) * NUM_NODE_PLACEMENT_TYPES);
for (i = 0; i < NUM_NODE_PLACEMENT_TYPES; i++) {
nodePlacementTypeCounts[i] = 0;
}
for (i = 0; i < numNodes; i++)
{
nodePositions[i].nodeId = nodeIdArray[i];
nodePositions[i].partitionId = 0;
//设置节点放置类型
IO_ReadString(
nodeIdArray[i],
ANY_ADDRESS,
nodeInput,
"NODE-PLACEMENT",
&wasFound,
buf);
if (strcmp(buf, "RANDOM") == 0) {
nodePositions[i].nodePlacementType = RANDOM_PLACEMENT;
nodePlacementTypeCounts[RANDOM_PLACEMENT]++;
}
else if (strcmp(buf, "UNIFORM") == 0) {
nodePositions[i].nodePlacementType = UNIFORM_PLACEMENT;
nodePlacementTypeCounts[UNIFORM_PLACEMENT]++;
}
else if (strcmp(buf, "GRID") == 0) {
nodePositions[i].nodePlacementType = GRID_PLACEMENT;
nodePlacementTypeCounts[GRID_PLACEMENT]++;
}
else if (strcmp(buf, "FILE") == 0) {
nodePositions[i].nodePlacementType = FILE_BASED_PLACEMENT;
nodePlacementTypeCounts[FILE_BASED_PLACEMENT]++;
}
else if (strcmp(buf, "GROUP") == 0) {
nodePositions[i].nodePlacementType = GROUP_PLACEMENT;
nodePlacementTypeCounts[GROUP_PLACEMENT]++;
}
else if (strcmp(buf, "EXTERNAL") == 0) {
nodePositions[i].nodePlacementType = EXTERNAL_PLACEMENT;
nodePlacementTypeCounts[EXTERNAL_PLACEMENT]++;
}
else {
char errorMessage[MAX_STRING_LENGTH];
sprintf(errorMessage, "Unknown NODE-PLACEMENT type: %s.\n", buf);
ERROR_ReportError(errorMessage);
}
// 分配内存并初始化节点移动类型
nodePositions[i].mobilityData =
(MobilityData*)MEM_malloc(sizeof(MobilityData));
memset(nodePositions[i].mobilityData, 0, sizeof(MobilityData));
MOBILITY_PreInitialize(
nodeIdArray[i],
nodePositions[i].mobilityData,
nodeInput,
seedVal);
}
}
2 预先初始化节点移动数据
struct MobilityData
{
MobilityType mobilityType;
D_Float32 distanceGranularity;
D_BOOL groundNode;
RandomSeed seed;
//组移动模型相关
RandomSeed groupSeed;
int groupIndex;
Coordinates groupTerrainOrigin;
Coordinates groupTerrainDimensions;
double groupMaxSpeed;
double groupMinSpeed;
double internalMaxSpeed;
double internalMinSpeed;
clocktype internalMobilityPause;
//序列号,未来、当前、过去位置
int sequenceNum;
MobilityElement* next;
MobilityElement* current;
MobilityElement* past[NUM_PAST_MOBILITY_EVENTS];
//目的地数量、目的地列表
int numDests;
MobilityElement* destArray;
MobilityRemainder remainder;
void *mobilityVar;
};
节点移动数据结构主要包括移动类型、当前过去和未来位置、目的地列表等,组移动时还有组内组件最大最小移动速度等参数。MOBILITY_PreInitialize()函数读取用户配置文件,设置节点移动类型等参数,初始化节点当前过去和未来位置。
void MOBILITY_PreInitialize(
NodeAddress nodeId,
MobilityData* mobilityData,
NodeInput* nodeInput,
int seedVal)
{
// 设置节点移动类型.
IO_ReadString(