您好,欢迎访问三七文档
当前位置:首页 > 商业/管理/HR > 咨询培训 > 基于NS2的动态调整节点发射功率
1基于NS2的动态调整节点发射功率在NS2中,Otcl类和C++类是通过TclCL关联起来的。以NS2实现的AODV协议为例,Tclcl类的定义如下:StaticclassAODVclass:publicTclClass{Public:AODVclass():TclClass(“Agent/MYAODV”){}TclObject*create(intargc,constchar*const*argv){assert(argv==5);return(newAODV((nsaddr_t)atoi(argv[4])));}}class_rtProtoAODV;其中,Agent/MYAODV为编译类(c++)AODV所对应的解释类(Otcl),这样就可以在tcl中使用newAgent/MYAODV来获得AODV类的对象。当在Otcl类中调用某个方法时,ns首先从tcl类中查找并执行该方法;若查找失败,则在该Otcl类对应的C++类的command方法中查找,若查找仍然失败,则沿着该类的父类一直往上找,尝试调用它们的command方法;若所有父类的command方法都不能解析,则报告该命令无法执行。对于每个TclObject,ns为其Otcl中的解释对象建立一个实例过程,cmd{}。过程cmd{}调用影像对象的方法command(),并将cmd{}的参数作为一个参数数组传递给command()方法。以WirelessPhy::command()为例:2intWirlessphy::command(intargc,constchar*const*argv){if(argc==3){if(strcmp(argv[1],“setTxpower”==0)){Pt_consume_=atof(argv[2]);returnTCL_OK;}}}(1)第1个参数(argc)指明解释器的命令行中参数的个数。(2)命令行参数数组(argv),它包括:argv[0]包含方法名“cmd”;argv[1]指定欲进行的操作,如例子中的“setTxpower”;用户指定的其他参数,被置于argv[2…(argc-1)]中。这些参数作为字符串传递:它们必须转换为适当的数据类型。这样,我们就可以在tcl中使用命令:$objectsetTxpowerxxxx就可以为某个节点($object为获得的节点的对象)的Pt_consume_赋值为xxxx。针对不同的模块,ns底层已提供了一些相应的command接口或是编写了自己的tcl文件来定义了相关的命令供我们使用。例如Phy/WirelessPhy类的command函数中提供了setTxpower命令来设置节点发送功率能耗。而Node类则在ns/tcl/lib中提供了node.tcl文件,其中定义了很多过程,如Nodeinsprocid{}、Nodeinsprocadd-neighbor{}等。这样,我们在编写自己的tcl文件时就可以直接调用这些命令,3而如果已有的这些命令不能满足仿真要求时就需要自己在相应的command函数中提供接口或者为类添加新的过程。通过查阅相关的资料以及多次尝试,可知利用ns2已有的接口只在tcl中动态调整节点发射功率是很难实现的,必须改变底层的c++代码。对此,我们提出两种解决方法:一种是完全在c++中进行,即在wirelessphy文件中提供一个定时器,定期调用遗传算法:首先获得各节点的坐标(通过获得节点类的坐标变量),然后迭代若干代得到各节点的发射功率值,将其赋给WirelessPhy::sendDown(Packet*p)函数中的发射功率Pt_。但存在两个问题:一方面遗传算法的运行时间较长,因此较难确定定时器的间隔时间,而且要进行调整时必须重新编译ns,效率较低;另一方面我们没有解决如何在WirelessPhy::sendDown(Packet*p)函数中区分每一个节点,为每一个节点分配对应的Pt_值。第二种方法就是在command中添加新的接口,使得可以在tcl文件中定时调用遗传算法并为每个节点分配对应的Pt_值。我们最开始是将遗传算法添加在WirelessPhy类中,然后在WirelessPhy::command()中提供了两个接口,如下:if(argc==2){if(strcmp(argv[1],“call-GA”==0)){GA();returnTCL_OK;}}4if(argc==3){if(strcmp(argv[1],“resetpt”==0)){Pt_=pt[atoi(argv[2])];returnTCL_OK;}}其中,pt[]为遗传算法中计算出来的节点的最优发射功率数组。然后在tcl文件中定时调用一个过程,在过程中首先得到某一个节点的物理层对象,然后用该对象去调用遗传算法(因为遗传算法的运行时间较长,如果在仿真中每个节点都去调用它,只运行四、五个节点就会死机)得到pt[]值,最后对每一个节点使用resetpt命令为各自的Pt_赋值。但运行结果出现的问题是,只有调用遗传算法GA()的那个节点的Pt_值正确,其它节点的Pt_值都为0。这是因为每个节点都有自己的物理层对象,所以在WirelessPhy类中定义的每个变量(也包括数组、函数返回值等)都会对应各个节点有不同的值。明白了这一点,我们就需要在c++中得到节点的物理层对象,然后将调用遗传算法的那个节点的物理层对象的pt[]值赋给command函数中的Pt_。但一直也没有解决如何在WirelessPhy.cc中获得节点的物理层对象。所以我们后来将遗传算法添加在了节点类中,即node.cc中(实际中,遗传算法就应该是由节点来运行吧)。然后在WirelessPhy.h中定义了一个节点类的对象:Node*tnode;并在WirelessPhy类的构造5函数中为其赋值:tnode=Node::get_node_by_address(0);//得到0节点的对象然后修改WirelessPhy类中的command函数,如下:if(argc==2){if(strcmp(argv[1],“call-GA”==0)){tnode-GA();//调用node0的GA算法returnTCL_OK;}}if(argc==3){if(strcmp(argv[1],“resetpt”==0)){Pt_=tnode-pt[atoi(argv[2])];//将node0的pt赋给Pt_returnTCL_OK;}}最后在tcl文件中定时调用遗传算法,并将得到的发射功率值赋给每个节点。自定义过程如下:procmyproc{}{globalns_node_setnow[$ns_now]#获得当前时间settime120#//每隔120秒去调用一次setmac0[$node_(0)getMac0];#Node0对象的Mac层6settrace0[$mac0down-target];#Mac层的down-target原本应该是Phy,但是在无线仿真中,基本都打开Trace,所以这里是CUMTrace对象setphy0[$trace0target];#CUMTrace对象的Target就是Phy对象$phy0call-GA;#调用节点0的GA算法for{seti0}{$i20}{incri}{setmac[$node_($i)getMac0]settrace[$macdown-target]setphy[$tracetarget]$phyresetpti}#为每一个节点设置发送功率值$ns_at[expr$expr$now+$time]“myproc”#递归调用}
本文标题:基于NS2的动态调整节点发射功率
链接地址:https://www.777doc.com/doc-6684625 .html