Integral algebra for simulating dynamical systems with interval uncertainties

Luc Jaulin



This microsite is associated to the paper
Integral algebra for simulating dynamical systems with interval uncertainties

This work presents an integral algebra and shows how it can be used to simulate a dynamical system with interval uncertainties. These uncertainties, can be either on the initial state vector or on the evolution function. Compare to other techniques used for the guaranteed integration of differential inclusion, the presented approach does not require the use of a fixed-point Picard operator. Three test-cases related to robotics are presented to illustrate the efficiency of the approach.
The Python code for the three test-cases is given below.





Linear system







from codac import *

dt = 0.01
tmax=10
tdomain = Interval(0,tmax)
beginDrawing()
fig_map = VIBesFigMap("Example Linear")
fig_map.set_properties(50, 50, 1200, 600)
fig_map.axis_limits(-3,3,-3,3)
fig_map.smooth_tube_drawing(True)
fig_map.show(1.)


tt = Trajectory(tdomain, TFunction("t"), dt)
u = TubeVector(tdomain, dt, 2)
u[0] = Tube(0*tt,dt) + Interval(-0.02,0.02)
u[1] = Tube(0*tt,dt) + Interval(-0.02,0.02)
tt   = Tube(tt,dt) + 0.0000001*Interval(-1,1)

def TubeSimu(x10,x20):
    L,w=-0.1,2
    v1=x10+(exp(-L*tt)*( cos(w*tt)*u[0]+sin(w*tt)*u[1])).primitive()
    v2=x20+(exp(-L*tt)*(-sin(w*tt)*u[0]+cos(w*tt)*u[1])).primitive()
    x1=exp(L*tt)*(v1*cos(w*tt)-v2*sin(w*tt))
    x2=exp(L*tt)*(v1*sin(w*tt)+v2*cos(w*tt))
    y=TubeVector(tdomain, dt, 2)
    y[0],y[1]=x1,x2
    fig_map.add_tube(y, "y",0,1)


x1=2+Interval(-0.1,0.1)
x2=1+Interval(-0.1,0.1)
TubeSimu(x1,x2)
fig_map.show(1.)
 






Turnstile






from codac import *
import numpy as np

dt = 0.01
tmax=3
tdomain = Interval(0,tmax)

beginDrawing()
fig_map = VIBesFigMap("shape")
fig_map.set_properties(50, 50, 1200, 600)
fig_map.axis_limits(-10,10,-10,10)
fig_map.smooth_tube_drawing(True)
fig_map.show(1.)


u = TubeVector(tdomain, dt, 2)
u1 = Trajectory(tdomain, TFunction("4*exp(-t)"), dt)
u2 = Trajectory(tdomain, TFunction("4*exp(-t)"), dt)
u[0] = Tube(u1,dt) + Interval(-0.01,0.01)
u[1] = Tube(u2,dt) + Interval(-0.01,0.01)
i=1

def TubeSimu(x10,x20,x30):
    global i
    v10=cos(x30)*x10-sin(x30)*x20
    v20=sin(x30)*x10+cos(x30)*x20
    x3=x30+u[1].primitive()
    v1=v10+(u[0]*cos(x3)).primitive()
    v2=v20+(u[0]*sin(x3)).primitive()
    x1= cos(x3)*v1+sin(x3)*v2
    x2=-sin(x3)*v1+cos(x3)*v2
    y=TubeVector(tdomain, dt, 2)
    y[0],y[1]=x1,x2
    fig_map.add_tube(y, "y"+str(i), 0, 1)
    i=i+1


def draw_turnstile(x,colorbody,colorwheel="black[gray]"):
    x1,x2,x3=x[0,0],x[1,0],x[2,0]
    e=0.05
    P=[[0,-e],[2*R+1,-e],[2*R+1,e],[0,e]]
    Pfront=[[A[0]+x1,A[1]+x2] for A in P]
    fig_map.draw_polygon(Polygon(Pfront), colorbody)
    Q0=[[0.3,-0.1],[0.3,0.1],[-0.3,0.1],[-0.3,-0.1]]
    Q=[[A[0]+x1,A[1]+x2] for A in Q0]
    fig_map.draw_polygon(Polygon(Q), colorwheel)
    Q=[[A[0]+x1+2*R+1,A[1]+x2] for A in Q0]
    fig_map.draw_polygon(Polygon(Q),colorwheel)
    fig_map.draw_circle(R*cos(-x3-2),R*sin(-x3-2),0.1,"black[black]")
    fig_map.draw_circle(2*R+1+R*cos(-x3-2),R*sin(-x3-2),0.1,"black[black]")


x0 = np.array([[-2],[2],[1]])
dE1,dE2,dE3=0.01,0.01,0.1
ds=0.01

R=5
fig_map.draw_circle(0,0,R,"blue[#DDFFFF]")
fig_map.draw_circle(2*R+1,0,R,"blue[#DDFFFF]")
fig_map.draw_line([0,2*R+1],[R,R],"blue")
fig_map.draw_line([0,2*R+1],[-R,-R],"blue")


for s1 in np.arange(-dE1,dE1,ds): # We bisect the initial box
    x1=x0[0,0]+Interval(s1,s1+ds)
    for s2 in np.arange(-dE2,dE2,ds):
        x2=x0[1,0]+Interval(s2,s2+ds)
        for s3 in np.arange(-dE3,dE3,ds):
            x3=x0[2,0]+Interval(s3,s3+ds)
            TubeSimu(x1,x2,x3)

x=x0
for t in np.arange(0,tmax,dt):
    def f(x,t):
        x1,x2,x3=x[0,0],x[1,0],x[2,0]
        u1,u2=4*np.exp(-t),4*np.exp(-t)
        return (np.array([[u1+u2*x2],[-u2*x1],[u2]]))
    fig_map.draw_circle(x[0,0],x[1,0],0.1,"red[red]")
    draw_turnstile(x,"grey[]","grey[]")
    x=x+dt*f(x,t)

draw_turnstile(x0,"black[green]")
draw_turnstile(x,"black[yellow]")
fig_map.show(1.)







Car-trailer






from codac import *
import numpy as np

dt = 0.01
tmax=3
tdomain = Interval(0,tmax)

beginDrawing()
fig_map = VIBesFigMap("shape")
fig_map.set_properties(50, 50, 1200, 600)
fig_map.axis_limits(-5,5,-3,6)
fig_map.smooth_tube_drawing(True)
fig_map.show(1.)


u = TubeVector(tdomain, dt, 2)
u1 = Trajectory(tdomain, TFunction("exp(-t)"), dt)
u2 = Trajectory(tdomain, TFunction("exp(-t)"), dt)
u[0] = Tube(u1,dt) + Interval(-0.01,0.01)
u[1] = Tube(u2,dt) + Interval(-0.01,0.01)
i=1

def TubeSimu(x10,x20,x30,x40,x50):
    global i
    v10=x30-x40
    v1=u[0].primitive()+v10
    x5=u[1].primitive()+x50
    x4=x40 + (x5*sin(v1)).primitive()
    x3 = x4+v1
    x1 = x10+(x5*cos(x3)).primitive()
    x2 = x20+(x5*sin(x3)).primitive()
    y=TubeVector(tdomain, dt, 2)
    y[0],y[1]=x1,x2
    fig_map.add_tube(y, "y"+str(i), 0, 1)
    i=i+1

def move(x1,x2,a,t1=0,t2=0):
    y1=np.cos(a)*x1-np.sin(a)*x2+t1
    y2=np.sin(a)*x1+np.cos(a)*x2+t2
    return [y1,y2]

def draw_cartrailer(x,colorbody,colorwheel="black[gray]"):
    def draw_body(a,x1,x2):
        e=0.05
        P=[[1,e],[e,e],[e,0.9],[-e,0.9],[-e,-0.9],[e,-0.9],[e,-e],[1,-e],[1,e]]
        Pfront=[move(A[0],A[1],a,x1,x2) for A in P]
        fig_map.draw_polygon(Polygon(Pfront), colorbody)
        Q0=[[0.3,-0.1],[0.3,0.1],[-0.3,0.1],[-0.3,-0.1]]
        Q=[move(A[0],A[1],0,0,1) for A in Q0]
        Q=[move(A[0],A[1],a,x1,x2) for A in Q]
        fig_map.draw_polygon(Polygon(Q), colorwheel)
        Q=[move(A[0],A[1],0,0,-1) for A in Q0]
        Q=[move(A[0],A[1],a,x1,x2) for A in Q]
        fig_map.draw_polygon(Polygon(Q),colorwheel)
    x1,x2,x3,x4=x[0,0],x[1,0],x[2,0],x[3,0]
    draw_body(x3,x1,x2)
    fig_map.draw_circle(x1+np.cos(x3),x2+np.sin(x3),0.2,colorbody)
    z1=-np.cos(x4)+x1
    z2=-np.sin(x4)+x2
    draw_body(x4,z1,z2)


x0 = np.array([[0],[0],[1],[1.5],[1]])  #(x,y,heading_front,heading_back,speed_front
dE1,dE2,dE3,dE4,dE5=0.001,0.001,0.2,0.01,0.001
ds=0.01

for s1 in np.arange(-dE1,dE1,ds): # We bisect the initial box
    x1=x0[0,0]+Interval(s1,s1+ds)
    for s2 in np.arange(-dE2,dE2,ds):
        x2=x0[1,0]+Interval(s2,s2+ds)
        for s3 in np.arange(-dE3,dE3,ds):
            x3=x0[2,0]+Interval(s3,s3+ds)
            for s4 in np.arange(-dE4,dE4,ds):
                x4=x0[3,0]+Interval(s4,s4+ds)
                for s5 in np.arange(-dE5,dE5,ds):
                    x5=x0[4,0]+Interval(s5,s5+ds)
                    TubeSimu(x1,x2,x3,x4,x5)

x=x0
for t in np.arange(0,tmax,dt):
    def f(x,t):
        x1,x2,x3,x4,x5=x[0,0],x[1,0],x[2,0],x[3,0],x[4,0]
        u1,u2=np.exp(-t),np.exp(-t)
        return (np.array([[x5*np.cos(x3)],[x5*np.sin(x3)],[u1+x5*np.sin(x3-x4)],[x5*np.sin(x3-x4)],[u2]]))
    def draw_center(x):
        xc,yc=move(0,0,x[2,0],x[0,0],x[1,0])
        fig_map.draw_circle(xc,yc,0.01,"red[red]")
    draw_center(x)
    draw_cartrailer(x,"grey[]","grey[]")
    x=x+dt*f(x,t)
    draw_center(x)

draw_cartrailer(x0,"black[green]")
draw_cartrailer(x,"black[yellow]")
fig_map.show(1.)




Hovercraft







from codac import *
import numpy as np

dt = 0.01
tmax=3
tdomain = Interval(0,tmax)


beginDrawing()
fig_map = VIBesFigMap("shape")
fig_map.set_properties(50, 50, 1200, 600)
fig_map.axis_limits(-2,8,-2,9)
fig_map.smooth_tube_drawing(True)
fig_map.show(1.)


u = TubeVector(tdomain, dt, 2)
u1 = Trajectory(tdomain, TFunction("exp(-t)"), dt)
u2 = Trajectory(tdomain, TFunction("exp(-t)"), dt)
du=0.01
u[0] = Tube(u1,dt) + Interval(-du,du)
u[1] = Tube(u2,dt) + Interval(-du,du)
i=1

def TubeSimu(x10,x20,v10,v20,psi0,w0):
    global i
    w=w0+u[1].primitive()
    psi=psi0+w.primitive()
    a10=cos(psi0)*v10-sin(psi0)*v20
    a20=sin(psi0)*v10+cos(psi0)*v20
    a1=a10+(u[0]*cos(psi)).primitive()
    a2=a20+(u[0]*sin(psi)).primitive()
    v1=cos(psi)*a1+sin(psi)*a2
    v2=-sin(psi)*a1+cos(psi)*a2
    x1 = x10+(cos(psi)*v1-sin(psi)*v2).primitive()
    x2 = x20+(sin(psi)*v1+cos(psi)*v2).primitive()
    y=TubeVector(tdomain, dt, 2)
    y[0],y[1]=x1,x2
    fig_map.add_tube(y, "y"+str(i), 0, 1)
    i=i+1

def move(x1,x2,a,t1=0,t2=0):
    y1=np.cos(a)*x1-np.sin(a)*x2+t1
    y2=np.sin(a)*x1+np.cos(a)*x2+t2
    return [y1,y2]

def draw_hovercraft(x,colorbody,colorblades="black[gray]"):
    def draw_body(a,x1,x2):
        e=0.05
        P=[[1,e],[e,e],[e,1],[-e,1],[-e,-1],[e,-1],[e,-e],[1,-e],[1,e]]
        Pfront=[move(A[0],A[1],a,x1,x2) for A in P]
        fig_map.draw_polygon(Polygon(Pfront), colorbody)
        Q0=[[0,0],[0.1,0.1],[0,0.3],[0,-0.3],[-0.1,-0.1],[0,0.01],[0.2,0],[0,-0.01]]
        Q=[move(A[0],A[1],0,-0.2,1) for A in Q0]
        Q=[move(A[0],A[1],a,x1,x2) for A in Q]
        fig_map.draw_polygon(Polygon(Q), colorblades)
        Q=[move(A[0],A[1],0,-0.2,-1) for A in Q0]
        Q=[move(A[0],A[1],a,x1,x2) for A in Q]
        fig_map.draw_polygon(Polygon(Q),colorblades)
    x1,x2,psi=x[0,0],x[1,0],x[4,0]
    draw_body(psi,x1,x2)
    fig_map.draw_circle(x1+np.cos(psi),x2+np.sin(psi),0.2,colorbody)



x0 = np.array([[0],[0],[2],[0],[1],[0]])  #(x,y,vr1,vr2,psi,w
dE1,dE2,dE3,dE4,dE5,dE6=0.001,0.001,0.001,0.001,0.2,0.001
ds=0.01

for s1 in np.arange(-dE1,dE1,ds): # We bisect the initial box
    x1=x0[0,0]+Interval(s1,s1+ds)
    for s2 in np.arange(-dE2,dE2,ds):
        x2=x0[1,0]+Interval(s2,s2+ds)
        for s3 in np.arange(-dE3,dE3,ds):
            x3=x0[2,0]+Interval(s3,s3+ds)
            for s4 in np.arange(-dE4,dE4,ds):
                x4=x0[3,0]+Interval(s4,s4+ds)
                for s5 in np.arange(-dE5,dE5,ds):
                    x5=x0[4,0]+Interval(s5,s5+ds)
                    for s6 in np.arange(-dE6,dE6,ds):
                        x6=x0[5,0]+Interval(s6,s6+ds)
                        TubeSimu(x1,x2,x3,x4,x5,x6)

x=x0
for t in np.arange(0,tmax,dt):
    def f(x,t):
        x1,x2,v1,v2,psi,w=x[0,0],x[1,0],x[2,0],x[3,0],x[4,0],x[5,0]
        u1,u2=np.exp(-t),np.exp(-t)
        dx1=v1*cos(psi)-v2*sin(psi)
        dx2=v1*sin(psi)+v2*cos(psi)
        return (np.array([[dx1],[dx2],[u1+w*v2],[-w*v1],[w],[u2]]))
    def draw_center(x):
        xc,yc=move(0,0,x[4,0],x[0,0],x[1,0])
        fig_map.draw_circle(xc,yc,0.01,"red[red]")
	 x=x+dt*f(x,t)
    draw_center(x)

draw_hovercraft(x0,"black[green]")
draw_hovercraft(x,"black[yellow]")

fig_map.show(1.)