Artificial repulsive pheromone approach

for ocean exploration

Fabrice Le Bars, Luc Jaulin, Olivier Ménage, Aurélien Ponte



This microsite is associated to the paper
Artificial repulsive pheromone approach for ocean exploration

We propose a swarm robotic approach to construct a time-dependent map of the surface currents of a part a the ocean for a chosen time period. For this purpose, we use several drifting buoys which provide a poor approximation of the displacement of the water masses. Then, we propose to accompany the buoys by a swarm of autonomous boats collecting measurement around to buoys. To avoid collecting data at places that have already been visited few minutes before (which would be of little interest), we propose that our robots release some artificial repulsive pheromones.






A video with 10 robots and 5 buoys






The code for 5 robots and 3 buoys



Click below to see/run/modify the online program :





from roblib import *

def clock_rob():
    global X
    for i in range(nx):
        xi=X[:,i].flatten()
        x1,x2,θ=list(xi)
        xi=xi.reshape(3,1)
        sow(xi)
        gradx,grady=GradV(x1,x2)
        draw_tank(xi,'blue',0.8,1)
        Gi=-array([[gradx],[grady]])
        H = zeros((2,2*(nx-1)))
        k = 0
        for j in range(nx):
            if i != j:
                xj=X[:,j].flatten()
                dp = array([xi[0]-xj[0], xi[1]-xj[1]])
                v = 50*dp/(norm(dp)**3)
                H[0,k],H[1,k] = v[0],v[1]
                k += 1
        Hbar = mean(H,1).reshape(2,1)
        F=Gi+1*Hbar   #Mettre zero si on ne veut pas la répulsion
        #draw_arrow(x1,x2,angle(Gi),20*(0.2+tanh(norm(Gi))),'darkblue',0.5)
        #draw_arrow(x1,x2,angle(Hbar),20*(0.2+tanh(norm(Hbar))),'magenta',0.5)
        draw_arrow(x1,x2,angle(F),20*(0.2+tanh(norm(F))),'black',0.5)
        u = 0.2*sawtooth(angle(F)-θ)
        x1,x2,θ=x1+dt*(cos(θ)+dB0[0,0]),x2+dt*(sin(θ)+dB0[1,0]),θ+dt*u
        X[0,i],X[1,i],X[2,i]=x1,x2,θ


def sow(x):
    global φ
    x1,x2,θ=list(x.flatten())
    p1,p2=int(round(x1-4*cos(θ))),int(round(x2-4*sin(θ)))
    for i in range(-4,5):
        for j in range(-4,5):
            φ[p2-j,p1-i]=max(φ[p2-j,p1-i],exp(0.5*(-i**2-j**2)))

def V(x1,x2):  return (x1-xb)**2+(x2-yb)**2

def GradV(x1,x2):
    GImx,GImy=GIm[1],GIm[0]
    j,i=int(round(x1)),int(round(x2))
    return GImx[i,j],GImy[i,j]

N=100 #size of the world
ax=init_figure(0,N,0,N)
dt =0.05
nb=3 # number of buoys
dB=5*randn(2,nb)
X=1.0*array([[40,60,50,60,40],[60,50,60,40,50],[0,0,0,0,0]]) # 5 robots
#X=1.0*array([[40,60,50,60,40,45,65,55,70,35],[60,50,60,40,50,45,60,55,60,45],[0,0,0,0,0,0,0,0,0,0]]) #10 robots
nx=size(X,1)
X1,X2 = meshgrid(arange(0,N,1),arange(0,N,1))
φ = zeros((N,N))  # pheromones
w0=1/30
R0=10

k=10000
for t in arange(0,500,dt):
    print(t)
    B0=array([[50],[50]])+R0*array([[cos(t*w0)],[sin(t*w0)]])
    dB0=(R0*w0)*array([[-sin(t*w0)],[cos(t*w0)]])
    dB=dB+0.05*randn(2,nb)
    B=B0+dB
    φ=0.999*φ  # evaporation
    xb=mean(B[0,:])
    yb=mean(B[1,:])
    Im=V(X1,X2)
    Im=(1/np.amax(Im))*Im
    Im=2*Im+φ
    GIm=np.gradient(Im)
    clear(ax)
    for i in range(nb):  ax.scatter(B[0,i],B[1,i], color='red')
    clock_rob()
    ax.imshow(Im, cmap="Greys", interpolation='nearest',alpha=0.4)
    draw_arrow(xb,yb,angle(dB0),10,'red',1)
    k=k+1
    savefig('pherom'+str(k)+'.png')
    pause(0.01)
pause(1)
import os
os.system("ffmpeg -framerate 100 -pattern_type glob -i '*.png'   -c:v libx264 -pix_fmt yuv420p out.mp4")