# # 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=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(i0) 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(i0) m_unWaitCount=m_unWaitCount-1 #find a set of joined robots var setJoinedLabels={} var setJoinedIndexes={} var i=0 var j=0 while(i0){ 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(im_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") }