NS-3 学习之reference-point-group-mobility-examplee.cc 分析

/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2020 Institute for the Wireless Internet of Things, Northeastern University, Boston, MA
 * Copyright (c) 2021 University of Washington: for HierarchicalMobilityModel
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation;
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * Author: Michele Polese <michele.polese@gmail.com>
 * Heavily edited by Tom Henderson (to reuse HierachicalMobilityModel)
 */

/**
 * This example shows how to use the ns3::HierarchicalMobilityModel
 * to construct a Reference Point Group Mobility model (RPGM) model
 * as described in "A survey of mobility models for ad hoc network
 * research" by Tracy Camp, Jeff Boleng, and Vanessa Davies, Wireless
 * Communications and Mobile Computing, 2002: vol. 2, pp. 2483-502.
 * 此示例说明如何使用 ns3::HierarchicalMobilityModel 构建参考点组移动模型 (RPGM) 模型。
 *
 * The HierarchicalMobilityModel is composed of two mobility models;
 * a parent and a child.  The position of the child is expressed
 * in reference to the position of the parent.  For group mobility,
 * each node in the group installs the same parent mobility model
 * and different child mobility models.
 * HierarchicalMobilityModel 由两个移动模型组成; 父移动模型和子移动模型。
 * 子模型的位置是参照父模型的位置来表达的。
 * 对于群组移动,群组中的每个节点安装相同的父移动模型和不同的子移动模型。
 *
 * There is no node associated with the parent (reference) model.
 * Instead, all nodes are associated with a hiearchical mobility model
 * containing both the parent and child models, and the position of
 * the node is the vector sum of these parent and child positions.
 * 没有与父(参考)模型关联的节点。
 * 相反,所有节点都与包含父模型和子模型的分层移动模型相关联,并且节点的位置是这些父子位置的向量和。
 * Jerry:即节点与分层移动模型相关联,不直接与父或者子移动模型关联。而节点的移动方式是有父子两个模型综合作用的结果。
 *
 * Standard ns-3 mobility model course change output is traced in
 * 'reference-point-course-change.mob' file.  This file only traces
 * position when there is a course change.  A second trace is produced
 * by this example: a time-series of node positions sampled every second.
 * This file is 'reference-point-time-series.mob' and can be plotted
 * with the 'reference-point-group-mobility-animation.sh' program.
 * 标准 ns-3 移动模型课程更改输出在“reference-point-course-change.mob”文件中进行跟踪。 该文件仅在路线发生变化时跟踪位置。
 * 这个例子产生了第二条轨迹:每秒采样的节点位置的时间序列。
 * 该文件是“reference-point-time-series.mob”,可以使用“reference-point-group-mobility-animation.sh”程序绘制。
 *
 * There is a bit of randomness in the child mobility models (random
 * walk within a 10m x 10m box surrounding the parent mobility position);
 * slightly different output can be rendered by changing the ns-3 'RunNumber'
 * value (see the documentation on ns-3 random variables).
 * 子移动模型有一点随机性(在父移动位置周围 10m x 10m 的盒子内随机行走);
 * 通过更改 ns-3 'RunNumber' 值可以呈现稍微不同的输出(请参阅有关 ns-3 随机变量的文档)。
 *
 * There is one program option:  'useHelper'.  This is simply for code
 * demonstration purposes; it selects the branch of code that is used
 * to either configure the mobility using a helper object, or
 * to directly configure using CreateObject<> () and handling of pointers.
 * The traces generated should be the same.
 * 有一个程序选项:“useHelper”。 这只是为了代码演示的目的;
 * 它选择用于使用辅助(helper)对象配置移动性或使用 CreateObject<> () 直接配置和处理指针的代码分支。
 * 生成的trace 应该是一样的。
 */

#include <iostream>
#include "ns3/core-module.h"
#include <ns3/mobility-module.h>
#include "ns3/network-module.h"

using namespace ns3;

NS_LOG_COMPONENT_DEFINE("ReferencePointGroupMobilityExample");

std::ofstream g_timeSeries;

void PrintPosition(Ptr<Node> node) {
	if (node == nullptr)
		return;
	Ptr<MobilityModel> model = node->GetObject<MobilityModel>();
	if (model == nullptr)
		return;
	NS_LOG_LOGIC(
			"Node: " << node->GetId () << " Position: " << model->GetPosition ());
	g_timeSeries << Simulator::Now().GetSeconds() << " " << node->GetId() << " "
			<< model->GetPosition() << std::endl;
}

int main(int argc, char *argv[]) {
	Time simTime = Seconds(800);
	uint32_t numPrints = 800;
	bool useHelper = false;

	CommandLine cmd(__FILE__);
	cmd.AddValue("useHelper", "Whether to use helper code", useHelper);
	cmd.Parse(argc, argv);

	g_timeSeries.open("reference-point-time-series.mob");

	NodeContainer n;
	n.Create(3);

	// The primary mobility model is the WaypointMobilityModel defined within
	// this bounding box:
	//
	// (0,50)                   (100,50)
	//   +-------------------------+
	//   |  .(10,40)    (90,40).   |
	//   |                         |
	//   |                         |
	//   |  .(10,10)    (90,10).   |
	//   |                         |
	//   +-------------------------+
	// (0,0)                     (100,0)
	//

	// The reference (parent) mobility model starts at coordinate (10,10
	// and walks clockwise to each waypoint, making two laps.  The time
	// to travel between each waypoint is 100s, so the velocity alternates
	// between two values due to the rectangular path.
	/*
	 * 参考(父)移动模型从坐标(10,10)开始,顺时针走到每个航路点,绕两圈。
	 * 每个航路点之间的行驶时间为 100 秒,因此由于矩形路径,速度在两个值之间交替。
	 * 个人理解:因为四个点的距离是不一样的,但两点间移动所需时间是一致的,则速度会有两种,且根据距离的变化而在这两种之间切换。
	 */
	// No actual node is represented by the position of this mobility
	// model; it forms the reference point from which the node's child
	// mobility model position is offset.
	/*
	 * 该移动模型的位置不代表任何实际节点; 它形成了节点的子移动模型位置偏移的参考点。
	 */

	Ptr<WaypointMobilityModel> waypointMm =
			CreateObject<WaypointMobilityModel>();
	waypointMm->AddWaypoint(Waypoint(Seconds(0), Vector(10, 10, 0)));
	waypointMm->AddWaypoint(Waypoint(Seconds(100), Vector(10, 40, 0)));
	waypointMm->AddWaypoint(Waypoint(Seconds(200), Vector(90, 40, 0)));
	waypointMm->AddWaypoint(Waypoint(Seconds(300), Vector(90, 10, 0)));
	waypointMm->AddWaypoint(Waypoint(Seconds(400), Vector(10, 10, 0)));
	waypointMm->AddWaypoint(Waypoint(Seconds(500), Vector(10, 40, 0)));
	waypointMm->AddWaypoint(Waypoint(Seconds(600), Vector(90, 40, 0)));
	waypointMm->AddWaypoint(Waypoint(Seconds(700), Vector(90, 10, 0)));
	waypointMm->AddWaypoint(Waypoint(Seconds(800), Vector(10, 10, 0)));

	// Each HierachicalMobilityModel contains the above model as the Parent,
	// and a user defined model as the Child.  Two MobilityModel objects are
	// instantiated per node (one hierarchical, and one child model), and
	// a single parent model is reused across all nodes.
	/**
	 * 每个 HierachicalMobilityModel 都包含上述模型作为 Parent,以及一个用户定义的模型作为 Child。
	 * 每个节点实例化两个 MobilityModel 对象(一个分层模型和一个子模型),并且在所有节点之间重用一个父模型。
	 */

	// The program now branches into two:  one using the low-level API, and
	// one using the GroupMobilityHelper.  Both branches result in equivalent
	// configuration.
	/*
	 * 该程序现在分为两种:一种使用低级 API,另一种使用 GroupMobilityHelper。
	 * 两个分支都产生相同的配置。
	 */

	int64_t streamIndex = 1;
	if (useHelper == false) {
		// Assign random variable stream numbers on the parent and each child
		streamIndex += waypointMm->AssignStreams(streamIndex);

		// Mobility model for the first node (node 0),第一个节点(节点 0)的移动模型
		// HierarchicalMobilityModel,分层移动模型
		Ptr<HierarchicalMobilityModel> hierarchical0 = CreateObject<
				HierarchicalMobilityModel>();
		//为分层移动模型设置父移动模型
		hierarchical0->SetParent(waypointMm);

		// Child Mobility model for the first node (node 0).  This can be any
		// other mobility model type; for this example, we reuse the random walk
		// but with a small 10m x 10m bounding box.
		/*
		 * 第一个节点(节点 0)的子移动模型。 这可以是任何其他移动模型类型;
		 * 对于这个例子,我们重用了随机游走,但使用了一个 10m x 10m 的小边界框。
		 */
		Ptr<RandomWalk2dMobilityModel> childRandomWalk0 = CreateObject<
				RandomWalk2dMobilityModel>();
		// Position in reference to the original random walk
		childRandomWalk0->SetAttribute("Bounds",
				RectangleValue(Rectangle(-5, 5, -5, 5)));
		childRandomWalk0->SetAttribute("Speed",
				StringValue("ns3::ConstantRandomVariable[Constant=5]"));
		streamIndex += childRandomWalk0->AssignStreams(streamIndex);
		hierarchical0->SetChild(childRandomWalk0);
		//为分层移动模型设置子移动模型
		n.Get(0)->AggregateObject(hierarchical0);

		// Repeat for other two nodes,为其他两个节点进行类似的设置
		Ptr<HierarchicalMobilityModel> hierarchical1 = CreateObject<
				HierarchicalMobilityModel>();
		//为分层移动模型设置父移动模型
		hierarchical1->SetParent(waypointMm); // Same parent as before
		Ptr<RandomWalk2dMobilityModel> childRandomWalk1 = CreateObject<
				RandomWalk2dMobilityModel>();
		childRandomWalk1->SetAttribute("Bounds",
				RectangleValue(Rectangle(-5, 5, -5, 5)));
		childRandomWalk1->SetAttribute("Speed",
				StringValue("ns3::ConstantRandomVariable[Constant=0.1]"));
		streamIndex += childRandomWalk1->AssignStreams(streamIndex);
		//为分层移动模型设置子移动模型
		hierarchical1->SetChild(childRandomWalk1);
		n.Get(1)->AggregateObject(hierarchical1);

		Ptr<HierarchicalMobilityModel> hierarchical2 = CreateObject<
				HierarchicalMobilityModel>();
		hierarchical2->SetParent(waypointMm); // Same parent as before
		Ptr<RandomWalk2dMobilityModel> childRandomWalk2 = CreateObject<
				RandomWalk2dMobilityModel>();
		childRandomWalk2->SetAttribute("Bounds",
				RectangleValue(Rectangle(-5, 5, -5, 5)));
		childRandomWalk2->SetAttribute("Speed",
				StringValue("ns3::ConstantRandomVariable[Constant=0.1]"));
		streamIndex += childRandomWalk2->AssignStreams(streamIndex);
		hierarchical2->SetChild(childRandomWalk2);
		n.Get(2)->AggregateObject(hierarchical2);
	} else {
		// This branch demonstrates an equivalent set of commands but using
		// the GroupMobilityHelper
		/*
		 * 此分支演示了一组等效的命令,但使用了 GroupMobilityHelper
		 * Jerry:即本else{}中的代码与if{}中的代码实现同等效果
		 */
		GroupMobilityHelper group;

		// The helper provides a method to set the reference mobility model
		// for construction by an object factory, but in this case, since we
		// are using the WaypointMobilityModel, which requires us to add
		// waypoints directly on the object, we will just pass in the pointer.
		/*
		 * helper 提供了一种方法来设置参考移动模型以供对象工厂构造,但在这种情况下,
		 * 由于我们使用的是 WaypointMobilityModel,这需要我们直接在对象上添加航点,
		 * 因此我们只需传入指针即可。
		 */
		group.SetReferenceMobilityModel(waypointMm);

		// The WaypointMobilityModel does not need a position allocator
		// (it can use its first waypoint as such), but in general, the
		// GroupMobilityHelper can be configured to accept configuration for
		// a PositionAllocator for the reference model.  We skip that here.
		/*
		 * WaypointMobilityModel 不需要位置分配器(它可以使用它的第一个航路点),
		 * 但通常可以将 GroupMobilityHelper 配置为接受参考模型的 PositionAllocator 配置。
		 */

		// Next, configure the member mobility model
		group.SetMemberMobilityModel("ns3::RandomWalk2dMobilityModel", "Bounds",
				RectangleValue(Rectangle(-5, 5, -5, 5)), "Speed",
				StringValue("ns3::ConstantRandomVariable[Constant=0.1]"));

		// Again, we could call 'SetMemberPositionAllocator' and provide a
		// position allocator here for the member nodes, but none is provided
		// in this example, so they will start at time zero with the same
		// position as the reference node.

		// Install to all three nodes
		group.Install(n);

		// After installation, use the helper to make the equivalent
		// stream assignments as above
		/*
		 * 安装后,使用 helper 进行与上述(if{...})等效的流分配
		 */
		group.AssignStreams(n, streamIndex);//如果AssignStreams在Install之前调用,将不会有任何效果。
	}

	// Note:  The tracing methods are static methods declared on the
	// MobilityHelper class, not on the GroupMobilityHelper class
	AsciiTraceHelper ascii;
	MobilityHelper::EnableAsciiAll(
			ascii.CreateFileStream("reference-point-course-change.mob"));

	// Use a logging PrintPosition() to record time-series position
	for (unsigned int i = 0; i < numPrints; i++) {
		for (auto nodeIt = n.Begin(); nodeIt != n.End(); ++nodeIt) {
			Simulator::Schedule(
					NanoSeconds(i * simTime.GetNanoSeconds() / numPrints),
					&PrintPosition, (*nodeIt));
		}
	}

	Simulator::Stop(simTime);
	Simulator::Run();
	g_timeSeries.close();
	Simulator::Destroy();
}

1.代码源自:NS-3 3.35 源码包:sr/mobility/examples/reference-point-group-mobility-example.cc

2.个人理解该示例主要是演示分层移动模型和能实现同等效果的GroupMobilityHelper(代码更简洁)的使用、trace  文件的生成及可视化绘图(.sh脚本读取.mob生成.png图)。分层移动节点结合了父移动模型和子移动模型,父移动模型主要控制节点的大体的移动方向,子移动模型负责微调。GroupMobilityHelper 达到了同样的效果。


3.执行该程序两种方式,第一种eclipse 下Run->External Tools ->自定义run(后文会结合图详细介绍),第二种命令行方式./waf --run reference-point-group-mobility-example --vis ,实际两种是一回事儿。

会生成两个trace 文件:

  • reference-point-course-change.mob ,只有在节点路线发生变化时NS3 才会将节点位置写入到该文件中。
  • reference-point-time-series.mob ,NS3 每秒将采样的节点位置的时间序列写入该文件。

第二个文件, 可以通过src/mobility/examples/reference-point-group-mobility-animate.sh 脚本(后文会结合图介绍)进行读取并生成大量.png 图片,每张图展示节点每隔一秒钟的节点位置。
运行脚本读取第二个文件reference-point-time-series.mob 的命令如下:
neusoft001@ubuntu:/usr/local/eclipse/projects20220106/NS-3_20220111$ ./src/mobility/examples/reference-point-group-mobility-animate.sh 
该脚本会读取reference-point-time-series.mob 文件。

注意.sh脚本和.mob 文件所在的位置。.sh 脚本文件在src/mobility/examples/ 下,生成的reference-point-time-series.mob 在eclipse 项目的根目录下。

4.节点移动轨迹:
父节点的移动路径是按照WaypointMobilityModel 规划好的,在整个游走范围内,分4个点,如下所示,父节点从(0,0)点出发按矩形路线顺时针移动,绕两圈。
    // (0,50)                   (100,50)
    //   +-------------------------+
    //   |  .(10,40)    (90,40).   |
    //   |                         |
    //   |                         |
    //   |  .(10,10)    (90,10).   |
    //   |                         |
    //   +-------------------------+
    // (0,0)                     (100,0)
5.遗留问题

暂时未整明白AssignStreams()函数是干嘛用的?望路过的懂得的老师,帮忙解答一下。先谢过了。

6.运行,eclipse 下Run->External Tools ->自定义run,如图:

自定义run(我这里自定义名为waf_run_vis)的配置如图:

 在自定义run 配置界面中点击Run 按钮或者直接点击eclipse 下Run->External Tools ->waf_run_vis 运行程序reference-point-group-mobility-example,如图,在弹框内输入reference-point-group-mobility-example(不带.cc扩展名):

 点击OK 按钮:

点击vis 仿真界面中的Simulator(F3) 按钮开始仿真:

我们看到左侧工程浏览区域里生成了两个trace 文件:

两个trace 文件的内容:

执行脚本,读取reference-point-time-series.mob trace文件生成png图片:

NS-3 3.35 源码包(编译后的源码包拷贝到eclipse 工程下了)中的 ./src/mobility/examples/reference-point-group-mobility-animate.sh

会生成很多.png 文件, 逐个打开png文件,我们将看到三个节点的位置变化情况:

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值