Beispiel #1
0
		def LQR(self, ztraj, utraj, Q, R, Qf):
			tspan = utraj.get_segment_times()
			dztrajdt = ztraj.derivative(1)
			
			context = self.CreateDefaultContext()
			nZ = context.num_continuous_states()
			nU = self.GetInputPort('u').size()

			sym_system = self.ToSymbolic()
			sym_context = sym_system.CreateDefaultContext()
			prog = MathematicalProgram()
			z = prog.NewIndeterminates(nZ,'z')
			ucon = prog.NewIndeterminates(nU,'u')
			#nY = self.GetOutputPort('z').size()
			#N = np.zeros([nX, nU])
			
			times = ztraj.get_segment_times()
			K = []
			S = []
			
			for t in times:
				# option 1
				z0 = ztraj.value(t).transpose()[0]
				u0 = utraj.value(t).transpose()[0]
				
				sym_context.SetContinuousState(z0+z)
				sym_context.FixInputPort(0, u0+ucon )
				# zdot=f(z,u)==>zhdot=f(zh+z0,uh+u0)-z0dot
				f = sym_system.EvalTimeDerivatives(sym_context).CopyToVector() # - dztrajdt.value(t).transpose()
				
				mapping = dict(zip(z, z0))
				mapping.update(dict(zip(ucon, u0)))
				
				A = Evaluate(Jacobian(f, z), mapping)
				B = Evaluate(Jacobian(f, ucon), mapping)
				
				k, s = LinearQuadraticRegulator(A, B, Q, R)
				import pdb; pdb.set_trace()
				
				if(len(K) == 0):
					K = np.ravel(k).reshape(nU*nZ,1) 
					S = np.ravel(s).reshape(nZ*nZ,1) 
				else:
					K = np.hstack( (K, np.ravel(k).reshape(nU*nZ,1)) )
					S = np.hstack( (S, np.ravel(s).reshape(nZ*nZ,1)) )
				
				#
				# option 2
				#context.SetContinuousState(xtraj.value(t) )
				#context.FixInputPort(0, utraj.value(t) )
				#linearized_plant = Linearize(self, context)
				#K.append(LinearQuadraticRegulator(linearized_plant.A(),
                #                    	linearized_plant.B(),
                #                      	Q, R)) #self, context, Q, R)
				

			Kpp = PiecewisePolynomial.FirstOrderHold(times, K)
						
			return Kpp
Beispiel #2
0
		def RegionOfAttraction(self, context, zdotraj, V=None):
			z0 = context.get_continuous_state_vector().CopyToVector()
			if(zdotraj is None):
				zdotraj = 0.0*z0

			# Check that x0 is a "fixed point" (on the trajectory).
			zdot0 = self.EvalTimeDerivatives(context).CopyToVector()
			assert np.allclose(zdot0, zdotraj), "context does not describe a fixed point."   #0*xdot0), 
			
			sym_system = self.ToSymbolic()
			sym_context = sym_system.CreateDefaultContext()

			prog = MathematicalProgram()
			z = prog.NewIndeterminates(sym_context.num_continuous_states(),'z')
			
			# Evaluate the dynamics (in relative coordinates)
			sym_context.SetContinuousState(z0+z)
			#import pdb; pdb.set_trace()
			uinput = self.GetInputPort('u')
			u0 = uinput.EvalBasicVector(context).CopyToVector()
			nU = uinput.size()
			ucon = prog.NewIndeterminates(nU,'u')
			sym_context.FixInputPort(0, u0+ucon )
			f = sym_system.EvalTimeDerivatives(sym_context).CopyToVector()

			mapping = dict(zip(z, z0))
			mapping.update(dict(zip(ucon, u0)))

			if V is None:
				# Solve a Lyapunov equation to find the Lyapunov candidate.
				A = Evaluate(Jacobian(f, z), mapping)
				Q = np.eye(sym_context.num_continuous_states())
				import pdb; pdb.set_trace()
				P = RealContinuousLyapunovEquation(A, Q)
				V = x.dot(P.dot(z))

			Vdot = V.Jacobian(z).dot(f)

			# Check Hessian of Vdot at origin
			H = Evaluate(0.5*Jacobian(Vdot.Jacobian(z),z), mapping)
			assert isPositiveDefinite(-H), "Vdot is not negative definite at the fixed point."

			#V = FixedLyapunovMaximizeLevelSet(prog, z, V, Vdot)
			V = self.FixedLyapunovSearchRho(prog, z, V, Vdot)

			# Put V back into global coordinates
			mapping = dict(zip(z,z-z0))
			mapping.update(dict(zip(ucon, u0)))
			V = V.Substitute(mapping)
			return V
Beispiel #3
0
    def SOS_compute_3(self, K, l_coeff, rho_max=10.):
        prog = MathematicalProgram()
        # fix u and lbda, search for V and rho
        x = prog.NewIndeterminates(2, "x")

        # get lbda from before
        l = np.array([x[1], x[0], 1])
        lbda = l.dot(np.dot(l_coeff, l))

        # rho is decision variable now
        rho = prog.NewContinuousVariables(1, "rho")[0]

        # create lyap V
        s = prog.NewContinuousVariables(4, "s")
        S = np.array([[s[0], s[1]], [s[2], s[3]]])
        V = x.dot(np.dot(S, x))
        Vdot = Jacobian([V], x).dot(self.dynamics_K(x, K))[0]

        prog.AddSosConstraint(V)
        prog.AddSosConstraint(-Vdot - lbda * (rho - V))

        prog.AddLinearCost(-rho)
        prog.AddLinearConstraint(rho <= rho_max)

        prog.Solve()
        rho = prog.GetSolution(rho)
        s = prog.GetSolution(s)
        return s, rho
Beispiel #4
0
    def SOS_compute_2(self, l_coeff, S, rho_max=10.):
        prog = MathematicalProgram()
        # fix V and lbda, searcu for u and rho
        x = prog.NewIndeterminates(2, "x")
        # get lbda from before
        l = np.array([x[1], x[0], 1])
        lbda = l.dot(np.dot(l_coeff, l))

        # Define u
        K = prog.NewContinuousVariables(2, "K")

        # Fixed Lyapunov
        V = x.dot(np.dot(S, x))
        Vdot = Jacobian([V], x).dot(self.dynamics_K(x, K))[0]

        # rho is decision variable now
        rho = prog.NewContinuousVariables(1, "rho")[0]

        prog.AddSosConstraint(-Vdot - lbda * (rho - V))

        prog.AddLinearConstraint(rho <= rho_max)
        prog.AddLinearCost(-rho)
        prog.Solve()
        rho = prog.GetSolution(rho)
        K = prog.GetSolution(K)
        return rho, K
Beispiel #5
0
    def SOS_compute_1(self, S, rho_prev):
        # fix V and rho, search for L and u
        prog = MathematicalProgram()
        x = prog.NewIndeterminates(2, "x")

        # Define u
        K = prog.NewContinuousVariables(2, "K")

        # Fixed Lyapunov
        V = x.dot(np.dot(S, x))
        Vdot = Jacobian([V], x).dot(self.dynamics_K(x, K))[0]

        # Define the Lagrange multipliers.
        (lambda_, constraint) = prog.NewSosPolynomial(Variables(x), 2)
        prog.AddLinearConstraint(K[0] * x[0] <= 2.5)
        prog.AddSosConstraint(-Vdot - lambda_.ToExpression() * (rho_prev - V))

        result = prog.Solve()
        # print(lambda_.ToExpression())
        # print(lambda_.decision_variables())
        lc = [prog.GetSolution(var) for var in lambda_.decision_variables()]
        lbda_coeff = np.ones([3, 3])
        lbda_coeff[0, 0] = lc[0]
        lbda_coeff[0, 1] = lbda_coeff[1, 0] = lc[1]
        lbda_coeff[2, 0] = lbda_coeff[0, 2] = lc[2]
        lbda_coeff[1, 1] = lc[3]
        lbda_coeff[2, 1] = lbda_coeff[1, 2] = lc[4]
        lbda_coeff[2, 2] = lc[5]
        return lbda_coeff
		def my_plot_sublevelset_expression(self, ax, e, x0, vertices=51): #, **kwargs):
			p = Polynomial(e)
			assert p.TotalDegree() == 2

			x = list(e.GetVariables())
			env = {a: 0 for a in x}
			c = e.Evaluate(env)
			e1 = e.Jacobian(x)
			b = Evaluate(e1, env)
			e2 = Jacobian(e1, x)
			A = 0.5*Evaluate(e2, env)
			# simple projection to 2D assuming we want to plot on (x1,x2)
			A = A[0:2,0:2]
			b = b[0:2]*0.0
			c = 0.0
			#Plots the 2D ellipse representing x'Ax + b'x + c <= 1, e.g.
    		#the one sub-level set of a quadratic form.
			H = .5*(A+A.T)
			xmin = np.linalg.solve(-2*H, np.reshape(b, (2, 1)))
			fmin = -xmin.T.dot(H).dot(xmin) + c  # since b = -2*H*xmin
			assert fmin <= 1, "The minimum value is > 1; there is no sub-level set " \
                      "to plot"

			# To plot the contour at f = (x-xmin)'H(x-xmin) + fmin = 1,
			# we make a circle of values y, such that: y'y = 1-fmin,
			th = np.linspace(0, 2*np.pi, vertices)
			Y = np.sqrt(1-fmin)*np.vstack([np.sin(th), np.cos(th)])
			# then choose L'*(x - xmin) = y, where H = LL'.
			L = np.linalg.cholesky(H)
			X = np.tile(xmin, vertices) + np.linalg.inv(np.transpose(L)).dot(Y)

			return ax.fill(X[0, :]+x0[0], X[1, :]+x0[1], "b")
        def LQR(self, xtraj, utraj, Q, R, Qf):
            tspan = utraj.get_segment_times()

            context = self.CreateDefaultContext()
            nX = context.num_continuous_states()
            nU = self.GetInputPort('u').size()

            sym_system = self.ToSymbolic()
            sym_context = sym_system.CreateDefaultContext()
            prog = MathematicalProgram()
            x = prog.NewIndeterminates(nX, 'x')
            ucon = prog.NewIndeterminates(nU, 'u')
            #nY = self.GetOutputPort('x').size()
            #N = np.zeros([nX, nU])

            times = xtraj.get_segment_times()
            K = []

            import pdb
            pdb.set_trace()
            for t in times:
                # option 1
                x0 = xtraj.value(t).transpose()[0]
                u0 = utraj.value(t).transpose()[0]

                sym_context.SetContinuousState(x0 + x)
                sym_context.FixInputPort(0, u0 + ucon)
                f = sym_system.EvalTimeDerivatives(sym_context).CopyToVector()
                A = Evaluate(Jacobian(f, x), dict(zip(x, x0)))
                B = Evaluate(Jacobian(f, ucon), dict(zip(ucon, u0)))
                K.append(LinearQuadraticRegulator(A, B, Q, R))

                # option 2
                #context.SetContinuousState(xtraj.value(t) )
                #context.FixInputPort(0, utraj.value(t) )
                #linearized_plant = Linearize(self, context)
                #K.append(LinearQuadraticRegulator(linearized_plant.A(),
                #                    	linearized_plant.B(),
                #                      	Q, R)) #self, context, Q, R)

            Kpp = PiecewisePolynomial.FirstOrderHold(times, K)

            return Kpp
        def RegionOfAttraction(self, context, V=None):
            x0 = context.get_continuous_state_vector().CopyToVector()

            # Check that x0 is a fixed point.
            xdot0 = self.EvalTimeDerivatives(context).CopyToVector()
            assert np.allclose(
                xdot0, 0 * xdot0), "context does not describe a fixed point."

            import pdb
            pdb.set_trace()
            sym_system = self.ToSymbolic()
            sym_context = sym_system.CreateDefaultContext()

            prog = MathematicalProgram()
            x = prog.NewIndeterminates(sym_context.num_continuous_states(),
                                       'x')

            # Evaluate the dynamics (in relative coordinates)
            sym_context.SetContinuousState(x0 + x)
            f = sym_system.EvalTimeDerivatives(sym_context).CopyToVector()

            if V is None:
                # Solve a Lyapunov equation to find the Lyapunov candidate.
                A = Evaluate(Jacobian(f, x), dict(zip(x, x0)))
                Q = np.eye(sym_context.num_continuous_states())
                import pdb
                pdb.set_trace()
                P = RealContinuousLyapunovEquation(A, Q)
                V = x.dot(P.dot(x))

            Vdot = V.Jacobian(x).dot(f)

            # Check Hessian of Vdot at origin
            H = Evaluate(0.5 * Jacobian(Vdot.Jacobian(x), x), dict(zip(x, x0)))
            assert isPositiveDefinite(
                -H), "Vdot is not negative definite at the fixed point."

            #V = FixedLyapunovMaximizeLevelSet(prog, x, V, Vdot)
            V = self.FixedLyapunovSearchRho(prog, x, V, Vdot)

            # Put V back into global coordinates
            V = V.Substitute(dict(zip(x, x - x0)))
            return V
def RegionOfAttraction(system, context, V=None):
    # TODO(russt): Add python binding for has_only_continuous_state
    # assert(context.has_only_continuous_state())
    # TODO(russt): Handle more general cases.

    x0 = context.get_continuous_state_vector().CopyToVector()
    # Check that x0 is a fixed point.
    xdot0 = system.EvalTimeDerivatives(context).get_vector().CopyToVector()
    #assert np.allclose(xdot0, 0*xdot0), "context does not describe a fixed point."

    sym_system = system.ToSymbolic()
    sym_context = sym_system.CreateDefaultContext()
    
    prog = MathematicalProgram()
    x = prog.NewIndeterminates(sym_context.num_continuous_states(),'x')

    # Evaluate the dynamics (in relative coordinates)
    sym_context.SetContinuousState(x0+x)
    f = sym_system.EvalTimeDerivatives(sym_context).get_vector().CopyToVector()
    
    if V is None:
        # Solve a Lyapunov equation to find the Lyapunov candidate.
        #A = Evaluate(Jacobian(f, x), dict(zip(x, x0)))
        #A = np.array([[0., 1.], [-10.*np.cos(x[0]), -0.1]])
        #A = A.Evaluate(dict(zip(x, x0)))
        A = np.array([[0., 1.], [-10.*np.cos(x0[0]), -0.1]])
        Q = np.eye(sym_context.num_continuous_states())
        P = RealContinuousLyapunovEquation(A, Q)
        V = x.dot(P.dot(x))
    
	#for i in range(len(f)):
    #    f[i] = f[i].Substitute(dict(zip(x,x-x0)))
		
    Vdot = V.Jacobian(x).dot(f)
    
    # Check Hessian of Vdot at origin
    import pdb; pdb.set_trace()
    H = Evaluate(0.5*Jacobian(Vdot.Jacobian(x),x), dict(zip(x, 0*x0)))
    print('H=')
    print(H)
    print('P(Lyapunov)=')
    print(P)
    assert isPositiveDefinite(-H), "Vdot is not negative definite at the fixed point."

    #V = FixedLyapunovMaximizeLevelSet(prog, x, V, Vdot)
    V = FixedLyapunovSearchRho(prog, x, V, Vdot)
    
    # Put V back into global coordinates
    V = V.Substitute(dict(zip(x,x-x0)))
    
    return V
		def Cdre_CL(self, t, S, Q, Rinv, xtraj, utraj, x, ucon, K):
			x0 = xtraj.value(t).transpose()[0]
			u0 = utraj.value(t).transpose()[0]
			x0d = xtraj.derivative(1).value(t).transpose()[0]
			Kf = K.value(t).reshape(self.nU, self.nX)
						
			zero_map = dict(zip(x,np.zeros(self.nX)))
			f_Lcl    = self.EvalClosedLoopDynamics(x, ucon, x0, u0, x0d, Kf, order=1) # linearization CL
			Af       = Evaluate(Jacobian(f_Lcl, x), zero_map) # because this is rel. coord.
					
			s1 = S.reshape(self.nX, self.nX) # comes in as vector, switch to matrix
			S1dot = -(Af.transpose().dot(s1) + s1.dot(Af) + Q)

			return S1dot.ravel() # return as vector
Beispiel #11
0
def SOS_traj_optim(S, rho_guess):
    # S provides the initial V guess
    # STEP 1: search for L and u with fixed V and p
    mp1 = MathematicalProgram()
    x = mp1.NewIndeterminates(3, "x")
    V = x.dot(np.dot(S, x))
    print(S)
    # Define the Lagrange multipliers.
    (lambda_, constraint) = mp1.NewSosPolynomial(Variables(x), 4)
    xd = mp1.NewFreePolynomial(Variables(x), 2)
    yd = mp1.NewFreePolynomial(Variables(x), 2)
    thetd = mp1.NewFreePolynomial(Variables(x), 2)
    u = np.vstack((xd, yd))
    u = np.vstack((u, thetd))
    Vdot = Jacobian([V], x).dot(plant(x, u))[0]
    mp1.AddSosConstraint(-Vdot + lambda_.ToExpression() * (V - rho_guess))
    result = mp1.Solve()
    # print(type(lambda_).__dict__.keys())
    print(type(lambda_.decision_variables()).__dict__.keys())
    L = [mp1.GetSolution(var) for var in lambda_.decision_variables()]
    # print(lambda_.monomial_to_coefficient_map())
    return L, u
		def RegionOfAttraction(self, xtraj, utraj, V=None):
			# Construct a polynomial V that contains all monomials with s,c,thetadot up to degree 2.
			#deg_V = 2
			do_normalization = False
			do_balancing     = False #True
			do_use_Slti      = True
			# Construct a polynomial L representing the "Lagrange multiplier".
			deg_L = 4
			taylor_order = 3
			Q  = 10.0*np.eye(self.nX)
			R  = 1.0*np.eye(self.nU)
			Qf = 1.0*np.eye(self.nX)
			rho_f = 1.0
			xdotraj = xtraj.derivative(1)
			# set some constraints on inputs
			#context.SetContinuousState(xtraj.value(xtraj.end_time()))
			#context.FixInputPort(0, utraj.value(utraj.end_time()))

			#x0 = context.get_continuous_state_vector().CopyToVector()
			#if(xdotraj is None):
			#	xdotraj = xtraj.Derivative(1)
			
			# Check that x0 is a "fixed point" (on the trajectory).
			#xdot0 = self.EvalTimeDerivatives(context).CopyToVector()
			#assert np.allclose(xdot0, xdotraj), "context does not describe valid path."   #0*xdot0), 
			
			prog = MathematicalProgram()
			x = prog.NewIndeterminates(self.nX, 'x')
			ucon = prog.NewIndeterminates(self.nU, 'u')
			#sym_system = self.ToSymbolic()
			#sym_context = sym_system.CreateDefaultContext()
			#sym_context.SetContinuousState(x)
			#sym_context.FixInputPort(0, ucon )
			#f = sym_system.EvalTimeDerivativesTaylor(sym_context).CopyToVector() 
						
			times = xtraj.get_segment_times()
			all_V   = [] #might be transformed
			all_Vd  = [] #might be transformed
			all_Vd2 = [] 
			all_fcl = [] #might be transformed
			all_T   = [] #might be transformed
			all_x0  = [] #might be transformed
			sumV = 0.0
			zero_map = dict(zip(x,np.zeros(self.nX)))
			if(do_use_Slti):
				# get the final ROA to be the initial condition (of t=end) of the S from Ricatti)
				for tf in [times[-1]]:
					#tf = times[-1]
					xf = xtraj.value(tf).transpose()[0]
					xdf = xdotraj.value(tf).transpose()[0]
					uf = utraj.value(tf).transpose()[0]
					Af, Bf = self.PlantDerivatives(xf, uf) #0.0*uf)
					Kf, __ = LinearQuadraticRegulator(Af, Bf, Q, R)
					# get a polynomial representation of f_closedloop, xdot = f_cl(x)
					# where x is actually in rel. coord.
					f_Lcl   = self.EvalClosedLoopDynamics(x, ucon, xf, uf, xdf, Kf, order=1) # linearization CL
					Af     = Evaluate(Jacobian(f_Lcl, x), zero_map) # because this is rel. coord.
					Qf 	   = RealContinuousLyapunovEquation(Af, Q)
					f_cl   = self.EvalClosedLoopDynamics(x, ucon, xf, uf, xdf, Kf, order=taylor_order) # for dynamics CL
					# make sure Lyapunov candidate is pd
					if (self.isPositiveDefinite(Qf)==False):
						assert False, '******\nQf is not PD for t=%f\n******' %(tf)
					Vf = (x-xf).transpose().dot(Qf.dot((x-xf)))

					#import pdb; pdb.set_trace()
					if(do_normalization):
						#coeffs = Polynomial(Vf).monomial_to_coefficient_map().values()
						#sumV = 0.
						#for coeff in coeffs:
						#	sumV = sumV + np.abs(coeff.Evaluate())
						sumV = Vf.Evaluate(dict(zip(x, xf+np.ones(self.nX)))) #do: V(1,1,...)=1
						Vf = Vf / sumV  #normalize coefficient sum to one
						Qf = Qf / sumV

					Vfdot = Vf.Jacobian(x).dot(f_cl) # we're just doing the static final point to get Rho_f
					#H = Evaluate(0.5*Jacobian(Vfdot.Jacobian(x),x), zero_map)
					#if (self.isPositiveDefinite(-H)==False):
					#	assert False, '******\nVdot is not ND at the end point, for t=%f\n******' %(tf)

					if(do_balancing):
						#import pdb; pdb.set_trace()
						S1 = Evaluate(0.5*Jacobian(Vf.Jacobian(x),x), zero_map)
						S2 = Evaluate(0.5*Jacobian(Vfdot.Jacobian(x),x), zero_map)
						T = self.balanceQuadraticForm(S1, S2)
						balanced_x = T.dot(x)
						balance_map = dict(zip(x, balanced_x))
						Vf = Vf.Substitute(balance_map)
						Vfdot = Vfdot.Substitute(balance_map)
						for i in range(len(f_cl)):
							f_cl[i] = f_cl[i].Substitute(balance_map)
						xf = np.linalg.inv(T).dot(xf) #the new coordinates of the equilibrium point

					rhomin = 0.0
					rhomax = 1.0

					#import pdb; pdb.set_trace()
					#deg_L = Polynomial(Vfdot).TotalDegree()
					# First bracket the solution
					while self.CheckLevelSet(x, xf, Vf, Vfdot, rhomax, multiplier_degree=deg_L) > 0:
						rhomin = rhomax
						rhomax = 1.2*rhomax

					#print('Rho_max = %f' %(rhomax))
					tolerance = 1e-4
					slack = -1.0
					while rhomax - rhomin > tolerance:
						rho_f = (rhomin + rhomax)/2
						slack = self.CheckLevelSet(x, xf, Vf, Vfdot, rho_f, multiplier_degree=deg_L)
						if  slack >= 0:
							rhomin = rho_f
						else:
							rhomax = rho_f

					rho_f = (rhomin + rhomax)/2
					rho_f = rho_f*0.8 # just to be on the safe-side. REMOVE WHEN WORKING
					print('Rho_final(t=%f) = %f; slack=%f' %(tf, rho_f, slack))
					#import pdb; pdb.set_trace()
			    
			#import pdb; pdb.set_trace()
			# end of getting initial conditions
			if V is None:
				# Do optimization to find the Lyapunov candidate.
				#print('******\nRunning SOS to find Lyapunov function ...') 
				#V, Vdot = self.findLyapunovFunctionSOS(xtraj, utraj, deg_V, deg_L)
				# or Do tvlqr to get S
				print('******\nRunning TVLQR ...')
				K, S  = self.TVLQR(xtraj, utraj, Q, R, Qf) 
				#S0 = S.value(times[-1]).reshape(self.nX, self.nX)
				#print(Polynomial(x.dot(S0.dot(x))).RemoveTermsWithSmallCoefficients(1e-6))
				print('Done\n******')
				for t in times:
					x0 = xtraj.value(t).transpose()[0]
					xd0 = xdotraj.value(t).transpose()[0]
					u0 = utraj.value(t).transpose()[0]
					K0 = K.value(t).reshape(self.nU, self.nX)
					S0 = S.value(t).reshape(self.nX, self.nX)
					S0d = S.derivative(1).value(t).reshape(self.nX, self.nX) # Sdot
					# make sure Lyapunov candidate is pd
					if (self.isPositiveDefinite(S0)==False):
						assert False, '******\nS is not PD for t=%f\n******' %(t)
					# for debugging
					#S0 = np.eye(self.nX)
					#V = x.dot(S0.dot(x))
					V = (x-x0).transpose().dot(S0.dot((x-x0)))
					# normalization of the lyapunov function
					if(do_normalization):
						#coeffs = Polynomial(V).monomial_to_coefficient_map().values()
						#sumV = 0.
						#for coeff in coeffs:
						#	sumV = sumV + np.abs(coeff.Evaluate())
						#sumV = V.Evaluate(dict(zip(x, x0+np.ones(self.nX)))) #do: V(1,1,...)=1
						V = V / sumV  #normalize coefficient sum to one
					# get a polynomial representation of f_closedloop, xdot = f_cl(x)
					f_cl = self.EvalClosedLoopDynamics(x, ucon, x0, u0, xd0, K0, order=taylor_order)
					#import pdb; pdb.set_trace()
					# vdot = x'*Sdot*x + dV/dx*fcl_poly
					#Vdot = (x.transpose().dot(S0d)).dot(x) + V.Jacobian(x).dot(f_cl(xbar)) 
					Vdot = ((x-x0).transpose().dot(S0d)).dot((x-x0)) + V.Jacobian(x).dot(f_cl) 
					#deg_L = np.max([Polynomial(Vdot).TotalDegree(), deg_L])
					if(do_balancing):
						#import pdb; pdb.set_trace()
						S1 = Evaluate(0.5*Jacobian(V.Jacobian(x),x), zero_map)
						S2 = Evaluate(0.5*Jacobian(Vdot.Jacobian(x),x), zero_map)
						T = self.balanceQuadraticForm(S1, S2)
						balanced_x = T.dot(x)
						balance_map = dict(zip(x, balanced_x))
						V = V.Substitute(balance_map)
						Vdot = Vdot.Substitute(balance_map)
						for i in range(len(f_cl)):
							f_cl[i] = f_cl[i].Substitute(balance_map)
						x0 = np.linalg.inv(T).dot(x0) #the new coordinates of the equilibrium point
					else:
						T = np.eye(self.nX)
					
					# store it for later use
					all_V.append(V)
					all_fcl.append(f_cl)
					all_Vd.append(Vdot)
					all_T.append(T)
					all_x0.append(x0)
			
			for i in range(len(times)-1):
				xd0 = xdotraj.value(times[i]).transpose()[0]
				Vdot = (all_V[i+1]-all_V[i])/(times[i+1]-times[i]) + all_V[i].Jacobian(x).dot(all_fcl[i]) 
				all_Vd2.append(Vdot)
			#import pdb; pdb.set_trace()
			#rho_f = 1.0
			# time-varying PolynomialLyapunovFunction who's one-level set defines the verified invariant region
			V = self.TimeVaryingLyapunovSearchRho(x, all_V, all_Vd, all_T, times, xtraj, utraj, rho_f, \
												  multiplier_degree=deg_L)
			# Check Hessian of Vdot at origin
			#H = Evaluate(0.5*Jacobian(Vdot.Jacobian(x),x), dict(zip(x, x0)))
			#assert isPositiveDefinite(-H), "Vdot is not negative definite at the fixed point."
			return V
Beispiel #13
0
import math

from pydrake.all import Jacobian, MathematicalProgram, Solve


def dynamics(x):
    return -x + x**3


prog = MathematicalProgram()
x = prog.NewIndeterminates(1, "x")
rho = prog.NewContinuousVariables(1, "rho")[0]

# Define the Lyapunov function.
V = x.dot(x)
Vdot = Jacobian([V], x).dot(dynamics(x))[0]

# Define the Lagrange multiplier.
lambda_ = prog.NewContinuousVariables(1, "lambda")[0]
prog.AddConstraint(lambda_ >= 0)

prog.AddSosConstraint((V - rho) * x.dot(x) - lambda_ * Vdot)
prog.AddLinearCost(-rho)

result = Solve(prog)

assert result.is_success()

print("Verified that " + str(V) + " < " + str(result.GetSolution(rho)) +
      " is in the region of attraction.")
	# To plot the contour at f = (x-xmin)'H(x-xmin) + fmin = 1,
	# we make a circle of values y, such that: y'y = 1-fmin,
	th = np.linspace(0, 2*np.pi, vertices)
	Y = np.sqrt(1-fmin)*np.vstack([np.sin(th), np.cos(th)])
	# then choose L'*(x - xmin) = y, where H = LL'.
	L = np.linalg.cholesky(H)
	X = np.tile(xmin, vertices) + np.linalg.inv(np.transpose(L)).dot(Y)

	return ax.fill(X[0, :]+x0[0], X[1, :]+x0[1], color=color)
		
prog = MathematicalProgram()
x    = prog.NewIndeterminates(2, 'x')  
V1   = prog.NewSosPolynomial(Variables(x), 2)[0].ToExpression()
V2   = prog.NewSosPolynomial(Variables(x), 2)[0].ToExpression()

a = 0.5*Jacobian(V1.Jacobian(x),x) 
b = 0.5*Jacobian(V2.Jacobian(x),x) 

pxi = np.array([[-0.5,-0.5], [-0.5, 0.5], [0.5,0.5], [0.5,-0.5]])
for pt in pxi:
	prog.AddConstraint( pt.T.dot(a).dot(pt) <= 1.0)
	prog.AddConstraint( pt.T.dot(b).dot(pt) <= 1.0)
pxi = np.array([[0.0, 1.0] ])
prog.AddConstraint( pxi[-1].T.dot(b).dot(pxi[-1]) <= 1.0)

prog.AddMaximizeLogDeterminantSymmetricMatrixCost(a)
prog.AddMaximizeLogDeterminantSymmetricMatrixCost(b)

result = Solve(prog)
assert(result.is_success())
V1 = result.GetSolution(V1)