网络拓扑结构中包含2类独立的节点模型 :信标节点和未知节点.本节将分别介绍2类节点的功能及详细创建过程.
信标节点通过向邻居节点按一定周期发送数据包达到使邻近的未知节点定位的目的,数据包中包含有该信标节点的位置信息.质心算法要求包中含有信标节点的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,横纵坐标,以及发射功率
信标节点以相同强度功率向各个方向发送携带自身位置信息的数据包.此节点包含一个包生成模块tx_gen、一个包处理模块tx_pro、一个无线发射机模块radio_tx和一个天线模块ant_tx(仿真模型中所涉及到的天线均为全向天线).如图所示,在节点编辑器中创建各个模块.
(若是编辑栏没有天线模块,License->Produce Modules->Wireless)
#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;
}
未知节点接收邻近的信标节点发送的数据包,解析所接收的数据包,利用接收到的具有不同id的信标节点(大于等于3个)的坐标估算自身位置坐标,当获得自身坐标后停止接收数据并将自身作为信标节点以相同强度向周围发送携带自身位置信息的数据包该节点包含两个天线模块ant_rx和a_1、一个无线接收机模块rr_0、一个无线发射机模块rt_0和一个数据处理模块rx_sink,如图所示.
#include
#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
注意创建工程时选择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为预测误差