如何处理广播请求响应的冲突?
How to handle collision for response of a broadcast request?
我正在尝试使用广播请求从相邻节点获取坐标并将它们存储到列表中。我只能得到其中一个响应,我认为这是由于节点同时响应时响应之间的冲突而发生的。我尝试在相邻节点的代理上使用具有随机退避的退避行为,但它没有解决问题。如何同步机制以避免碰撞?
我已经为每个盲节点(将发出广播请求)和相邻节点编写了一个代理。
以下是代码片段。
盲节点上的代理:
import org.arl.fjage.*
import org.arl.fjage.Message
import org.arl.fjage.RealTimePlatform
import org.arl.unet.phy.*
import org.arl.unet.mac.*
import org.arl.unet.*
import org.arl.unet.PDU
import org.arl.unet.net.Router
import org.arl.unet.nodeinfo.NodeInfo
import org.arl.unet.localization.*
import org.arl.unet.localization.RangeNtf.*
import org.arl.unet.localization.Ranging.*
import org.arl.unet.localization.RangeReq
import org.arl.unet.net.RouteDiscoveryReq
class node_agent extends UnetAgent {
float neighbor_addr;
float distance;
def xlist = [];
def ylist = [];
def zlist = [];
def dlist = [];
private final static PDU format = PDU.withFormat
{
uint16('source')
}
void startup()
{
def phy = agentForService Services.PHYSICAL;
subscribe topic(phy);
println 'Starting discovery...'
phy << new DatagramReq(to: 0, protocol:Protocol.MAC);
}
void processMessage(Message msg)
{
def ranging = agentForService Services.RANGING;
subscribe topic(ranging);
if(msg instanceof RxFrameNtf && msg.protocol==Protocol.MAC)
{
def rx = format.decode(msg.data);
neighbor_addr=rx.source;
println "Found one neighbour with address "+neighbor_addr;
ranging<< new RangeReq(to: neighbor_addr,requestLocation: true);
}
else if (msg instanceof RangeNtf )
{
distance = msg.getRange();
def locat=new double[3];
locat = msg.getPeerLocation();
double x,y,z;
x=locat[0];
y=locat[1];
z=locat[2];
xlist.add(x);
ylist.add(y);
zlist.add(z);
dlist.add(distance);
println " The coordinates of "+msg.to + " are " +locat+ " and the distance is "+distance;
println xlist;
println ylist;
println zlist;
println dlist;
}
}
}
相邻节点上的代理:
import org.arl.fjage.*
import org.arl.fjage.Message
import org.arl.fjage.RealTimePlatform
import org.arl.unet.phy.*
import org.arl.unet.mac.*
import org.arl.unet.*
import org.arl.unet.PDU
import org.arl.unet.net.Router
import org.arl.unet.nodeinfo.NodeInfo
import org.arl.unet.localization.*
import org.arl.unet.localization.RangeNtf.*
import org.arl.unet.localization.Ranging.*
import org.arl.unet.localization.RangeReq
import org.arl.unet.net.RouteDiscoveryReq
class anchor_agent extends UnetAgent {
def addr;
private final static PDU format = PDU.withFormat
{
uint16('source')
}
void startup()
{
def phy = agentForService Services.PHYSICAL;
subscribe topic(phy);
}
void processMessage(Message msg)
{
def phy = agentForService Services.PHYSICAL;
subscribe topic(phy);
def nodeInfo = agentForService Services.NODE_INFO;
addr = nodeInfo.address;
def datapacket = format.encode(source: addr);
if(msg instanceof DatagramNtf && msg.protocol==Protocol.MAC)
{
def n=rndint(3);
add new BackoffBehavior(n*1000,{
phy << new TxFrameReq(to: msg.from,
protocol: Protocol.MAC,
data: datapacket)})
backoff(n*1000)})
}
}
}
模拟脚本:
import org.arl.fjage.*
println '''
3-node network
--------------
'''
platform = RealTimePlatform
simulate {
node 'B', address: 101, location: [ 0.km, 0.km, -15.m], web:8081,api: 1101, shell: true, stack: "$home/etc/setup2"
node '1', address: 102, location: [ 0.km, 1.km, -15.m], web:8082,api: 1102, shell: 5101, stack: "$home/etc/setup3"
node '2', address: 103, location: [-900.m, 0.km, -15.m], web:8083,api: 1103, shell: 5102, stack: "$home/etc/setup3"
node '3', address: 104, location: [ 600.m, 0.km, -15.m], web:8084,api: 1104, shell: 5103, stack: "$home/etc/setup3"
}
我已经简化了您的代理并制作了一个工作示例。锚点发现分为两个阶段:(1)找到周围的锚点,以及(2)获取它们的位置。将其分解的原因是您希望初始发现需要最少的通道访问以减少冲突的机会。一旦知道周围有哪些节点,就可以更好地控制以后的定位请求。
我已将代理合并到一个模拟脚本中,因此您只需将代码复制到一个文件中,然后 运行 它:
import org.arl.fjage.*
import org.arl.unet.*
import org.arl.unet.localization.*
platform = RealTimePlatform
class NodeAgent extends UnetAgent {
AgentID phy
AgentID ranging
List<Integer> anchors = []
def anchorLocations = [:]
void startup() {
phy = agentForService Services.PHYSICAL
ranging = agentForService Services.RANGING
subscribe topic(phy)
log.info 'Starting anchor discovery...'
phy << new DatagramReq(to: 0, protocol: Protocol.USER)
// wait for 15 seconds for all nodes to respond before trying to get their locations
add new WakerBehavior(15000, this.&getLocations)
}
void getLocations() {
log.info "Discovered ${anchors.size()} anchor(s), getting locations..."
anchors.eachWithIndex { addr, i ->
// request location for each node 5 seconds apart
add new WakerBehavior(5000*i, {
log.info "Asking node ${addr} for its location..."
ranging << new RangeReq(to: addr, requestLocation: true)
})
}
}
void processMessage(Message msg) {
if (msg instanceof DatagramNtf && msg.protocol == Protocol.USER) {
log.info "Discovered node ${msg.from}"
anchors.add(msg.from)
}
if (msg instanceof RangeNtf) {
log.info "Got location of anchor ${msg.to}: ${msg.peerLocation}"
anchorLocations[msg.to] = msg.peerLocation
}
}
}
class AnchorAgent extends UnetAgent {
AgentID phy
AgentLocalRandom rnd
void startup() {
rnd = AgentLocalRandom.current()
phy = agentForService Services.PHYSICAL
subscribe topic(phy)
}
void processMessage(Message msg) {
if (msg instanceof DatagramNtf && msg.protocol == Protocol.USER) {
// respond back to a discovery request with a random backoff of up to 13 seconds
long backoff = rnd.nextDouble(0, 13000)
log.info "Discovery request from ${msg.from}, will respond after ${backoff} ms"
add new WakerBehavior(backoff, {
log.info 'Responding...'
phy << new DatagramReq(to: msg.from, protocol: Protocol.USER)
})
}
}
}
setup2 = { c ->
c.add 'ranging', new Ranging()
c.add 'agent2', new NodeAgent()
}
setup3 = { c ->
c.add 'ranging', new Ranging()
c.add 'agent3', new AnchorAgent()
}
simulate {
node 'B', address: 101, location: [ 0.km, 0.km, -15.m], web:8081,api: 1101, shell: true, stack: setup2
node '1', address: 102, location: [ 0.km, 1.km, -15.m], web:8082,api: 1102, shell: 5101, stack: setup3
node '2', address: 103, location: [-900.m, 0.km, -15.m], web:8083,api: 1103, shell: 5102, stack: setup3
node '3', address: 104, location: [ 600.m, 0.km, -15.m], web:8084,api: 1104, shell: 5103, stack: setup3
}
以下是来自样本 运行 的日志:
1613226179777|INFO|NodeAgent/B@83:call|Starting anchor discovery...
1613226180943|INFO|AnchorAgent/3@112:doInvoke|Discovery request from 101, will respond after 6704 ms
1613226181134|INFO|AnchorAgent/2@103:doInvoke|Discovery request from 101, will respond after 7628 ms
1613226181193|INFO|AnchorAgent/1@94:doInvoke|Discovery request from 101, will respond after 3747 ms
1613226184945|INFO|AnchorAgent/1@94:call|Responding...
1613226186356|INFO|NodeAgent/B@83:doInvoke|Discovered node 102
1613226187654|INFO|AnchorAgent/3@112:call|Responding...
1613226188764|INFO|AnchorAgent/2@103:call|Responding...
1613226188805|INFO|NodeAgent/B@83:doInvoke|Discovered node 104
1613226190731|INFO|NodeAgent/B@83:doInvoke|Discovered node 103
1613226194960|INFO|NodeAgent/B@83:doInvoke|Discovered 3 anchor(s), getting locations...
1613226194963|INFO|NodeAgent/B@83:doInvoke|Asking node 102 for its location...
1613226199126|INFO|NodeAgent/B@83:doInvoke|Got location of anchor 102: [0.0, 1000.0, -15.0]
1613226199965|INFO|NodeAgent/B@83:doInvoke|Asking node 104 for its location...
1613226203782|INFO|NodeAgent/B@83:doInvoke|Got location of anchor 104: [600.0, 0.0, -15.0]
1613226204969|INFO|NodeAgent/B@83:doInvoke|Asking node 103 for its location...
1613226209069|INFO|NodeAgent/B@83:doInvoke|Got location of anchor 103: [-900.0, 0.0, -15.0]
表明它有效!
在随机访问情况下,仍然存在发生冲突的可能性,但初始发现时间越长(目前为 15 秒),它就会越小。如果您收到 BadFrameNtf
或 CollisionNtf
,表明某个节点尝试通信但失败,您可以通过添加重试来进一步使系统更健壮。
我正在尝试使用广播请求从相邻节点获取坐标并将它们存储到列表中。我只能得到其中一个响应,我认为这是由于节点同时响应时响应之间的冲突而发生的。我尝试在相邻节点的代理上使用具有随机退避的退避行为,但它没有解决问题。如何同步机制以避免碰撞? 我已经为每个盲节点(将发出广播请求)和相邻节点编写了一个代理。
以下是代码片段。
盲节点上的代理:
import org.arl.fjage.*
import org.arl.fjage.Message
import org.arl.fjage.RealTimePlatform
import org.arl.unet.phy.*
import org.arl.unet.mac.*
import org.arl.unet.*
import org.arl.unet.PDU
import org.arl.unet.net.Router
import org.arl.unet.nodeinfo.NodeInfo
import org.arl.unet.localization.*
import org.arl.unet.localization.RangeNtf.*
import org.arl.unet.localization.Ranging.*
import org.arl.unet.localization.RangeReq
import org.arl.unet.net.RouteDiscoveryReq
class node_agent extends UnetAgent {
float neighbor_addr;
float distance;
def xlist = [];
def ylist = [];
def zlist = [];
def dlist = [];
private final static PDU format = PDU.withFormat
{
uint16('source')
}
void startup()
{
def phy = agentForService Services.PHYSICAL;
subscribe topic(phy);
println 'Starting discovery...'
phy << new DatagramReq(to: 0, protocol:Protocol.MAC);
}
void processMessage(Message msg)
{
def ranging = agentForService Services.RANGING;
subscribe topic(ranging);
if(msg instanceof RxFrameNtf && msg.protocol==Protocol.MAC)
{
def rx = format.decode(msg.data);
neighbor_addr=rx.source;
println "Found one neighbour with address "+neighbor_addr;
ranging<< new RangeReq(to: neighbor_addr,requestLocation: true);
}
else if (msg instanceof RangeNtf )
{
distance = msg.getRange();
def locat=new double[3];
locat = msg.getPeerLocation();
double x,y,z;
x=locat[0];
y=locat[1];
z=locat[2];
xlist.add(x);
ylist.add(y);
zlist.add(z);
dlist.add(distance);
println " The coordinates of "+msg.to + " are " +locat+ " and the distance is "+distance;
println xlist;
println ylist;
println zlist;
println dlist;
}
}
}
相邻节点上的代理:
import org.arl.fjage.*
import org.arl.fjage.Message
import org.arl.fjage.RealTimePlatform
import org.arl.unet.phy.*
import org.arl.unet.mac.*
import org.arl.unet.*
import org.arl.unet.PDU
import org.arl.unet.net.Router
import org.arl.unet.nodeinfo.NodeInfo
import org.arl.unet.localization.*
import org.arl.unet.localization.RangeNtf.*
import org.arl.unet.localization.Ranging.*
import org.arl.unet.localization.RangeReq
import org.arl.unet.net.RouteDiscoveryReq
class anchor_agent extends UnetAgent {
def addr;
private final static PDU format = PDU.withFormat
{
uint16('source')
}
void startup()
{
def phy = agentForService Services.PHYSICAL;
subscribe topic(phy);
}
void processMessage(Message msg)
{
def phy = agentForService Services.PHYSICAL;
subscribe topic(phy);
def nodeInfo = agentForService Services.NODE_INFO;
addr = nodeInfo.address;
def datapacket = format.encode(source: addr);
if(msg instanceof DatagramNtf && msg.protocol==Protocol.MAC)
{
def n=rndint(3);
add new BackoffBehavior(n*1000,{
phy << new TxFrameReq(to: msg.from,
protocol: Protocol.MAC,
data: datapacket)})
backoff(n*1000)})
}
}
}
模拟脚本:
import org.arl.fjage.*
println '''
3-node network
--------------
'''
platform = RealTimePlatform
simulate {
node 'B', address: 101, location: [ 0.km, 0.km, -15.m], web:8081,api: 1101, shell: true, stack: "$home/etc/setup2"
node '1', address: 102, location: [ 0.km, 1.km, -15.m], web:8082,api: 1102, shell: 5101, stack: "$home/etc/setup3"
node '2', address: 103, location: [-900.m, 0.km, -15.m], web:8083,api: 1103, shell: 5102, stack: "$home/etc/setup3"
node '3', address: 104, location: [ 600.m, 0.km, -15.m], web:8084,api: 1104, shell: 5103, stack: "$home/etc/setup3"
}
我已经简化了您的代理并制作了一个工作示例。锚点发现分为两个阶段:(1)找到周围的锚点,以及(2)获取它们的位置。将其分解的原因是您希望初始发现需要最少的通道访问以减少冲突的机会。一旦知道周围有哪些节点,就可以更好地控制以后的定位请求。
我已将代理合并到一个模拟脚本中,因此您只需将代码复制到一个文件中,然后 运行 它:
import org.arl.fjage.*
import org.arl.unet.*
import org.arl.unet.localization.*
platform = RealTimePlatform
class NodeAgent extends UnetAgent {
AgentID phy
AgentID ranging
List<Integer> anchors = []
def anchorLocations = [:]
void startup() {
phy = agentForService Services.PHYSICAL
ranging = agentForService Services.RANGING
subscribe topic(phy)
log.info 'Starting anchor discovery...'
phy << new DatagramReq(to: 0, protocol: Protocol.USER)
// wait for 15 seconds for all nodes to respond before trying to get their locations
add new WakerBehavior(15000, this.&getLocations)
}
void getLocations() {
log.info "Discovered ${anchors.size()} anchor(s), getting locations..."
anchors.eachWithIndex { addr, i ->
// request location for each node 5 seconds apart
add new WakerBehavior(5000*i, {
log.info "Asking node ${addr} for its location..."
ranging << new RangeReq(to: addr, requestLocation: true)
})
}
}
void processMessage(Message msg) {
if (msg instanceof DatagramNtf && msg.protocol == Protocol.USER) {
log.info "Discovered node ${msg.from}"
anchors.add(msg.from)
}
if (msg instanceof RangeNtf) {
log.info "Got location of anchor ${msg.to}: ${msg.peerLocation}"
anchorLocations[msg.to] = msg.peerLocation
}
}
}
class AnchorAgent extends UnetAgent {
AgentID phy
AgentLocalRandom rnd
void startup() {
rnd = AgentLocalRandom.current()
phy = agentForService Services.PHYSICAL
subscribe topic(phy)
}
void processMessage(Message msg) {
if (msg instanceof DatagramNtf && msg.protocol == Protocol.USER) {
// respond back to a discovery request with a random backoff of up to 13 seconds
long backoff = rnd.nextDouble(0, 13000)
log.info "Discovery request from ${msg.from}, will respond after ${backoff} ms"
add new WakerBehavior(backoff, {
log.info 'Responding...'
phy << new DatagramReq(to: msg.from, protocol: Protocol.USER)
})
}
}
}
setup2 = { c ->
c.add 'ranging', new Ranging()
c.add 'agent2', new NodeAgent()
}
setup3 = { c ->
c.add 'ranging', new Ranging()
c.add 'agent3', new AnchorAgent()
}
simulate {
node 'B', address: 101, location: [ 0.km, 0.km, -15.m], web:8081,api: 1101, shell: true, stack: setup2
node '1', address: 102, location: [ 0.km, 1.km, -15.m], web:8082,api: 1102, shell: 5101, stack: setup3
node '2', address: 103, location: [-900.m, 0.km, -15.m], web:8083,api: 1103, shell: 5102, stack: setup3
node '3', address: 104, location: [ 600.m, 0.km, -15.m], web:8084,api: 1104, shell: 5103, stack: setup3
}
以下是来自样本 运行 的日志:
1613226179777|INFO|NodeAgent/B@83:call|Starting anchor discovery...
1613226180943|INFO|AnchorAgent/3@112:doInvoke|Discovery request from 101, will respond after 6704 ms
1613226181134|INFO|AnchorAgent/2@103:doInvoke|Discovery request from 101, will respond after 7628 ms
1613226181193|INFO|AnchorAgent/1@94:doInvoke|Discovery request from 101, will respond after 3747 ms
1613226184945|INFO|AnchorAgent/1@94:call|Responding...
1613226186356|INFO|NodeAgent/B@83:doInvoke|Discovered node 102
1613226187654|INFO|AnchorAgent/3@112:call|Responding...
1613226188764|INFO|AnchorAgent/2@103:call|Responding...
1613226188805|INFO|NodeAgent/B@83:doInvoke|Discovered node 104
1613226190731|INFO|NodeAgent/B@83:doInvoke|Discovered node 103
1613226194960|INFO|NodeAgent/B@83:doInvoke|Discovered 3 anchor(s), getting locations...
1613226194963|INFO|NodeAgent/B@83:doInvoke|Asking node 102 for its location...
1613226199126|INFO|NodeAgent/B@83:doInvoke|Got location of anchor 102: [0.0, 1000.0, -15.0]
1613226199965|INFO|NodeAgent/B@83:doInvoke|Asking node 104 for its location...
1613226203782|INFO|NodeAgent/B@83:doInvoke|Got location of anchor 104: [600.0, 0.0, -15.0]
1613226204969|INFO|NodeAgent/B@83:doInvoke|Asking node 103 for its location...
1613226209069|INFO|NodeAgent/B@83:doInvoke|Got location of anchor 103: [-900.0, 0.0, -15.0]
表明它有效!
在随机访问情况下,仍然存在发生冲突的可能性,但初始发现时间越长(目前为 15 秒),它就会越小。如果您收到 BadFrameNtf
或 CollisionNtf
,表明某个节点尝试通信但失败,您可以通过添加重试来进一步使系统更健壮。