850 lines
20 KiB
Plaintext
850 lines
20 KiB
Plaintext
#
|
|
# Include files
|
|
#
|
|
include "string.bzz"
|
|
include "vec2.bzz"
|
|
include "update.bzz"
|
|
|
|
#include "vstigenv.bzz" # reserve stigmergy id=20 and 21 for this header.
|
|
include "barrier.bzz" # reserve stigmergy id=80 (auto-increment up) for this header.
|
|
include "uavstates.bzz" # require an 'action' function to be defined here.
|
|
|
|
include "graphs/shapes_P.bzz"
|
|
include "graphs/shapes_O.bzz"
|
|
include "graphs/shapes_L.bzz"
|
|
include "graphs/shapes_Y.bzz"
|
|
|
|
ROBOT_RADIUS = 50
|
|
ROBOT_DIAMETER = 2.0*ROBOT_RADIUS
|
|
ROBOT_SAFETYDIST = 2.0*ROBOT_DIAMETER
|
|
ROOT_ID = 2
|
|
old_state = -1
|
|
|
|
# max velocity in cm/step
|
|
ROBOT_MAXVEL = 150.0
|
|
|
|
#
|
|
# Global variables
|
|
#
|
|
|
|
#
|
|
# Save message from all neighours
|
|
#the indexes are as 1,2,3..., while each value is a table that store the information of a neighbour robot
|
|
m_MessageState={}#store received neighbour message
|
|
m_MessageLabel={}#store received neighbour message
|
|
m_MessageReqLabel={}#store received neighbour message
|
|
m_MessageReqID={}#store received neighbour message
|
|
m_MessageResponse={}#store received neighbour message
|
|
m_MessageRange={}#store received neighbour message
|
|
m_MessageBearing={}#store received neighbour message
|
|
m_neighbourCount=0#used to cunt neighbours
|
|
#Save message from one neighbour
|
|
#the indexes are as State(received state),Label(received Label),ReqLabel,ReqID,Response,Range,Bearing
|
|
m_receivedMessage={.State=s2i("STATE_FREE"),.Label=0,.ReqLabel=0,.ReqID=0,.Response=r2i("REQ_NONE"),.Range=0,.Bearing=0}
|
|
|
|
#
|
|
#Save the message to send
|
|
#The keys of the talbe is State(current state),Label(current Label),ReqLabel(requested Label),ReqID(request id),Response(reply message{REQ_NONE,REQ_GRANTED,REQ_RESEND})
|
|
m_selfMessage={.State=s2i("STATE_FREE"),.Label=0,.ReqLabel=0,.ReqID=0,.Response=r2i("REQ_NONE")}
|
|
|
|
#navigation vector
|
|
m_navigation={.x=0,.y=0}
|
|
|
|
#Current label being requested or chosen (-1 when none)
|
|
m_nLabel=-1
|
|
m_messageID={}
|
|
repeat_assign=0
|
|
assign_label=-1
|
|
assign_id=-1
|
|
m_gotjoinedparent = 0
|
|
#neighbor distance to lock the current pattern
|
|
lock_neighbor_id={}
|
|
lock_neighbor_dis={}
|
|
|
|
#Label request id
|
|
m_unRequestId=0
|
|
|
|
#Global bias, used to map local coordinate to global coordinate
|
|
m_bias=0
|
|
|
|
#Vector to predecessor,range is the distance between robots, bearing is the angle of pred wrt self in local coordinate of self, globalbearing is the angle of self wrt pred in global coordinate
|
|
m_cMeToPred={.Range=0.0,.Bearing=0.0,.GlobalBearing=0.0}
|
|
|
|
#Counter to wait for something to happen
|
|
m_unWaitCount=0
|
|
|
|
#Number of steps to wait before looking for a free label
|
|
m_unLabelSearchWaitTime=0
|
|
|
|
#Number of steps to wait for an answer to be received
|
|
m_unResponseTimeThreshold=0
|
|
|
|
#Number of steps to wait until giving up joining
|
|
m_unJoiningLostPeriod=0
|
|
|
|
#Tolerance distance to a target location
|
|
m_fTargetDistanceTolerance=0
|
|
|
|
# virtual stigmergy for the LOCK barrier.
|
|
m_lockstig = 1
|
|
|
|
# Lennard-Jones parameters, may need change
|
|
EPSILON = 4000 #13.5 the LJ parameter for other robots
|
|
|
|
# Lennard-Jones interaction magnitude
|
|
|
|
function FlockInteraction(dist,target,epsilon){
|
|
var mag = -(epsilon / dist) * ((target / dist)^4 - (target / dist)^2)
|
|
return mag
|
|
}
|
|
|
|
#
|
|
#return the number of value in table
|
|
#
|
|
function count(table,value){
|
|
var number=0
|
|
var i=0
|
|
while(i<size(table)){
|
|
if(table[i]==value){
|
|
number=number+1
|
|
}
|
|
i=i+1
|
|
}
|
|
return number
|
|
}
|
|
#
|
|
#map from int to state
|
|
#
|
|
function i2s(value){
|
|
if(value==1){
|
|
return "STATE_FREE"
|
|
}
|
|
else if(value==2){
|
|
return "STATE_ASKING"
|
|
}
|
|
else if(value==3){
|
|
return "STATE_JOINING"
|
|
}
|
|
else if(value==4){
|
|
return "STATE_JOINED"
|
|
}
|
|
else if(value==5){
|
|
return "STATE_LOCK"
|
|
}
|
|
}
|
|
#
|
|
#map from state to int
|
|
#
|
|
function s2i(value){
|
|
if(value=="STATE_FREE"){
|
|
return 1
|
|
}
|
|
else if(value=="STATE_ASKING"){
|
|
return 2
|
|
}
|
|
else if(value=="STATE_JOINING"){
|
|
return 3
|
|
}
|
|
else if(value=="STATE_JOINED"){
|
|
return 4
|
|
}
|
|
else if(value=="STATE_LOCK"){
|
|
return 5
|
|
}
|
|
}
|
|
#
|
|
#map form int to response
|
|
#
|
|
function i2r(value){
|
|
if(value==1){
|
|
return "REQ_NONE"
|
|
}
|
|
else if(value==2){
|
|
return "REQ_GRANTED"
|
|
}
|
|
}
|
|
#
|
|
#map from response to int
|
|
#
|
|
function r2i(value){
|
|
if(value=="REQ_NONE"){
|
|
return 1
|
|
}
|
|
else if(value=="REQ_GRANTED"){
|
|
return 2
|
|
}
|
|
}
|
|
#
|
|
#return the index of value
|
|
#
|
|
function find(table,value){
|
|
var ind=nil
|
|
var i=0
|
|
while(i<size(table)){
|
|
if(table[i]==value)
|
|
ind=i
|
|
i=i+1
|
|
}
|
|
return ind
|
|
}
|
|
#
|
|
#pack message into 1 number
|
|
#
|
|
function packmessage(send_table){
|
|
var send_value
|
|
send_value=100000*send_table.State+10000*send_table.Label+1000*send_table.ReqLabel+10*send_table.ReqID+send_table.Response
|
|
return send_value
|
|
}
|
|
#
|
|
#pack guide message into 1 number
|
|
#
|
|
function pack_guide_msg(send_table){
|
|
var send_value
|
|
var r_id=send_table.Label#id of target robot
|
|
var pon#positive or negative ,0 postive, 1 negative
|
|
if(send_table.Bearing>=0){
|
|
pon=0
|
|
}
|
|
else{
|
|
pon=1
|
|
}
|
|
var b=math.abs(send_table.Bearing)
|
|
send_value=r_id*1000+pon*100+b
|
|
return send_value
|
|
}
|
|
#
|
|
#unpack message
|
|
#
|
|
function unpackmessage(recv_value){
|
|
var wan=(recv_value-recv_value%100000)/100000
|
|
recv_value=recv_value-wan*100000
|
|
var qian=(recv_value-recv_value%10000)/10000
|
|
recv_value=recv_value-qian*10000
|
|
var bai=(recv_value-recv_value%1000)/1000
|
|
recv_value=recv_value-bai*1000
|
|
var shi=(recv_value-recv_value%10)/10
|
|
recv_value=recv_value-shi*10
|
|
var ge=recv_value
|
|
var return_table={.State=0.0,.Label=0.0,.ReqLabel=0.0,.ReqID=0.0,.Response=0.0}
|
|
return_table.State=wan
|
|
return_table.Label=qian
|
|
return_table.ReqLabel=bai
|
|
return_table.ReqID=shi
|
|
return_table.Response=ge
|
|
return return_table
|
|
}
|
|
#
|
|
#unpack guide message
|
|
#
|
|
function unpack_guide_msg(recv_value){
|
|
#log(id,"I pass value=",recv_value)
|
|
var qian=(recv_value-recv_value%1000)/1000
|
|
recv_value=recv_value-qian*1000
|
|
var bai=(recv_value-recv_value%100)/100
|
|
recv_value=recv_value-bai*100
|
|
var b=recv_value
|
|
var return_table={.Label=0.0,.Bearing=0.0}
|
|
return_table.Label=qian
|
|
if(bai==1){
|
|
b=b*-1.0
|
|
}
|
|
return_table.Bearing=b
|
|
return return_table
|
|
}
|
|
#
|
|
#get the target distance to neighbr nei_id
|
|
#
|
|
function target4label(nei_id){
|
|
var return_val="miss"
|
|
var i=0
|
|
while(i<size(lock_neighbor_id)){
|
|
if(lock_neighbor_id[i]==nei_id){
|
|
return_val=lock_neighbor_dis[i]
|
|
}
|
|
i=i+1
|
|
}
|
|
return return_val
|
|
}
|
|
#
|
|
#calculate LJ vector for neibhor stored in i
|
|
#
|
|
function LJ_vec(i){
|
|
var dis=m_MessageRange[i]
|
|
var ljbearing=m_MessageBearing[i]
|
|
var nei_id=m_messageID[i]
|
|
var target=target4label(nei_id)
|
|
var cDir={.x=0.0,.y=0.0}
|
|
if(target!="miss"){
|
|
cDir=math.vec2.newp(FlockInteraction(dis,target,EPSILON),ljbearing)
|
|
}
|
|
#log(id,"dis=",dis,"target=",target,"label=",nei_id)
|
|
#log("x=",cDir.x,"y=",cDir.y)
|
|
return cDir
|
|
}
|
|
#
|
|
#calculate the motion vector
|
|
#
|
|
function motion_vector(){
|
|
var i=0
|
|
var m_vector={.x=0.0,.y=0.0}
|
|
while(i<m_neighbourCount){
|
|
#calculate and add the motion vector
|
|
m_vector=math.vec2.add(m_vector,LJ_vec(i))
|
|
#log(id,"x=",m_vector.x,"y=",m_vector.y)
|
|
i=i+1
|
|
}
|
|
m_vector=math.vec2.scale(m_vector,1.0/m_neighbourCount)
|
|
#log(id,"fnal=","x=",m_vector.x,"y=",m_vector.y)
|
|
return m_vector
|
|
}
|
|
#
|
|
# starts the neighbors listener
|
|
#
|
|
function start_listen(){
|
|
neighbors.listen("m",
|
|
function(vid,value,rid){
|
|
#store the received message
|
|
var temp_id=rid
|
|
var recv_val=unpackmessage(value)
|
|
Get_DisAndAzi(temp_id)
|
|
#add the received message
|
|
#
|
|
m_MessageState[m_neighbourCount]=i2s(recv_val.State)
|
|
m_MessageLabel[m_neighbourCount]=recv_val.Label
|
|
m_MessageReqLabel[m_neighbourCount]=recv_val.ReqLabel
|
|
m_MessageReqID[m_neighbourCount]=recv_val.ReqID
|
|
m_MessageResponse[m_neighbourCount]=i2r(recv_val.Response)
|
|
m_MessageRange[m_neighbourCount]=m_receivedMessage.Range
|
|
m_MessageBearing[m_neighbourCount]=m_receivedMessage.Bearing
|
|
m_messageID[m_neighbourCount]=rid
|
|
|
|
#log(rid, " is in ", m_MessageState[m_neighbourCount], " ", m_MessageLabel[m_neighbourCount])
|
|
|
|
m_neighbourCount=m_neighbourCount+1
|
|
})
|
|
}
|
|
#
|
|
#Function used to get the station info of the sender of the message
|
|
#
|
|
function Get_DisAndAzi(id){
|
|
neighbors.foreach(
|
|
function(rid, data) {
|
|
if(rid==id){
|
|
m_receivedMessage.Range=data.distance*100.0
|
|
m_receivedMessage.Bearing=data.azimuth
|
|
}
|
|
})
|
|
}
|
|
#
|
|
#Update node info according to neighbour robots
|
|
#
|
|
function UpdateNodeInfo(){
|
|
#Collect informaiton
|
|
#Update information
|
|
var i=0
|
|
|
|
while(i<m_neighbourCount){
|
|
if(m_MessageState[i]=="STATE_JOINED"){
|
|
m_vecNodes[m_MessageLabel[i]].State="ASSIGNED"
|
|
m_vecNodes[m_MessageLabel[i]].StateAge=m_unJoiningLostPeriod
|
|
}
|
|
else if(m_MessageState[i]=="STATE_JOINING"){
|
|
m_vecNodes[m_MessageLabel[i]].State="ASSIGNING"
|
|
m_vecNodes[m_MessageLabel[i]].StateAge=m_unJoiningLostPeriod
|
|
}
|
|
i=i+1
|
|
}
|
|
#Forget old information
|
|
i=0
|
|
while(i<size(m_vecNodes)){
|
|
if((m_vecNodes[i].StateAge>0) and (m_vecNodes[i].State=="ASSIGNING")){
|
|
m_vecNodes[i].StateAge=m_vecNodes[i].StateAge-1
|
|
if(m_vecNodes[i].StateAge==0)
|
|
m_vecNodes[i].State="UNASSIGNED"
|
|
}
|
|
i=i+1
|
|
}
|
|
}
|
|
#
|
|
#Transistion to state free
|
|
#
|
|
function TransitionToFree(){
|
|
UAVSTATE="STATE_FREE"
|
|
m_unWaitCount=m_unLabelSearchWaitTime
|
|
m_selfMessage.State=s2i(UAVSTATE)
|
|
}
|
|
#
|
|
#Transistion to state asking
|
|
#
|
|
function TransitionToAsking(un_label){
|
|
UAVSTATE="STATE_ASKING"
|
|
m_nLabel=un_label
|
|
m_unRequestId=id #don't know why the random numbers are the same, add id to make the ReqID different
|
|
m_selfMessage.State=s2i(UAVSTATE)
|
|
m_selfMessage.ReqLabel=m_nLabel
|
|
m_selfMessage.ReqID=m_unRequestId
|
|
|
|
m_unWaitCount=m_unResponseTimeThreshold
|
|
}
|
|
#
|
|
#Transistion to state joining
|
|
#
|
|
function TransitionToJoining(){
|
|
UAVSTATE="STATE_JOINING"
|
|
m_selfMessage.State=s2i(UAVSTATE)
|
|
m_selfMessage.Label=m_nLabel
|
|
m_unWaitCount=m_unJoiningLostPeriod
|
|
}
|
|
#
|
|
#Transistion to state joined
|
|
#
|
|
function TransitionToJoined(){
|
|
UAVSTATE="STATE_JOINED"
|
|
m_selfMessage.State=s2i(UAVSTATE)
|
|
m_selfMessage.Label=m_nLabel
|
|
m_vecNodes[m_nLabel].State="ASSIGNED"
|
|
|
|
#write statues
|
|
#v_tag.put(m_nLabel, m_lockstig)
|
|
barrier_create()
|
|
barrier_ready()
|
|
|
|
m_navigation.x=0.0
|
|
m_navigation.y=0.0
|
|
uav_moveto(m_navigation.x/100.0, m_navigation.y/100.0, 0.0)
|
|
}
|
|
#
|
|
#Transistion to state Lock, lock the current formation
|
|
#
|
|
function TransitionToLock(){
|
|
UAVSTATE="STATE_LOCK"
|
|
m_selfMessage.State=s2i(UAVSTATE)
|
|
m_selfMessage.Label=m_nLabel
|
|
m_vecNodes[m_nLabel].State="ASSIGNED"
|
|
#record neighbor distance
|
|
lock_neighbor_id={}
|
|
lock_neighbor_dis={}
|
|
var i=0
|
|
while(i<m_neighbourCount){
|
|
lock_neighbor_id[i]=m_messageID[i]
|
|
lock_neighbor_dis[i]=m_MessageRange[i]
|
|
i=i+1
|
|
}
|
|
m_navigation.x=0.0
|
|
m_navigation.y=0.0
|
|
uav_moveto(m_navigation.x, m_navigation.y, 0.0)
|
|
|
|
# prepare to restart a new shape
|
|
old_state = rc_State
|
|
#stop listening
|
|
neighbors.ignore("m")
|
|
}
|
|
#
|
|
# Do free
|
|
#
|
|
function DoFree() {
|
|
m_selfMessage.State=s2i(UAVSTATE)
|
|
|
|
#wait for a while before looking for a Label
|
|
if(m_unWaitCount>0)
|
|
m_unWaitCount=m_unWaitCount-1
|
|
|
|
#find a set of joined robots
|
|
var setJoinedLabels={}
|
|
var setJoinedIndexes={}
|
|
var i=0
|
|
var j=0
|
|
while(i<m_neighbourCount){
|
|
if(m_MessageState[i]=="STATE_JOINED"){
|
|
setJoinedLabels[j]=m_MessageLabel[i]
|
|
setJoinedIndexes[j]=i
|
|
j=j+1
|
|
}
|
|
i=i+1
|
|
}
|
|
|
|
#go through the graph to look for a proper Label
|
|
var unFoundLabel=0
|
|
# var IDofPred=0
|
|
i=1
|
|
while(i<size(m_vecNodes) and (unFoundLabel==0)){
|
|
#if the node is unassigned and the predecessor is insight
|
|
if(m_vecNodes[i].State=="UNASSIGNED" and count(setJoinedLabels,m_vecNodes[i].Pred)==1){
|
|
unFoundLabel=m_vecNodes[i].Label
|
|
# IDofPred=find(m_MessageLabel,m_vecNodes[unFoundLabel].Pred)
|
|
}
|
|
i=i+1
|
|
}
|
|
|
|
if(unFoundLabel>0){
|
|
TransitionToAsking(unFoundLabel)
|
|
return
|
|
}
|
|
|
|
#set message
|
|
m_selfMessage.State=s2i(UAVSTATE)
|
|
|
|
}
|
|
#
|
|
#Do asking
|
|
#
|
|
function DoAsking(){
|
|
#look for response from predecessor
|
|
var i=0
|
|
var psResponse=-1
|
|
while(i<m_neighbourCount and psResponse==-1){
|
|
#the respond robot in joined state
|
|
#the request Label be the same as requesed
|
|
#get a respond
|
|
if(m_MessageState[i]=="STATE_JOINED"){
|
|
#log("received label = ",m_MessageReqLabel[i])
|
|
if(m_MessageReqLabel[i]==m_nLabel)
|
|
if(m_MessageResponse[i]!="REQ_NONE"){
|
|
psResponse=i
|
|
}}
|
|
if(m_MessageState[i]=="STATE_JOINING" and m_MessageLabel[i]==m_nLabel){
|
|
TransitionToFree()
|
|
return
|
|
}
|
|
i=i+1
|
|
}
|
|
#analyse response
|
|
if(psResponse==-1){
|
|
#no response, wait
|
|
|
|
m_unWaitCount=m_unWaitCount-1
|
|
m_selfMessage.State=s2i(UAVSTATE)
|
|
m_selfMessage.ReqLabel=m_nLabel
|
|
m_selfMessage.ReqID=m_unRequestId
|
|
#if(m_unWaitCount==0){
|
|
#TransitionToFree()
|
|
#return
|
|
#}
|
|
}
|
|
else{
|
|
log("respond id=",m_MessageReqID[psResponse])
|
|
if(m_MessageReqID[psResponse]!=m_unRequestId){
|
|
m_vecNodes[m_nLabel].State="ASSIGNING"
|
|
m_vecNodes[m_nLabel].StateAge=m_unJoiningLostPeriod
|
|
TransitionToFree()
|
|
}
|
|
if(m_MessageReqID[psResponse]==m_unRequestId){
|
|
if(m_MessageResponse[psResponse]=="REQ_GRANTED"){
|
|
TransitionToJoining()
|
|
return
|
|
}
|
|
else{
|
|
TransitionToAsking(m_nLabel)
|
|
return
|
|
}
|
|
}
|
|
}
|
|
m_selfMessage.Label=m_nLabel
|
|
|
|
m_navigation.x=0.0
|
|
m_navigation.y=0.0
|
|
uav_moveto(m_navigation.x/100.0, m_navigation.y/100.0, 0.0)
|
|
}
|
|
#
|
|
#Do joining
|
|
#
|
|
function DoJoining(){
|
|
|
|
if(m_gotjoinedparent!=1)
|
|
set_rc_goto()
|
|
else
|
|
gotoWP(TransitionToJoined)
|
|
#pack the communication package
|
|
m_selfMessage.State=s2i(UAVSTATE)
|
|
m_selfMessage.Label=m_nLabel
|
|
}
|
|
|
|
function set_rc_goto() {
|
|
#get information of pred
|
|
var i=0
|
|
var IDofPred=-1
|
|
while(i<m_neighbourCount and IDofPred==-1){
|
|
if(m_MessageLabel[i]==m_vecNodes[m_nLabel].Pred and m_MessageState[i]=="STATE_JOINED")
|
|
IDofPred=i
|
|
i=i+1
|
|
}
|
|
|
|
#found pred
|
|
if(IDofPred!=-1){
|
|
m_unWaitCount=m_unJoiningLostPeriod#if see pred, reset the timer
|
|
|
|
var P2Target=math.vec2.newp(m_vecNodes[m_nLabel].distance,m_vecNodes[m_nLabel].bearing)
|
|
m_cMeToPred.Range=m_MessageRange[IDofPred]#the poition of self to pred in local coordinate
|
|
m_cMeToPred.Bearing=m_MessageBearing[IDofPred]
|
|
|
|
var S2Pred=math.vec2.newp(m_cMeToPred.Range,m_cMeToPred.Bearing)
|
|
var S2Target=math.vec2.add(S2Pred,P2Target)
|
|
|
|
goal = gps_from_vec(math.vec2.newp(math.vec2.length(S2Target)/100.0, math.atan(S2Target.y,S2Target.x)))
|
|
print("Saving GPS goal: ",goal.latitude, goal.longitude)
|
|
uav_storegoal(goal.latitude, goal.longitude, position.altitude)
|
|
m_gotjoinedparent = 1
|
|
}
|
|
}
|
|
#
|
|
#Do joined
|
|
#
|
|
function DoJoined(){
|
|
m_selfMessage.State=s2i(UAVSTATE)
|
|
m_selfMessage.Label=m_nLabel
|
|
|
|
#collect all requests
|
|
var mapRequests={}
|
|
var i=0
|
|
var j=0
|
|
var ReqLabel
|
|
var JoiningLabel
|
|
var seenPred=0
|
|
while(i<m_neighbourCount){
|
|
if(m_MessageState[i]=="STATE_ASKING"){
|
|
ReqLabel=m_MessageReqLabel[i]
|
|
#log("ReqLabel var:",ReqLabel)
|
|
#log("M_vec var",m_vecNodes[ReqLabel].State)
|
|
if(m_vecNodes[ReqLabel].State=="UNASSIGNED")
|
|
if(m_nLabel==m_vecNodes[ReqLabel].Pred){
|
|
#is a request, store the index
|
|
mapRequests[j]=i
|
|
j=j+1
|
|
}
|
|
}
|
|
if(m_MessageState[i]=="STATE_JOINING"){
|
|
JoiningLabel=m_MessageLabel[i]
|
|
if(m_nLabel==m_vecNodes[JoiningLabel].Pred){
|
|
##joining wrt this dot,send the global bearing
|
|
var m_messageForJoining={.Label=JoiningLabel,.Bearing=m_MessageBearing[i]-m_bias}
|
|
}
|
|
}
|
|
|
|
if(m_MessageState[i]=="STATE_JOINING" and repeat_assign==1 and m_MessageLabel[i]==assign_label){
|
|
repeat_assign=0
|
|
}
|
|
|
|
|
|
#if it is the pred
|
|
if((m_MessageState[i]=="STATE_JOINED" or m_MessageState[i]=="STATE_LOCK") and m_MessageLabel[i]==m_vecNodes[m_nLabel].Pred){
|
|
seenPred=1
|
|
m_unWaitCount=m_unJoiningLostPeriod
|
|
}
|
|
i=i+1
|
|
}
|
|
|
|
#get request
|
|
if(size(mapRequests)!=0){
|
|
i=1
|
|
var ReqIndex=0
|
|
while(i<size(mapRequests)){
|
|
#compare the distance
|
|
if(m_MessageRange[mapRequests[ReqIndex]]>m_MessageRange[mapRequests[i]])
|
|
ReqIndex=i
|
|
i=i+1
|
|
}
|
|
if(repeat_assign==0){
|
|
#get the best index, whose ReqLabel and Reqid are
|
|
ReqLabel=m_MessageReqLabel[mapRequests[ReqIndex]]
|
|
var ReqID=m_MessageReqID[mapRequests[ReqIndex]]
|
|
assign_label=ReqLabel
|
|
assign_id=ReqID
|
|
repeat_assign=1
|
|
}
|
|
m_selfMessage.ReqLabel=assign_label
|
|
m_selfMessage.ReqID=assign_id
|
|
m_selfMessage.Response=r2i("REQ_GRANTED")
|
|
#m_vecNodes[ReqLabel].State="ASSIGNING"
|
|
log("Label=",assign_label)
|
|
log("ID=",assign_id)
|
|
m_vecNodes[ReqLabel].StateAge=m_unJoiningLostPeriod
|
|
}
|
|
|
|
#lost pred, wait for some time and transit to free
|
|
if(seenPred==0){
|
|
m_unWaitCount=m_unWaitCount-1
|
|
if(m_unWaitCount==0){
|
|
TransitionToFree()
|
|
return
|
|
}
|
|
}
|
|
|
|
#check if should to transists to lock
|
|
#write statues
|
|
#v_tag.get(m_nLabel)
|
|
#log(v_tag.size(), " of ", ROBOTS, " ready to lock")
|
|
#if(v_tag.size()==ROBOTS){
|
|
# TransitionToLock()
|
|
#}
|
|
barrier_wait(ROBOTS, TransitionToLock, DoJoined, -1)
|
|
}
|
|
#
|
|
#Do Lock
|
|
#
|
|
function DoLock(){
|
|
m_selfMessage.State=s2i(UAVSTATE)
|
|
m_selfMessage.Label=m_nLabel
|
|
m_navigation.x=0.0
|
|
m_navigation.y=0.0
|
|
#calculate motion vection
|
|
if(m_nLabel==0){
|
|
m_navigation.x=0.0 #change value so that robot 0 will move
|
|
m_navigation.y=0.0
|
|
}
|
|
if(m_nLabel!=0){
|
|
m_navigation=motion_vector()
|
|
}
|
|
#move
|
|
uav_moveto(m_navigation.x, m_navigation.y, 0.0)
|
|
|
|
}
|
|
#
|
|
# Executed after takeoff
|
|
#
|
|
function action(){
|
|
|
|
statef=action
|
|
UAVSTATE="STATE_FREE"
|
|
|
|
# reset the graph
|
|
Reset()
|
|
}
|
|
#
|
|
# Executed at init
|
|
#
|
|
function init() {
|
|
#
|
|
# Global parameters for graph formation
|
|
#
|
|
m_unResponseTimeThreshold=10
|
|
m_unLabelSearchWaitTime=10
|
|
m_fTargetDistanceTolerance=100
|
|
m_fTargetAngleTolerance=0.1
|
|
m_unJoiningLostPeriod=100
|
|
|
|
#
|
|
# Join Swarm
|
|
#
|
|
uav_initswarm()
|
|
#v_tag = stigmergy.create(m_lockstig)
|
|
#uav_initstig()
|
|
# go to diff. height since no collision avoidance implemented yet
|
|
#TARGET_ALTITUDE = 20.0 + id * 2.5
|
|
statef=turnedoff
|
|
UAVSTATE = "TURNEDOFF"
|
|
}
|
|
#
|
|
# Executed every step (main loop)
|
|
#
|
|
function step() {
|
|
# listen to potential RC
|
|
uav_rccmd()
|
|
# get the swarm commands
|
|
uav_neicmd()
|
|
# update the vstig (status/net/batt)
|
|
#uav_updatestig()
|
|
|
|
#update the graph
|
|
UpdateNodeInfo()
|
|
#reset message package to be sent
|
|
m_selfMessage={.State=s2i("STATE_FREE"),.Label=0,.ReqLabel=0,.ReqID=0,.Response=r2i("REQ_NONE")}
|
|
#
|
|
# graph state machine
|
|
#
|
|
if(UAVSTATE=="STATE_FREE")
|
|
statef=DoFree
|
|
else if(UAVSTATE=="STATE_ASKING")
|
|
statef=DoAsking
|
|
else if(UAVSTATE=="STATE_JOINING")
|
|
statef=DoJoining
|
|
else if(UAVSTATE=="STATE_JOINED")
|
|
statef=DoJoined
|
|
else if(UAVSTATE=="STATE_LOCK" and old_state!=rc_State)
|
|
statef=action
|
|
else if(UAVSTATE=="STATE_LOCK" and old_state==rc_State)
|
|
statef=DoLock
|
|
|
|
# high level UAV state machine
|
|
statef()
|
|
|
|
log("Current state: ", UAVSTATE, " and label: ", m_nLabel)
|
|
log("Swarm size: ", ROBOTS)
|
|
|
|
#navigation
|
|
#broadcast message
|
|
neighbors.broadcast("m",packmessage(m_selfMessage))
|
|
|
|
#
|
|
#clean message storage
|
|
m_MessageState={}#store received neighbour message
|
|
m_MessageLabel={}#store received neighbour message
|
|
m_MessageReqLabel={}#store received neighbour message
|
|
m_MessageReqID={}#store received neighbour message
|
|
m_MessageResponse={}#store received neighbour message
|
|
m_MessageRange={}#store received neighbour message
|
|
m_MessageBearing={}#store received neighbour message
|
|
m_neighbourCount=0
|
|
|
|
}
|
|
#
|
|
# Executed when reset
|
|
#
|
|
function Reset(){
|
|
m_receivedMessage={.State=s2i("STATE_FREE"),.Label=0,.ReqLabel=0,.ReqID=0,.Response=r2i("REQ_NONE"),.Range=0,.Bearing=0}
|
|
m_selfMessage={.State=s2i("STATE_FREE"),.Label=0,.ReqLabel=0,.ReqID=0,.Response=r2i("REQ_NONE")}
|
|
m_navigation={.x=0,.y=0}
|
|
m_nLabel=-1
|
|
m_messageID={}
|
|
lock_neighbor_id={}
|
|
lock_neighbor_dis={}
|
|
m_unRequestId=0
|
|
m_bias=0
|
|
m_cMeToPred={.Range=0.0,.Bearing=0.0,.GlobalBearing=0.0}
|
|
m_unWaitCount=0
|
|
repeat_assign=0
|
|
assign_label=-1
|
|
assign_id=-1
|
|
m_gotjoinedparent = 0
|
|
|
|
if(rc_State==0){
|
|
log("Loading P graph")
|
|
Read_GraphP()
|
|
} else if(rc_State==1) {
|
|
log("Loading O graph")
|
|
Read_GraphO()
|
|
} else if(rc_State==2) {
|
|
log("Loading L graph")
|
|
Read_GraphL()
|
|
} else if(rc_State==3) {
|
|
log("Loading Y graph")
|
|
Read_GraphY()
|
|
}
|
|
|
|
#start listening
|
|
start_listen()
|
|
#
|
|
#set initial state, only one robot choose [A], while the rest choose [B]
|
|
#
|
|
#[A]The robot used to triger the formation process is defined as joined,
|
|
if(id==ROOT_ID){
|
|
m_nLabel=0
|
|
TransitionToJoined()
|
|
}
|
|
#[B]Other robots are defined as free.
|
|
else{
|
|
TransitionToFree()
|
|
}
|
|
}
|
|
#
|
|
# Executed upon destroy
|
|
#
|
|
function destroy() {
|
|
#clear neighbour message
|
|
m_navigation.x=0.0
|
|
m_navigation.y=0.0
|
|
uav_moveto(m_navigation.x/100.0, m_navigation.y/100.0, 0.0)
|
|
m_vecNodes={}
|
|
#stop listening
|
|
neighbors.ignore("m")
|
|
}
|