无线传感器网络质心定位算法的OPNET仿真实现

网络拓扑结构中包含2类独立的节点模型 :信标节点和未知节点.本节将分别介绍2类节点的功能及详细创建过程.

1 网络拓扑结构

1.1 创建数据包模型

信标节点通过向邻居节点按一定周期发送数据包达到使邻近的未知节点定位的目的,数据包中包含有该信标节点的位置信息.质心算法要求包中含有信标节点的x、y坐标和id号.数据包模型创建过程如下 :
在包格式编辑 器 (packet format)中新建包格式,命名为“wsn_location_format”.添加个32bits的包域,如图2所示,“anchor_id”为节点的 id,数据类型设置为“object id”“tx_x_position”和“tx_y_position”分别记录信标节点的X和Y坐标,数据类型为“floating point”.
数据包格式,包含节点ID,横纵坐标,以及发射功率
图1 包格式

1.2 信标节点模型

信标节点以相同强度功率向各个方向发送携带自身位置信息的数据包.此节点包含一个包生成模块tx_gen、一个包处理模块tx_pro、一个无线发射机模块radio_tx和一个天线模块ant_tx(仿真模型中所涉及到的天线均为全向天线).如图所示,在节点编辑器中创建各个模块.
在这里插入图片描述
(若是编辑栏没有天线模块,License->Produce Modules->Wireless)

  1. 无线发射机及天线模块 配置无线发射机“radio_ tx” 的“channel"属性,使得无线发射机支持包格式“wsn_ location_ format" ,并将“power"属性提升,将天线模型设置为“isotropic",即全向天线).发射机和天线的其它属性保持默认属性不变.
  2. 包生成模块 将包生成模块“tx_gen"中的“process model"修改为“simple_ source" ,此进程模块将以按一定的时间间隔产生数据包,修改“Packet Format"属性,使得产生的数据包格式为“wsn_location_format" ,将Packet Interarrival Time 属性提升“simple_ source" 进程模块为系统自带模块,这里不进行详细闹述.
    在这里插入图片描述
  3. 包处理模块 包处理模块“tx_pro"将信标节点的信息写入来自于包生成模块的数据包,然后将数据包发送到无线发射机.其内部的进程模块“wsn_location_tx_process" 的状态转换如图所示.仿真开始后仿真核心等待流中断,当有来自于包生成模块的包流时(即满足条件SRC_ ARRVL) ,执行函数xmt()被触发.xmt()函数将信标节点的位置信息及id写人数据包并将其发送到无线发射机。
    在这里插入图片描述
    在状态变量SV中定义如下如图所示变量
    在这里插入图片描述
    在头文件HB中输入如下代码:
#define XMT_OUT_STRM 0
#define SRC_ARRVL (op_intrpt_type () == OPC_INTRPT_STRM )

在功能函数FB中输入以下代码

static void xmt(void)
{
Packet * pkptr;
FIN(xmt());
tx_node_id = op_topo_parent(op_id_self());
pkptr=op_pk_get(op_intrpt_strm());
op_ima_obj_attr_get_dbl(tx_node_id,"x position",&src_nx);
op_ima_obj_attr_get_dbl(tx_node_id,"y position",&src_ny);
op_pk_nfd_set(pkptr,"tx_x_position",src_nx);
op_pk_nfd_set(pkptr,"tx_y_position",src_ny);
op_pk_nfd_set(pkptr,"anchor_id",tx_node_id);
op_pk_send(pkptr,XMT_OUT_STRM);
FOUT;
}
  1. 定义节点属性
    Interfaces -> Node Interfaces ,将altitude 属性置为0.03
    在这里插入图片描述
1.3 未知节点

未知节点接收邻近的信标节点发送的数据包,解析所接收的数据包,利用接收到的具有不同id的信标节点(大于等于3个)的坐标估算自身位置坐标,当获得自身坐标后停止接收数据并将自身作为信标节点以相同强度向周围发送携带自身位置信息的数据包该节点包含两个天线模块ant_rx和a_1、一个无线接收机模块rr_0、一个无线发射机模块rt_0和一个数据处理模块rx_sink,如图所示.

在这里插入图片描述

  1. 天线模块、无线接收机及无线发射机模块ant_rx为接收天线,a_1为发射天线(均为全向天线) ,分别完成接收数据包和定位完成后本节点作为信标节点发送数据包的任务.与信标节点中的天线属性设置相同,将发射机和接收机设置成为支持上文所定义的包格式,并具有相同的信道特性.
  2. 数据处理模块 数据处理模块rx_sink将所接收数据包中的信标节点存入自定义链表,选取3个不同id的信标节点计算未知节点坐标.模块rx_sink行为由进程“wsn_location_tx_est_process" 描述,进程状态转换如图所示.
    在这里插入图片描述
    强制状态init 为初始状态,完成注册统计量及初始化链表的功能.初始化结束后,init状态转移到wait状态,等待包流到来.当有新的包流到来时(即条件PACKET_STREAM_ ARRVAL满足)状态转移到restore状态,此强制状态用来将信标节点信息存储到链表,存储结束后返回wait状态,由wait状态判断链表的长度.当链表长度大于等于3时(条件SELF_ LOCATION_ COMPLETE满足) wait状态唤起自定义中断,状态转移到compute状态,该状态访问链表并应用质心算法公式计算节点坐标及定位误差.坐标计算结束,状态转移到idle状态,此状态定义自中断时间,当中断条件SEND_ CONDITION_ ACHEIVE满足时,转移到send状态. send状态创建“wsn_location_format"格式的数据包,将由compute状态估算的未知节点的坐标写入数据包并将其发送出去,发送完毕状态回到idle状态,等待下一次发送的时间到来.整个状态转移的过程可以大致分为两个阶段,一为未知节点接收信标节点所发送的数据包,计算自身坐标;二为未知节点获得自身位置信息后将自身作为信标节点向邻居发送数据包。

SV模块
在这里插入图片描述
HB模块代码

#include<math.h>

#define PACKET_STREAM_ARRVAL (op_intrpt_type()==OPC_INTRPT_STRM)
#define SELF_LOCATION_COMPLETE (op_intrpt_type()==OPC_INTRPT_SELF)
#define SEND_CONDITION_ACHEIVE (op_intrpt_type()==OPC_INTRPT_SELF)

typedef struct TX_Cache
   {
    double tx_x;
    double tx_y;
    Objid  node_id;	
   }TX_Cache;

Init 入口代码

/*´´½¨Á´±í*/
rxgroup_packet_lptr = op_prg_list_create ();

/*×¢²áͳ¼ÆÁ¿*/
Rx_Esti_Position_stathandle = op_stat_reg("Node_Position",OPC_STAT_INDEX_NONE, OPC_STAT_LOCAL);
Rx_Est_Position_Erro = op_stat_reg("Node_Position_Erro",OPC_STAT_INDEX_NONE, OPC_STAT_GLOBAL);

list_size = 0;

wait出口代码

list_size=op_prg_list_size(rxgroup_packet_lptr);
if(list_size >= 3){
  op_intrpt_schedule_self(op_sim_time(),0);
}

Restore入口代码

/*»ñÈ¡Á÷*/
packet = op_pk_get(op_intrpt_strm());

/*»ñµÃ°üµÄ¶ÔÏóµÄÊôÐÔÖµ*/
op_pk_nfd_get(packet,"tx_x_position",&tx_nx);
op_pk_nfd_get(packet,"tx_y_position",&tx_ny);
op_pk_nfd_get(packet,"anchor_id",&tx_node_id);


/*¶¨ÒåÒ»¸ö±êʶ·û*/
int flag = 0;

/*ÅжÏÁ´±íÖÐÊÇ·ñÓиýڵãÐÅÏ¢*/
for(i = 0 ; i < list_size ; i++){

packet_field_list_ptr = (TX_Cache*)op_prg_list_access(rxgroup_packet_lptr,i);
/*double temp_x = packet_field_list_ptr->tx_x;
double temp_y = packet_field_list_ptr->tx_x;*/
Objid temp_node_id = packet_field_list_ptr->node_id;
if( temp_node_id == tx_node_id)	
   {
   /*Èç¹ûÁ´±íÖк¬Óиýڵ㣬½«±êʶ·ûÖÃΪ1*/
   flag = 1;
   break;
   }
}

if(flag == 0) {
 /*¶¨ÒåÒ»¸ö¶ÔÏó*/
 TX_Cache* packet_field_elem_ptr;

 /*·ÖÅä¶ÔÏóÄÚ´æ*/
 /*packet_field_elem_pmh = op_prg_pmo_define ("packet list elements", sizeof (TX_Cache), 32);
 packet_field_elem_ptr =(TX_Cache *) op_prg_pmo_alloc(packet_field_elem_pmh);*/
 packet_field_elem_ptr = (TX_Cache *)op_prg_mem_alloc (sizeof (TX_Cache));


 /*É趨¶ÔÏóµÄÊôÐÔ*/
 packet_field_elem_ptr->tx_x = tx_nx;
 packet_field_elem_ptr->tx_y = tx_ny;
 packet_field_elem_ptr->node_id = tx_node_id;

 /*½«¶ÔÏóÌí¼Óµ½Á´±í*/
 /* Insert the buffer element into the list.			*/
 op_prg_list_insert (rxgroup_packet_lptr, packet_field_elem_ptr, OPC_LISTPOS_TAIL);	
}

Compute入口代码

list_size=op_prg_list_size(rxgroup_packet_lptr);
tx_x_sum = 0;
tx_y_sum = 0;
for(i = 0 ; i < list_size ; i++){

packet_field_list_ptr = (TX_Cache*)op_prg_list_access(rxgroup_packet_lptr,i);
/*point_ptr_xl = packet_field_list_ptr->tx_node_objid;
point_ptr_y1 = packet_field_list_ptr->tx_x;*/
tx_x_sum = tx_x_sum + packet_field_list_ptr->tx_x;
tx_y_sum = tx_y_sum + packet_field_list_ptr->tx_y;
}

if(list_size!=0){

rx_est_pos_x = tx_x_sum/list_size;
rx_est_pos_y = tx_y_sum/list_size;
op_stat_write_t(Rx_Esti_Position_stathandle,rx_est_pos_y,rx_est_pos_x);

}

/*»ñµÃ±¾½ÚµãµÄ×ø±ê*/
rx_tx_id =op_topo_parent(op_id_self());
op_ima_obj_attr_get_dbl(rx_tx_id,"x position",&rx_tx_pos_x);
op_ima_obj_attr_get_dbl(rx_tx_id,"y position",&rx_tx_pos_y);

/*¼ÆËã½ÚµãÎó²î*/
double temp_x_erro =  rx_tx_pos_x - rx_est_pos_x ;
double temp_y_erro =  rx_tx_pos_y - rx_est_pos_y ;
rx_est_erro = sqrt(temp_x_erro*temp_x_erro+temp_y_erro*temp_y_erro);
op_stat_write(Rx_Est_Position_Erro,rx_est_erro);

Idel入口代码

/*ÉèÖÃ×Ô¶¯¶Ï*/
op_intrpt_schedule_self(op_sim_time()+30,0);

end入口代码

/*¶¨ÒåÒ»¸ö·¢Éä°ü*/
Packet* send_pkptr;

/*´´½¨Ò»¸ö°ü*/
send_pkptr=op_pk_create_fmt("wsn_location_format");
op_pk_nfd_set(send_pkptr,"tx_x_position",rx_tx_pos_x);
op_pk_nfd_set(send_pkptr,"tx_y_position",rx_tx_pos_y);
op_pk_nfd_set(send_pkptr,"anchor_id",rx_tx_id);
op_pk_send(send_pkptr,0);

注册本地统计量
Interfaces -> Local Statistics
在这里插入图片描述
注册全局统计量
Interfaces -> Global Statistics
在这里插入图片描述
修改天线高度
Interfaces -> Node Interfaces ,将altitude 属性置为0.03

2 创建工程

在这里插入图片描述
注意创建工程时选择campus区域100km x 100km,其中tx是信标节点,est_rx是未知节点,图中tx_0坐标(12.5,37.5),tx_1坐标(50,25),tx_2坐标(62.5,62.5),est_rx坐标(37.5,37.5)(此处坐标随意,坐标设置在节点的高级属性里面设置)
同时在高级属性里面分别将tx_0,tx_1,tx_2,est_rx 的user id分别设置为1,2,3,4(此操作只是为了看结果时方便,对于实际计算无影响)
右键点击tx节点,依次修改三个节点的发包间隔为180,240,300
在这里插入图片描述
设定收集信息
设置未知节点统计量 Interfaces -> Node Statistics
在这里插入图片描述
右键est_rx节点 ->Choose Individual DES Statistics ->Node Statistics -> Node_Position
右键空白区域 -> Choose Individual DES Statistics ->Global Statistics -> Node_Position_Erro

运行仿真
DES > Configure/Run Discrete Event Simulation.
设置如图所示即可

在这里插入图片描述
然后运行,查看数据
在这里插入图片描述
点击右下角的show显示表格,右键表格,选择Export Graph Data to Spreadsheet,可以在弹出的excel表格中看到横纵坐标
在这里插入图片描述
其中41.66667代表所求质心的横坐标,41.66667代表所求质心的纵坐标。
同样方法查看节点误差
在这里插入图片描述
其中5.892557为预测误差

  • 5
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值