Пример #1
0
def lqr(A, B, Q, R):
    """
    Solve the continuous time LQR controller for a continuous time system.

    A and B are system matrices, describing the systems dynamics:
     dx/dt = A x + B u

    The controller minimizes the infinite horizon quadratic cost function:
     cost = integral (x.T*Q*x + u.T*R*u) dt

    where Q is a positive semidefinite matrix, and R is positive definite matrix.

    Returns K, X, eigVals:
    Returns gain the optimal gain K, the solution matrix X, and the closed loop system eigenvalues.
    The optimal input is then computed as:
     input: u = -K*x
    """
    # ref Bertsekas, p.151

    # first, try to solve the ricatti equation
    X = np.matrix(sp_linalg.solve_continuous_are(A, B, Q, R))
    # compute the LQR gain
    K = np.matrix(sp_linalg.inv(R) * (B.T * X))
    eigVals, eigVecs = sp_linalg.eig(A - B * K)
    return K, X, eigVals
Пример #2
0
    def __init__(self, settings):
        # add specific private settings
        settings.update(input_order=0)
        settings.update(ouput_dim=1)
        settings.update(input_type='system_state')

        pm.Controller.__init__(self, settings)

        eq_state = calc_equilibrium(settings)
        # pole placement
        parameter = [st.m0, st.m1, st.m2, st.l1, st.l2, st.g, self._settings["d0"], st.d1, st.d2]
        self.A = symcalc.A_func(list(eq_state), parameter)
        self.B = symcalc.B_func(list(eq_state), parameter)
        self.C = symcalc.C

        # create Q and R matrix
        self.Q = np.diag(self._settings["Q"])
        self.R = np.diag(self._settings["R"])

        # try to solve linear riccati equation
        self.P = solve_continuous_are(self.A, self.B, self.Q, self.R)
        self.K = np.dot(np.dot(np.linalg.inv(self.R), self.B.T), self.P)
        self.V = pm.calc_prefilter(self.A, self.B, self.C, self.K)

        eig = np.linalg.eig(self.A - np.dot(self.B, self.K))

        self._logger.info("equilibrium = " + str(eq_state))
        self._logger.info("Q = " + str(self._settings["Q"]))
        self._logger.info("R = " + str(self._settings["R"]))
        self._logger.info("P = " + str(self.P))
        self._logger.info("K = " + str(self.K))
        self._logger.info("eig = " + str(eig))
        self._logger.info("V = " + str(self.V[0][0]))
 def calculate_controller_params(self, yaw_time_constant=None, store=True, Q=None, r=None):
     if yaw_time_constant is None:
         try:
             yaw_time_constant = YAW_TIMECONSTANT
         except:
             raise()
         
     
     # approximated system modell, linearized, continous calculated (seems to be fine)
     A = A=array([[0, 1,        0],\
                     [0, -1./yaw_time_constant, 0],\
                     [-1, 0,       0]])
     B = array([0, 1, 1])
     
     # weigth matrices for riccati design
     if Q is None:
         Q = diag([1E-1, 1, 0.3])
         r = ones((1,1))*30
     
     #Q = diag([1E-1, 1, 0.3])
     #r = ones((1,1))*1000
     
     # calculating feedback
     P = solve_continuous_are(A,B[:, None],Q,r)
     K = sum(B[None, :] * P, axis=1)/r[0, 0]
     
     if store:
         self.KP = K[0]
         self.KD = K[1]
         self.KI = -K[2]
     print K
     
     return list(K)
Пример #4
0
    def _test_factory(case, dec):
        """Checks if 0 = XA + A'X - XB(R)^{-1} B'X + Q is true"""
        a, b, q, r, knownfailure = case
        if knownfailure:
            pytest.xfail(reason=knownfailure)

        x = solve_continuous_are(a, b, q, r)
        res = x.dot(a) + a.conj().T.dot(x) + q
        out_fact = x.dot(b)
        res -= out_fact.dot(solve(np.atleast_2d(r), out_fact.conj().T))
        assert_array_almost_equal(res, np.zeros_like(res), decimal=dec)
Пример #5
0
    def _test_factory(case, dec):
        """Checks if X = A'XA-(A'XB)(R+B'XB)^-1(B'XA)+Q) is true"""
        a, b, q, r, e, s, knownfailure = case
        if knownfailure:
            pytest.xfail(reason=knownfailure)

        x = solve_continuous_are(a, b, q, r, e, s)
        res = a.conj().T.dot(x.dot(e)) + e.conj().T.dot(x.dot(a)) + q
        out_fact = e.conj().T.dot(x).dot(b) + s
        res -= out_fact.dot(solve(np.atleast_2d(r), out_fact.conj().T))
        assert_array_almost_equal(res, np.zeros_like(res), decimal=dec)
Пример #6
0
def prob5():
	# Write the function find_P
	M, m = 23., 5.
	l = 4.
	q1, q2, q3, q4 = 1., 1., 1., 1.
	r = 10.
	tf = 60
	X0 = np.array([-1, -1, .1, -.2])

	A,B,Q,R = linearized_init(M,m,l,q1,q2,q3,q4,r)
	R_inv = inv(R)
	P = la.solve_continuous_are(A,B,Q,R)
	X,U = my_rickshaw(np.linspace(0,tf,400),X0,A,B,Q,inv(R),P)
Пример #7
0
    def control(self, arm, x_des=None):
        """Generates a control signal to move the 
        arm to the specified target.
            
        arm Arm: the arm model being controlled
        des list: the desired system position
        x_des np.array: desired task-space force, 
                        system goes to self.target if None
        """
        if self.u is None:
            self.u = np.zeros(arm.DOF)

        self.Q = np.zeros((arm.DOF*2, arm.DOF*2))
        self.Q[:arm.DOF, :arm.DOF] = np.eye(arm.DOF) * 1000.0 
        self.R = np.eye(arm.DOF) * 0.001 

        # calculate desired end-effector acceleration
        if x_des is None:
            self.x = arm.x 
            x_des = self.x - self.target 

        self.arm, state = self.copy_arm(arm)
        A, B = self.calc_derivs(state, self.u)

        if self.solve_continuous is True:
            X = sp_linalg.solve_continuous_are(A, B, self.Q, self.R)
            K = np.dot(np.linalg.pinv(self.R), np.dot(B.T, X))
        else: 
            X = sp_linalg.solve_discrete_are(A, B, self.Q, self.R)
            K = np.dot(np.linalg.pinv(self.R + np.dot(B.T, np.dot(X, B))), np.dot(B.T, np.dot(X, A)))

        # transform the command from end-effector space to joint space
        J = self.arm.gen_jacEE()

        u = np.hstack([np.dot(J.T, x_des), arm.dq])

        self.u = -np.dot(K, u)

        if self.write_to_file is True:
            # feed recorders their signals
            self.u_recorder.record(0.0, self.u)
            self.xy_recorder.record(0.0, self.x)
            self.dist_recorder.record(0.0, self.target - self.x)

        # add in any additional signals 
        for addition in self.additions:
            self.u += addition.generate(self.u, arm)

        return self.u
Пример #8
0
def lqr(A,B,Q,R):
    S = linalg.solve_continuous_are(A,B,Q,R)
    K = linalg.inv(R) @ B.transpose() @ S
    return K
Пример #9
0
def talker():
    cmd_publisher = rospy.Publisher('/cmd_drive', cmd_drive, queue_size=200)
    rospy.Subscriber("/IMU", Odometry, ImuCallback)
    rospy.Subscriber("/GPS/fix", NavSatFix, retour_gps)
    rospy.init_node('LQR', anonymous=True)
    r = rospy.Rate(10)  # 10hz
    simul_time = 15  # rospy.get_param('~simulation_time', '10')
    # == Dynamic Model ======================================================

    # == Steady State   ======================================================
    A = get_model_A_matrix()
    B = get_model_B_matrix()

    Vyss = -(k * vit * (A[(0, 1)] * B[(1, 0)] - A[(1, 1)] * B[(0, 0)] - A[
        (0, 1)] * B[(1, 1)] + A[(1, 1)] * B[(0, 1)])) / (A[(0, 0)] * B[
            (1, 0)] - A[(1, 0)] * B[(0, 0)] - A[(0, 0)] * B[(1, 1)] +
                                                         A[(1, 0)] * B[(0, 1)])
    Vpsiss = vit * k
    eyss = 0
    epsiss = -Vyss / vit

    bfss = -(k * vit * (A[(0, 0)] * A[(1, 1)] - A[(0, 1)] * A[
        (1, 0)])) / (A[(0, 0)] * B[(1, 0)] - A[(1, 0)] * B[(0, 0)] -
                     A[(0, 0)] * B[(1, 1)] + A[(1, 0)] * B[(0, 1)])
    brss = -bfss

    xsss = np.array([[Vyss], [Vpsiss], [eyss], [epsiss]])
    usss = np.array([[bfss], [brss]])

    # == LQR control (Gains)   ======================================================

    Q = np.array([[0.0001, 0, 0, 0], [0, 0.0001, 0, 0], [0, 0, 0.0001, 0],
                  [0, 0, 0, 0.0001]])

    R = np.array([[20000, 0], [0, 20000]])

    C = np.array([[1, 0, 0, 0], [0, 1, 0, 0]])

    P = solve_continuous_are(A, B, Q, R)
    #print(P)

    G = np.linalg.inv(R).dot(np.transpose(B)).dot(P)

    #print(G)
    #np.array([[-0.5,4.3e+13],[-0.5,-4.2e+13]])#
    M = pinv(C.dot(pinv(A - B.dot(G))).dot(B))
    #print(M)

    # == Observer  ======================================================

    xhat = np.array([[0], [0], [0], [0]])
    #print(xhat)
    Gammax = 0.01 * eye(4, 4)

    dt = 0.01  #periode d'échantionnage

    Gammaalpha = dt * 0.00001 * eye(4, 4)
    Gammabeta = dt**2 * eye(2, 2) * 0.00001
    Psiref = Psi  #-52*pi/180
    Psipref = 0 * pi / 180
    vyref = 0
    xref = X
    yref = Y

    t0 = rospy.get_time()
    file = open("steerLQR.txt", "w")
    cmd = cmd_drive()
    cmd.linear_speed = vit
    while not rospy.is_shutdown():
        print(rospy.get_time() - t0)

        ey = -sin(Psiref) * (X - xref) + cos(Psiref) * (Y - yref)
        epsi = (Psi - Psiref)  # par rapport au nord magntiquae
        #vy=-Xp*sin(Psi)+Yp*cos(Psi)
        #print(epsi*180/pi,ey)
        vy = xhat[0, 0]
        x = np.array([[vy], [Psip], [ey], [epsi]])
        yd = np.array([[vyref], [Psipref]])

        y = C.dot(x)
        #print('u',u)
        u = M.dot(yd) - G.dot(x)

        xhat, Gammax = kalman(xhat, Gammax, dt * B.dot(u), y, Gammaalpha,
                              Gammabeta,
                              eye(4, 4) + dt * A, C)
        cmd.linear_speed = vit
        cmd.steering_angle_front = u[0, 0]
        cmd.steering_angle_rear = u[1, 0]
        cmd_publisher.publish(cmd)
        #file.write(' '.join((str(rospy.get_time()-t0), str(u[0,0]), str(u[1,0]))))
        print(u)
        print(rospy.get_time() - t0)
        r.sleep()
    file.close()
    print(rospy.get_time() - t0)
Пример #10
0
linear_state_matrix, linear_input_matrix, inputs = \
    kane.linearize(new_method=True, A_and_B=True)
f_A_lin = linear_state_matrix.subs(parameter_dict).subs(equilibrium_dict)
f_B_lin = linear_input_matrix.subs(parameter_dict).subs(equilibrium_dict)
m_mat = mass_matrix.subs(parameter_dict).subs(equilibrium_dict)

A = matrix(m_mat.inv() * f_A_lin).astype(float)
B = matrix(m_mat.inv() * f_B_lin).astype(float)

assert controllable(A, B)

Q = matrix(eye(6))

R = matrix(eye(3))

S = solve_continuous_are(A, B, Q, R)

K = inv(R) * B.T * S

# This is an annoying little issue. We specified the order of things when
# creating the rhs function, but the linearize function returns the F_B
# matrix in the order corresponding to whatever order it finds the joint
# torques. This would also screw things up if we specified a different
# ordering of the coordinates and speeds as the standard kane._q + kane._u

K = K[[0, 2, 1], :]


def controller(x, t):
    return -asarray(dot(K, x)).flatten()
Пример #11
0
    def check_case(self, a, b, q, r):
        """Checks if (A'X + XA - XBR^-1B'X+Q=0) is true"""

        x = solve_continuous_are(a, b, q, r)
        assert_array_almost_equal(
            a.getH()*x + x*a - x*b*inv(r)*b.getH()*x + q, 0.0)
Пример #12
0
'''
If you are confident in the measures, increase
the confidence so that measure_confidence >> 1.
Otherwise, make it << 1. 
'''
measure_confidence = 1

Aext = np.mat('[0 1 0 0; 0 0 0 0; 0 0 0 1; 0 0 0 0]')
Cext = np.mat('[1 0 0 0; 0 0 1 0]')
n = Aext.shape[0]
ny = Cext.shape[0]
G = np.identity(n);
Q = measure_confidence * np.identity(n);
R = np.identity(ny);

P = solve_continuous_are(Aext.T, Cext.T, Q, R)

L = P * Cext.T * R;
  
dt = .1

A = np.identity(n) + dt * (Aext - L * Cext)
B = L * dt
C = Cext

xest_k = np.mat('[0; 0; 0; 0]')

with pymorse.Morse() as morse:

    while True:
        
Пример #13
0
def talker():
	cmd_publisher= rospy.Publisher('cmd_drive', cmd_drive,queue_size=10)
	data_pub = rospy.Publisher('floats', numpy_msg(Floats),queue_size=10)
	rospy.Subscriber("/IMU", Odometry, ImuCallback)
	rospy.Subscriber("/GPS/fix",NavSatFix,retour_gps)
	rospy.init_node('LQR', anonymous=True)
	r = rospy.Rate(200) # 10hz
	simul_time = rospy.get_param('~simulation_time', '10')
# == Dynamic Model ======================================================





# == Steady State   ======================================================

	B=get_model_B_matrix()


# == LQR control (Gains)   ======================================================


	Q=np.array([   [0.0001, 0,0, 0],
                        [0,0.0001, 0, 0],
                        [0,0, 0.0001, 0],
                        [0,0,0, 0.0001]])

	R=np.array([   [2000,0],
                        [0,2000]])



	C=np.array([[1, 0, 0 ,0],
    [0, 1, 0 ,0]])




	#print(M)



# == Observer  ======================================================


	#print(xhat)
	Gammax=0.01*eye(4,4)

	dt=0.01  #periode d'échantionnage

	Gammaalpha=dt*0.00001*eye(4,4)
	Gammabeta=dt**2*eye(2,2)*0.00001



	mat=np.loadtxt('/home/summit/Spido_ws/recorded_files/mat.txt')
	#mat[:,1]=mat[:,1]-mat[0,1]+X
	#mat[:,2]=mat[:,2]-mat[0,2]+Y
	Psiref=mat[0,3]
	Psipref=mat[0,6]
	xref=mat[0,1]
	yref=mat[0,2]
	ey=-sin(Psiref)*(X-xref)+cos(Psiref)*(Y-yref)
	epsi=(Psi-Psiref)
	xhat=np.array([[0],[Psip],[ey],[epsi]])
	#print(mat)
	#mat[:,3]=mat[:,3]-mat[0,3]+Psi
	#coords=mat[:,1:3]
	line = geom.LineString(mat[:,1:3])
	t0=  rospy.get_time()
	#pause = rospy.ServiceProxy('/gazebo/pause_physics', Empty)



	#file = open("steerLQR.txt","w")


	while (rospy.get_time()-t0<=simul_time):
		cmd=cmd_drive()
		#subprocess.check_call("rosservice call /gazebo/pause_physics", shell=True)
		point = geom.Point(X,Y)
		nearest_pt=line.interpolate(line.project(point))
		distance,index = spatial.KDTree(mat[:,1:3]).query(nearest_pt)
		xref=mat[index,1]
		yref=mat[index,2]
		Psiref=mat[index,3]
		k=mat[index,7]
		vyref=mat[index,5]
		Psipref=mat[index,6]
		ey=-sin(Psiref)*(X-xref)+cos(Psiref)*(Y-yref)
		epsi=(Psi-Psiref)
		#vy=-Xp*sin(Psi)+Yp*cos(Psi)
		vy=xhat[0,0]
		x=np.array([[vy],[Psip],[ey],[epsi]])
		yd=np.array([[vyref],[Psipref]])

		y=C.dot(x)
	        #print('u',u)

		A=get_model_A_matrix(k)
		Vyss=-(k*vit*(A[(0,1)]*B[(1,0)] - A[(1,1)]*B[(0,0)] - A[(0,1)]*B[(1,1)] + A[(1,1)]*B[(0,1)]))/(A[(0,0)]*B[(1,0)] - A[(1,0)]*B[(0,0)] - A[(0,0)]*B[(1,1)] +  A[(1,0)]*B[(0,1)])
		Vpsiss=vit*k
		eyss=0;
		epsiss=-Vyss/vit;

		bfss=-(k*vit*(A[(0,0)]*A[(1,1)] - A[(0,1)]*A[(1,0)]))/(A[(0,0)]*B[(1,0)] - A[(1,0)]*B[(0,0)] - A[(0,0)]*B[(1,1)] +  A[(1,0)]*B[(0,1)])
		brss=-bfss;

		xsss=np.array([[Vyss],[Vpsiss],[eyss],[epsiss]])
		usss=np.array([[bfss],[brss]])
		P=solve_continuous_are(A, B, Q, R)
	#print(P)


		G=np.linalg.inv(R).dot(np.transpose(B)).dot(P)
	#print(G)
	#np.array([[-0.5,4.3e+13],[-0.5,-4.2e+13]])#
		M = pinv(C.dot(pinv(A-B.dot(G))).dot(B))

		u=M.dot(yd)-G.dot(x-xsss)+usss
		#u=M.dot(yd)-G.dot(x)
		#print(u)
		xhat,Gammax=kalman(xhat,Gammax,dt*B.dot(u),y,Gammaalpha,Gammabeta,eye(4,4)+dt*A,C)
		#print('xhat',xhat)

		#vy1=-Xp*sin(Psi)+Yp*cos(Psi);# // vy:vitesse latérale expriméé dans le repère véhicule

		#;//-xpref*sin(psiref)+ypref*cos(psiref); // vy:vitesse latérale expriméé dans le repère véhicule
		#subprocess.check_call("rosservice call /gazebo/unpause_physics", shell=True)
		#unpause = rospy.ServiceProxy('/gazebo/unpause_physics', Empty)
		cmd.linear_speed=vit
		cmd.steering_angle_front=u[0,0]
		cmd.steering_angle_rear=u[1,0]
		cmd_publisher.publish(cmd)
		posture = np.array([X,Y,Psi,ey,epsi,vy,Psip,u[0,0],u[1,0]], dtype=np.float32)
                data_pub.publish(posture)
		#file.write(' '.join((str(rospy.get_time()-t0), str(u[0,0]), str(u[1,0]))))
        r.sleep()
	cmd.steering_angle_front=0
	cmd.steering_angle_rear=0
	aa=vit
	while (aa>0):
		cmd=cmd_drive()
		aa=aa-0.1
		if aa<0:
			aa=0
		cmd.linear_speed=aa
		cmd_publisher.publish(cmd)
Пример #14
0
# initial state
x0 = np.array([[0.98], [0], [0.2], [0]])

# size of A and B
n1 = np.size(A,0)
n2 = np.size(B,1)

# Solve the continuous time lqr controller
# to get controller gain 'K'
# J = x'Qx + u'Ru
# A'X + XA - XBR^(-1)B'X + Q = 0
# K = inv(R)B'X
Q = C.T.dot(C)
R = np.eye(n2)
X = np.matrix(lin.solve_continuous_are(A, B, Q, R))
K = -np.matrix(lin.inv(R)*(B.T*X)).getA()

# observability
ob = obsv(A, C)
print "observability =", ob

# controllability
cb = ctrb(A, B)
print "controllability =", cb

# get the observer gain, using pole placement
p = np.array([-13, -12, -11, -10])
fsf1 = sgn.place_poles(A.T, C.T, p)
L = fsf1.gain_matrix.T
Пример #15
0
def solve_lqr(A, B, Q, R):
    P = solve_continuous_are(A, B, Q, R)
    K = np.linalg.inv(R) @ B.T @ P
    #   K,S,E=control.lqr(A,B,Q,R)
    return K
Пример #16
0
def talker():
    cmd_publisher = rospy.Publisher('cmd_drive', cmd_drive, queue_size=10)
    rospy.Subscriber("/IMU", Odometry, ImuCallback)
    rospy.Subscriber("/GPS/fix", NavSatFix, retour_gps)
    rospy.init_node('LQR', anonymous=True)
    r = rospy.Rate(10)  # 10hz
    simul_time = rospy.get_param('~simulation_time', '10')
    # == Dynamic Model ======================================================

    from std_srvs.srv import Empty

    # == Steady State   ======================================================

    B = get_model_B_matrix()

    # == LQR control (Gains)   ======================================================

    Q = np.array([[0.0001, 0, 0, 0], [0, 0.0001, 0, 0], [0, 0, 0.0001, 0],
                  [0, 0, 0, 0.0001]])

    R = np.array([[20000, 0], [0, 20000]])

    C = np.array([[1, 0, 0, 0], [0, 1, 0, 0]])

    #print(M)

    # == Observer  ======================================================

    xhat = np.array([[0], [0], [1.5], [0]])
    #print(xhat)
    Gammax = 0.01 * eye(4, 4)

    dt = 0.01  #periode d'échantionnage

    Gammaalpha = dt * 0.00001 * eye(4, 4)
    Gammabeta = dt**2 * eye(2, 2) * 0.00001
    Psiref = 0 * pi / 180
    Psipref = 0 * pi / 180
    vyref = 0
    mat = np.loadtxt('/home/bachir/spido_ws/src/spido_riding/scripts/mat.txt')
    mat[:, 1] = mat[:, 1] - mat[0, 1] + X
    mat[:, 2] = mat[:, 2] - mat[0, 2] + Y
    mat[:, 3] = mat[:, 3] - mat[0, 0] + Psi
    coords = mat[:, 1:3]
    line = geom.LineString(coords)
    t0 = rospy.get_time()
    #pause = rospy.ServiceProxy('/gazebo/pause_physics', Empty)

    file = open("steerLQR.txt", "w")

    while (rospy.get_time() - t0 <= simul_time):
        cmd = cmd_drive()
        #subprocess.check_call("rosservice call /gazebo/pause_physics", shell=True)
        point = geom.Point(X, Y)
        nearest_pt = line.interpolate(line.project(point))
        distance, index = spatial.KDTree(coords).query(nearest_pt)
        xref = coords[index, 0]
        yref = coords[index, 1]
        Psiref = mat[index, 3]
        ey = -sin(Psiref) * (X - xref) + cos(Psiref) * (Y - yref)
        epsi = (Psi - Psiref)
        #vy=-Xp*sin(Psi)+Yp*cos(Psi)
        vy = xhat[0, 0]
        x = np.array([[vy], [Psip], [ey], [epsi]])
        yd = np.array([[vyref], [Psipref]])

        y = C.dot(x)
        #print('u',u)
        k = mat[index, 7]
        A = get_model_A_matrix(k)
        Vyss = -(k * vit * (A[(0, 1)] * B[(1, 0)] - A[(1, 1)] * B[(0, 0)] - A[
            (0, 1)] * B[(1, 1)] + A[(1, 1)] * B[
                (0, 1)])) / (A[(0, 0)] * B[(1, 0)] - A[(1, 0)] * B[(0, 0)] -
                             A[(0, 0)] * B[(1, 1)] + A[(1, 0)] * B[(0, 1)])
        Vpsiss = vit * k
        eyss = 0
        epsiss = -Vyss / vit

        bfss = -(k * vit * (A[(0, 0)] * A[(1, 1)] - A[(0, 1)] * A[
            (1, 0)])) / (A[(0, 0)] * B[(1, 0)] - A[(1, 0)] * B[(0, 0)] -
                         A[(0, 0)] * B[(1, 1)] + A[(1, 0)] * B[(0, 1)])
        brss = -bfss

        xsss = np.array([[Vyss], [Vpsiss], [eyss], [epsiss]])
        usss = np.array([[bfss], [brss]])
        P = solve_continuous_are(A, B, Q, R)
        #print(P)

        G = np.linalg.inv(R).dot(np.transpose(B)).dot(P)
        #print(G)
        #np.array([[-0.5,4.3e+13],[-0.5,-4.2e+13]])#
        M = pinv(C.dot(pinv(A - B.dot(G))).dot(B))

        u = M.dot(yd) - G.dot(x - xsss) + usss
        xhat, Gammax = kalman(xhat, Gammax, dt * B.dot(u), y, Gammaalpha,
                              Gammabeta,
                              eye(4, 4) + dt * A, C)
        #print('xhat',xhat)

        vy1 = -Xp * sin(Psi) + Yp * cos(Psi)
        # // vy:vitesse latérale expriméé dans le repère véhicule

        #;//-xpref*sin(psiref)+ypref*cos(psiref); // vy:vitesse latérale expriméé dans le repère véhicule
        #subprocess.check_call("rosservice call /gazebo/unpause_physics", shell=True)
        #unpause = rospy.ServiceProxy('/gazebo/unpause_physics', Empty)
        cmd.linear_speed = vit
        cmd.steering_angle_front = u[0, 0]
        cmd.steering_angle_rear = u[1, 0]
        cmd_publisher.publish(cmd)
        file.write(' '.join(
            (str(rospy.get_time() - t0), str(u[0, 0]), str(u[1, 0]))))
        r.sleep()
    #rospy.loginfo("out of the loop")
    file.close()
Пример #17
0
 def run_step(self):
     A = np.matrix([[0, self.v_target * (5. / 18.)], [0, 0]])
     B = np.matrix([[0], [(self.v_target / self.wheelbase) * (5. / 18.)]])
     V = np.matrix(linalg.solve_continuous_are(A, B, self.Q, self.R))
     K = np.matrix(linalg.inv(self.R) * (B.T * V))
     return K
# Q[10:13,10:13] = 1*np.eye(3)

R = 1e0 * np.eye(4)
R[0, ]

Aout = np.zeros((14, 14))
Aout[0:3, 3:6] = np.eye(3)
Aout[3:6, 6:9] = np.eye(3)
Aout[6:9, 10:13] = np.eye(3)
Aout[9, 13] = 1

Bout = np.zeros((14, 4))
Bout[10:14, 0:4] = np.eye(4)

print("A:", Aout, "B:", Bout)
Mout = solve_continuous_are(Aout, Bout, Q, R)
# print("M_out:", Mout)

# #-[2] Linearization and get (K,S) for LQR

# A, B =robobee_plantBS.GetLinearizedDynamics(uf, xf)

# print("A:", A, "B:", B)

# ControllabilityMatrix = np.zeros((15, 4*15))
# for i in range(0,15):
#     if i==0:
#         TestAB = B
#         ControllabilityMatrix= TestAB
#         # print("ControllabilityMatrix:", ControllabilityMatrix)
#     else:
Пример #19
0
	def LQR(v_target, wheelbase, Q, R):
		A = np.matrix([[0, v_target*(5./18.)], [0, 0]])
		B = np.matrix([[0], [(v_target/wheelbase)*(5./18.)]])
		V = np.matrix(linalg.solve_continuous_are(A, B, Q, R))
		K = np.matrix(linalg.inv(R)*(B.T*V))
		return K
def compute_LQR_gain(A, B, Q, R):
    P = sl.solve_continuous_are(A, B, Q, R)
    gain = sl.inv(R) @ B.T @ P
    return gain
Пример #21
0
def lqr(A, B, Q, R):
    X = solve_continuous_are(A, B, Q, R)
    K = inv(R) @ (B.T @ X)
    eigVals, eigVecs = eig(A - B * K)
    return K
Пример #22
0
def sdre():
    while not rospy.is_shutdown():
        global x, y, z, roll, pitch, yaw, vel_rover, goal, goal_body, v_x, v_y, v_z, Rot_body_to_inertial, Rot_inertial_to_body, yaw2, acc_rover, v3, zhold, change_landing, land_flag, bot_no, z_init, t, t_p
        t = timer()
        ####    Global to Body conversion for the goal

        posn.write('%f;' % float(x))
        posn.write('%f;' % float(y))
        posn.write('%f;' % float(z))
        posn.write('%f;' % float(v_x))
        posn.write('%f;' % float(v_y))
        posn.write('%f;' % float(v_z))

        # if land_flag!=[]:
        # if land_flag[bot_no] == 0:
        # goal[2] = z
        # if z>5 and bot_no!=0:
        # goal[0] = goal[0] - 3*cos(yaw2)*(1/(1+10*exp(-(z-5))))
        # goal[1] = goal[1] - 3*sin(yaw2)*(1/(1+10*exp(-(z-5))))

        # if bot_no == 0 and change_landing!=100:
        # goal_body[0] = goal[0]
        # goal_body[1] = goal[1]
        # goal_body[2] = goal[2]
        # else:
        goal[0] = 10 * cos(0.1 * (t - t_p))
        goal[1] = 10 * sin(0.1 * (t - t_p))
        goal[2] = 10 + 0.15 * (t - t_p)
        if goal[2] > 50:
            goal[2] = 50
        vel_rover[0] = -1 * sin(0.1 * (t - t_p))
        vel_rover[1] = 1 * cos(0.1 * (t - t_p))
        vel_rover[2] = 0.15
        if goal[2] >= 50:
            vel_rover[2] = 0
        goal_body[0] = goal[0] - x
        goal_body[1] = goal[1] - y
        goal_body[2] = goal[2] - z

        posn.write('%f;' % float(goal[0]))
        posn.write('%f;' % float(goal[1]))
        posn.write('%f;' % float(goal[2]))
        posn.write('%f;' % float(vel_rover[0]))
        posn.write('%f;' % float(vel_rover[1]))
        posn.write('%f;' % float(vel_rover[2]))
        posn.write('\n')

        print('goal', goal)
        goal_body = np.dot(Rot_inertial_to_body, goal_body.transpose())

        # if (sqrt(goal_body[0]**2 + goal_body[1]**2)>0.6 and change_landing!=100 and land_flag[bot_no]==1) or (detect==0 and bot_no==0 and land_flag[bot_no==1]):
        #     if sqrt(goal[0]**2+goal[1]**2)<z:
        #         goal[2] = sqrt(goal[0]**2+goal[1]**2)

        ####    Weighting Matrices Q R
        # if bot_no == 0:
        # Q = np.array([[((5*goal_body[0])**2)/abs(goal_body[2]+0.0001)+1, 0, 0, 0, 0, 0]
        #    ,[0, abs(150*(0.5+abs(goal_body[2]))*(vel_rover[0]-v_x)/(0.001+0.1*abs(goal_body[0]))), 0, 0, 0, 0]
        #    ,[0, 0, ((5*goal_body[1])**2)/abs(goal_body[2]+0.0001)+1, 0, 0, 0]
        #    ,[0, 0, 0, abs(150*(0.5+abs(goal_body[2]))*(vel_rover[1]-v_y)/(0.001+0.1*abs(goal_body[1]))), 0, 0]
        #    ,[0, 0, 0, 0, 1+(10*goal_body[2]/sqrt(0.01+0.01*(goal_body[0]**2)+0.01*(goal_body[1]**2)))**2, 0]
        #    ,[0, 0, 0, 0, 0, 1/abs(goal_body[2]+0.001)]])

        Q = np.array([
            [((15 * goal_body[0])**2) / abs(goal_body[2] + 0.0001) +
             50 / abs(abs(goal_body[0] + 0.00001) - 1) +
             100 / abs(goal_body[0] + 0.00001), 0, 0, 0, 0, 0, 0],
            [
                0,
                abs(200 * (0.5 + abs(goal_body[2])) * (vel_rover[0] - v_x) /
                    (0.001 + 0.01 * abs(goal_body[0] + 0.00001))), 0, 0, 0, 0,
                0
            ],
            [
                0, 0, ((15 * goal_body[1])**2) / abs(goal_body[2] + 0.0001) +
                50 / abs(abs(goal_body[1] + 0.00001) - 1) +
                100 / abs(goal_body[0] + 0.00001), 0, 0, 0, 0
            ],
            [
                0, 0, 0,
                abs(200 * (0.5 + abs(goal_body[2])) * (vel_rover[1] - v_y) /
                    (0.001 + 0.01 * abs(goal_body[1]))), 0, 0, 0
            ],
            [
                0, 0, 0, 0,
                1 + (10 * goal_body[2] / sqrt(0.01 + 0.01 *
                                              (goal_body[0]**2) + 0.01 *
                                              (goal_body[1]**2)))**2, 0, 0
            ]  #normal
            #,[0, 0, 0, 0, 1+((10*(goal_body[2]*10/z_init)+10*(change_landing))/sqrt(0.01+0.01*(goal_body[0]**2)+0.01*(goal_body[1]**2)))**2, 0, 0]   #alt hold
            ,
            [0, 0, 0, 0, 0, 1 / abs(goal_body[2] + 0.001), 0]  #normal
            #,[0, 0, 0, 0, 0, (1-change_landing+0.0001)/abs((goal_body[2]*10/z_init)+0.001), 0]   #alt hold
            ,
            [
                0, 0, 0, 0, 0, 0,
                0.001 / abs((goal_body[2] * z_init / 10) + 0.001)
            ]
        ])

        R = np.array([
            [800, 0, 0, 0]  #z - accn
            ,
            [0, 75000, 0, 0]  #Pitch
            ,
            [0, 0, 75000, 0]  #Roll
            ,
            [0, 0, 0, 2]
        ])
        # else:
        # Q = np.array([[((5*goal_body[0])**2)/abs(0.05*goal_body[2]**2+0.0001)+1, 0, 0, 0, 0, 0, 0]
        #     ,[0, abs(150*(vel_rover[0]-v_x)/(0.001+0.01*abs(goal_body[0])+0.05*abs(goal_body[2]))), 0, 0, 0, 0, 0]
        #     ,[0, 0, ((5*goal_body[1])**2)/abs(0.05*goal_body[2]**2+0.0001)+1, 0, 0, 0, 0]
        #     ,[0, 0, 0, abs(150*(vel_rover[1]-v_x)/(0.001+0.01*abs(goal_body[1])+0.05*abs(goal_body[2]))), 0, 0, 0]
        #     ,[0, 0, 0, 0, 1+((30*goal_body[2])/sqrt(0.01+0.1*(goal_body[0]**2)+0.1*(goal_body[1]**2)))**2, 0, 0]   #normal
        #     #,[0, 0, 0, 0, 1+((10*goal_body[2]+10*(land))/sqrt(0.01+0.01*(goal_body[0]**2)+0.01*(goal_body[1]**2)))**2, 0, 0]   #alt hold
        #     ,[0, 0, 0, 0, 0, 1/abs(goal_body[2]+0.001), 0]   #normal
        #     #,[0, 0, 0, 0, 0, (1-land+0.0001)/abs(goal_body[2]+0.001), 0]   #alt hold
        #     ,[0, 0, 0, 0, 0, 0, 10/abs(goal_body[2]+0.001)]])
        #
        # R = np.array([[100, 0, 0, 0]    #z - accn
        #             ,[0, 100, 0, 0]   #Pitch
        #             ,[0, 0, 100, 0]   #Roll
        #             ,[0, 0, 0, 500]])

        ####    Calculation for control done in body fixed frame
        ###     d2(e_x)/dt2 = 0-d2(x)/dt2 so all signs inverted
        #if bot_no!=0:
        X = np.array([[goal_body[0]], [vel_rover[0] - v_x], [goal_body[1]],
                      [vel_rover[1] - v_y], [goal_body[2]],
                      [vel_rover[2] - v_z], [yaw2 - yaw]])
        #else:
        #    X = np.array([[goal_body[0]],[vel_rover[0]],[goal_body[1]],[vel_rover[1]],[goal_body[2]],[vel_rover[2]],[yaw2-yaw]])
        B = np.array([[0, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 0], [0, 0, 1, 0],
                      [0, 0, 0, 0], [1, 0, 0, 0], [0, 0, 0, 1]])

        P = la.solve_continuous_are(A, B, Q, R)

        u = np.dot(-np.linalg.inv(R), B.transpose())
        u = np.dot(u, P)
        u = np.dot(u, X)

        u0 = float(u[0])
        u1 = float(u[1])
        u2 = float(u[2])
        u3 = float(u[3])

        ####    Normalizing the received thrust
        u0 = ((acc_rover[2] - u0) * 1.5 + 14.7) / 29.4
        u1 = (acc_rover[0] - u1) / 9.8
        u2 = (u2 - acc_rover[1]) / 9.8
        u3 = v3 - u3

        ####    Restrict rotation angles to 10 deg
        if u0 > 1:
            u0 = 1
        if u0 < 0:
            u0 = 0

        if u1 > 10 * np.pi / 180:
            u1 = 10 * np.pi / 180
        if u1 < -10 * np.pi / 180:
            u1 = -10 * np.pi / 180

        if u2 > 10 * np.pi / 180:
            u2 = 10 * np.pi / 180
        if u2 < -10 * np.pi / 180:
            u2 = -10 * np.pi / 180

        ####    Start descending for small errors
        # if sqrt(goal_body[0]**2+goal_body[1]**2)<0.8 and abs(goal_body[2])<1 and z<1 and abs(goal[2])<0.5 and change_landing!=100:
        #     #change_landing = 100
        #     rospy.loginfo("LAND")
        #     u0 = 0.0
        #     u1 = 0.0
        #     u2 = 0.0
        # if sqrt(goal_body[0]**2+goal_body[1]**2)<0.8 and abs(goal_body[2])<0.2 and z<1 and abs(goal[2])<0.5:
        #     change_landing=100
        # if change_landing==100 and z<1:
        #     armService = rospy.ServiceProxy('drone'+str(bot_no)+'/mavros/cmd/arming', mavros_msgs.srv.CommandBool)
        #     armService(True)
        #     takeoffService = rospy.ServiceProxy('drone'+str(bot_no)+'/mavros/cmd/takeoff', mavros_msgs.srv.CommandTOL)
        #     takeoffService(altitude = 1)

        ####    Convert to quaternions and publish
        quater = tf.transformations.quaternion_from_euler(
            u2, u1, yaw + np.pi / 2)  #0
        msg.header = Header()
        msg.type_mask = 0
        msg.orientation.x = quater[0]
        msg.orientation.y = quater[1]
        msg.orientation.z = quater[2]
        msg.orientation.w = quater[3]
        msg.body_rate.x = 0.0
        msg.body_rate.y = 0.0
        msg.body_rate.z = u3
        msg.thrust = u0

        pub.publish(msg)
        rate = rospy.Rate(50)
        rate.sleep
    print("\n\n1. Set point is not a fixed point")

#-[2] Linearization and get (K,S) for LQR

A, B = robobee_plant.GetLinearizedDynamics(uf, xf)

# print("A:", A, "B:", B)

Q = 1 * np.eye(13)
Q[0:3, 0:3] = 10 * np.eye(3)
Q[10:13, 10:13] = 1 * np.eye(3)

R = np.eye(4)
N = np.zeros((13, 4))

M_lqr = solve_continuous_are(A, B, Q, R)
# print("M_lqr:", M_lqr)
K_py = np.dot(np.dot(np.linalg.inv(R), B.T), M_lqr)
print("K_py", K_py)
# print("K_py size:", K_py.shape)

K_, S_ = LinearQuadraticRegulator(A, B, Q, R)

# print("K_:", K_, "S_:", S_)

ControllabilityMatrix = np.zeros((13, 4 * 13))
for i in range(0, 13):
    if i == 0:
        TestAB = B
        ControllabilityMatrix = TestAB
        # print("ControllabilityMatrix:", ControllabilityMatrix)
Пример #24
0
def solve_ricc_lrcf(A, E, B, C, R=None, S=None, trans=False, options=None):
    """Compute an approximate low-rank solution of a Riccati equation.

    See :func:`pymor.algorithms.riccati.solve_ricc_lrcf` for a general
    description.

    This function uses `scipy.linalg.solve_continuous_are`, which
    is a dense solver.
    Therefore, we assume all |Operators| and |VectorArrays| can be
    converted to |NumPy arrays| using
    :func:`~pymor.algorithms.to_matrix.to_matrix` and
    :func:`~pymor.vectorarrays.interfaces.VectorArrayInterface.to_numpy`.

    Parameters
    ----------
    A
        The |Operator| A.
    E
        The |Operator| E or `None`.
    B
        The operator B as a |VectorArray| from `A.source`.
    C
        The operator C as a |VectorArray| from `A.source`.
    R
        The operator R as a 2D |NumPy array| or `None`.
    S
        The operator S as a |VectorArray| from `A.source` or `None`.
    trans
        Whether the first |Operator| in the Riccati equation is
        transposed.
    options
        The solver options to use (see :func:`ricc_lrcf_solver_options`).

    Returns
    -------
    Z
        Low-rank Cholesky factor of the Riccati equation solution,
        |VectorArray| from `A.source`.
    """

    _solve_ricc_check_args(A, E, B, C, R, S, trans)
    options = _parse_options(options, ricc_lrcf_solver_options(), 'scipy',
                             None, False)
    if options['type'] != 'scipy':
        raise ValueError(
            f"Unexpected Riccati equation solver ({options['type']}).")

    A_source = A.source
    A = to_matrix(A, format='dense')
    E = to_matrix(E, format='dense') if E else None
    B = B.to_numpy().T
    C = C.to_numpy()
    S = S.to_numpy().T if S else None
    if R is None:
        R = np.eye(C.shape[0] if not trans else B.shape[1])
    if not trans:
        if E is not None:
            E = E.T
        X = solve_continuous_are(A.T, C.T, B.dot(B.T), R, E, S)
    else:
        X = solve_continuous_are(A, B, C.T.dot(C), R, E, S)

    return A_source.from_numpy(_chol(X).T)
Пример #25
0
K1 = K1.reshape(n, n) + 1e-14 * np.eye(n)
K2 = K2.reshape(n, n) + 1e-14 * np.eye(n)
Mean1 = Mean1.reshape(n, 1)
Mean2 = Mean2.reshape(n, 1)
# K1 = k1.compute_K(x_obs, x_obs) + 1e-14*np.eye(n)
# K2 = k2.compute_K(x_obs, x_obs) + 1e-14*np.eye(n)
# Mean1 = np.array([0 for i in x_obs]).reshape(n, 1)
# Mean2 = np.array([0 for i in x_obs]).reshape(n, 1)

# Find the euclidean barycenter
meuclid, Keuclid = (Mean1 + Mean2) / 2, (K1 + K2) / 2

# Find the wasserstein barycenter
# Solve.
print('Computing...')
C1 = spa.solve_continuous_are(np.zeros((n, n)), np.linalg.cholesky(K1), K2,
                              np.eye(n))
print('Symdiff C1:', np.sum(np.abs(C1 - C1.T)))
print('Mineig C1:', np.min(np.real(np.linalg.eig(C1)[0])))
iA1 = (np.eye(n) + C1) / 2.0
K_from1 = iA1 @ K1 @ iA1.T
K = K_from1
print('Checking...')
print('L1 norm of FP difference:', np.sum(np.abs(fp_difference(K, K1, K2))))
mw, Kw = (Mean1 + Mean2) / 2, K

# Compare the two barycenters
plot(Mean2, K2, x_obs)
plot(Mean1, K1, x_obs)
plot(mw, Kw, x_obs)
# plot(mw, Kw, x_obs)
Пример #26
0
def Cqp(omega_0, Ap, Dp):
    """Given the free particle Ap and Dp matrices and the frequency of the harmonic oscillator, computes the full covariance matrix."""
    dAqp = Aqp(omega_0, Ap)
    dDqp = Dqp(omega_0, Dp)
    return sp.solve_continuous_are(-dAqp, np.zeros(dAqp.shape), dDqp,
                                   np.eye(dAqp.shape[-1]))
Пример #27
0
# initial state
x0 = np.array([[0.98], [0], [0.2], [0]])

# size of A and B
n1 = np.size(A, 0)
n2 = np.size(B, 1)

# Solve the continuous time lqr controller
# to get controller gain 'K'
# J = x'Qx + u'Ru
# A'X + XA - XBR^(-1)B'X + Q = 0
# K = inv(R)B'X
Q = C.T.dot(C)
R = np.eye(n2)
X = np.matrix(lin.solve_continuous_are(A, B, Q, R))
K = -np.matrix(lin.inv(R) * (B.T * X)).getA()

# observability
ob = obsv(A, C)
print "observability =", ob

# controllability
cb = ctrb(A, B)
print "controllability =", cb

# get the observer gain, using pole placement
p = np.array([-13, -12, -11, -10])
fsf1 = sgn.place_poles(A.T, C.T, p)
L = fsf1.gain_matrix.T
Пример #28
0
    def lqr(self, A, B, Q, R):
        P = np.matrix(sp_linalg.solve_continuous_are(A, B, Q, R)) #solve continous time ricatti equation
        K = np.matrix(sp_linalg.inv(R)*(B.T*P)) #compute the LQR gain
        eigVals, eigVecs = sp_linalg.eig(A-B*K)

        return K, eigVals
Пример #29
0
    np.abs(np.real(linalg.eig(Ac, left=False, right=False,
                              check_finite=False))))
dT = 1 / (2 * evals[-1])
Tsim = (8 / np.min(evals[~np.isclose(evals[np.nonzero(evals)], 0)])
        if np.sum(np.isclose(evals[np.nonzero(evals)], 0)) > 0 else 8)

Ad, Bd, Cd, Dd, dT = signal.cont2discrete((Ac, Bc, Cc, Dc), dT)
dt_sys = LTISystem(Ad, Bd, Cd, dt=dT)
dt_sys.initial_condition = ic

Q = np.eye(Ac.shape[0])
R = np.eye(Bc.shape[1] if len(Bc.shape) > 1 else 1)

Sc = linalg.solve_continuous_are(
    Ac,
    Bc,
    Q,
    R,
)
Kc = linalg.solve(R, Bc.T @ Sc).reshape(1, -1)
ct_ctr = LTISystem(-Kc)

Sd = linalg.solve_discrete_are(
    Ad,
    Bd,
    Q,
    R,
)
Kd = linalg.solve(Bd.T @ Sd @ Bd + R, Bd.T @ Sd @ Ad)
dt_ctr = LTISystem(-Kd, dt=dT)

# Equality of discrete-time equivalent and original continuous-time
Пример #30
0
def continuous_LQR(speed, Q, R, wheelbase=2.995):
    A= np.matrix([[0, speed], [0, 0]])
    B = np.matrix([[0], [(speed/wheelbase)]])
    V = np.matrix(linalg.solve_continuous_are(A, B, Q, R))
    K = np.matrix(linalg.inv(R) * (B.T * V))
    return K
Пример #31
0
import scipy
from scipy import linalg
import numpy as np

print('start')

A = np.array([[-1, 1], [-0.5, -0.5]])
B = np.array([[3, 2], [1, 0]])
Q = np.array([[1, 0], [0, 1]])
R = np.array([[2, 0], [0, 2]])

P = linalg.solve_continuous_are(A, B, Q, R)

print(P)

print('Testing:')

test = np.matmul(A.transpose(), P) + np.matmul(P, A) + Q - np.matmul(
    P, np.matmul(B, np.matmul(np.linalg.inv(R), np.matmul(B.transpose(), P))))

print(test)

print('done')

#print('BR^ -1 B^t = ', np.matmul(B, np.matmul( np.linalg.inv(R), B.transpose())))
#print('PBR^ -1 B^t P = ', np.matmul(P, np.matmul(B, np.matmul( np.linalg.inv(R), np.matmul(B.transpose(), P)))))
print('optimal control: R^ -1 B^t P = ',
      np.matmul(np.linalg.inv(R), np.matmul(B.transpose(), P)))
Пример #32
0
def solve_ricc(A, E=None, B=None, Q=None, C=None, R=None, G=None,
               trans=False, options=None):
    """Find a factor of the solution of a Riccati equation using solve_continuous_are.

    Returns factor :math:`Z` such that :math:`Z Z^T` is approximately
    the solution :math:`X` of a Riccati equation

    .. math::
        A^T X E + E^T X A - E^T X B R^{-1} B^T X E + Q = 0.

    If E in `None`, it is taken to be the identity matrix.
    Q can instead be given as C^T * C. In this case, Q needs to be
    `None`, and C not `None`.
    B * R^{-1} B^T can instead be given by G. In this case, B and R need
    to be `None`, and G not `None`.
    If R and G are `None`, then R is taken to be the identity matrix.
    If trans is `True`, then the dual Riccati equation is solved

    .. math::
        A X E^T + E X A^T - E X C^T R^{-1} C X E^T + Q = 0,

    where Q can be replaced by B * B^T and C^T * R^{-1} * C by G.

    This uses the `scipy.linalg.spla.solve_continuous_are` method.
    Generalized Riccati equation is not supported.
    It can only solve medium-sized dense problems and assumes access to
    the matrix data of all operators.

    Parameters
    ----------
    A
        The |Operator| A.
    B
        The |Operator| B or `None`.
    E
        The |Operator| E or `None`.
    Q
        The |Operator| Q or `None`.
    C
        The |Operator| C or `None`.
    R
        The |Operator| R or `None`.
    G
        The |Operator| G or `None`.
    trans
        If the dual equation needs to be solved.
    options
        The |solver_options| to use (see :func:`ricc_solver_options`).

    Returns
    -------
    Z
        Low-rank factor of the Riccati equation solution,
        |VectorArray| from `A.source`.
    """

    _solve_ricc_check_args(A, E, B, Q, C, R, G, trans)
    options = _parse_options(options, lyap_solver_options(), 'scipy', None, False)
    assert options['type'] == 'scipy'

    if E is not None or G is not None:
        raise NotImplementedError

    import scipy.linalg as spla
    A_mat = to_matrix(A, format='dense')
    B_mat = to_matrix(B, format='dense') if B else None
    C_mat = to_matrix(C, format='dense') if C else None
    Q_mat = to_matrix(Q, format='dense') if Q else None
    R_mat = to_matrix(R, format='dense') if R else None

    if R is None:
        if not trans:
            R_mat = np.eye(B.source.dim)
        else:
            R_mat = np.eye(C.range.dim)
    if not trans:
        if Q is None:
            Q_mat = C_mat.T.dot(C_mat)
        X = spla.solve_continuous_are(A_mat, B_mat, Q_mat, R_mat)
    else:
        if Q is None:
            Q_mat = B_mat.dot(B_mat.T)
        X = spla.solve_continuous_are(A_mat.T, C_mat.T, Q_mat, R_mat)

    Z = chol(X, copy=False)
    Z = A.source.from_numpy(np.array(Z).T)

    return Z
Пример #33
0
    return optcontrol


### Stuff we care about running

if __name__ == '__main__':
    T = round(12 / 0.02)
    env = gym.make('CartPoleContinuous-v0')
    obs = env.reset()
    env.render()
    #initial_state = np.array([0,0,.25,0])
    #env.state = initial_state
    #M,m,l = 1,.1,1
    M, m, l = 1, .1, .5
    A, B, Q, R = linearized_init(M, m, l, 0, 1, 1, 1, .001)
    P = la.solve_continuous_are(A, B.reshape((4, 1)), Q, R)

    tol = 1e-2
    done = False
    for i in range(T):
        if la.norm(obs[1:]) < tol:
            print("Converged in {} iterations".format(i))
            #time.sleep(1)
            env.close()
            break
            # Determine the step size based on our mode
        else:
            z, u = cart(np.arange(i * .02, T, .02), obs, A, B, Q, R, P)
            step = np.array([u[0]])

            # Step in designated direction and update the visual
Пример #34
0
def sdre():
    while not rospy.is_shutdown():
        now = timer()
        global x_r, y_r, detect, x, y, z, roll, pitch, yaw, vel_rover, goal, goal_body, v_x, v_y, v_z, Rot_body_to_inertial, Rot_inertial_to_body
        ####    Global to Body conversion for the goal

        #posn.write('%f;' % float(x))
        #posn.write('%f;' % float(z))
        #posn.write('%f;' % float(x_r))
        #posn.write('%f;' % float(now))
        #posn.write('\n')

        goal_body[0] = goal[0] - x
        goal_body[1] = goal[1] - y
        goal_body[2] = goal[2] - z

        goal_body = np.dot(Rot_inertial_to_body, goal_body.transpose())

        ####    Weighting Matrices Q R
        Q = np.array(
            [[((5 * goal_body[0])**2) / abs(goal_body[2] + 0.0001) + 1, 0, 0,
              0, 0, 0],
             [
                 0,
                 abs(150 * (0.5 + abs(goal_body[2])) * (vel_rover[0] - v_x) /
                     (0.001 + 0.1 * abs(goal_body[0]))), 0, 0, 0, 0
             ],
             [
                 0, 0,
                 ((5 * goal_body[1])**2) / abs(goal_body[2] + 0.0001) + 1, 0,
                 0, 0
             ],
             [
                 0, 0, 0,
                 abs(150 * (0.5 + abs(goal_body[2])) * (vel_rover[1] - v_y) /
                     (0.001 + 0.1 * abs(goal_body[1]))), 0, 0
             ],
             [
                 0, 0, 0, 0,
                 1 + (10 * goal_body[2] / sqrt(0.01 + 0.01 *
                                               (goal_body[0]**2) + 0.01 *
                                               (goal_body[1]**2)))**2, 0
             ], [0, 0, 0, 0, 0, 1 / abs(goal_body[2] + 0.001)]])

        R = np.array([
            [800, 0, 0]  #z - accn
            ,
            [0, 75000, 0]  #Pitch
            ,
            [0, 0, 75000]
        ])  #Roll

        ####    Calculation for control done in body fixed frame
        ###     d2(e_x)/dt2 = 0-d2(x)/dt2 so all signs inverted
        X = np.array([[goal_body[0]], [vel_rover[0] - v_x], [goal_body[1]],
                      [vel_rover[1] - v_y], [goal_body[2]],
                      [vel_rover[2] - v_z]])

        B = np.array([[0, 0, 0], [0, -9.8, 0], [0, 0, 0], [0, 0, 9.8],
                      [0, 0, 0], [-1, 0, 0]])

        P = la.solve_continuous_are(A, B, Q, R)

        u = np.dot(-np.linalg.inv(R), B.transpose())
        u = np.dot(u, P)
        u = np.dot(u, X)

        u0 = float(u[0])
        u1 = float(u[1])
        u2 = float(u[2])

        ####    Normalizing the received thrust
        u0 = (u0 * 1.5 + 14.7) / 29.4

        ####    Restrict rotation angles to 10 deg
        if u0 > 1:
            u0 = 1
        if u0 < 0:
            u0 = 0

        if u1 > 10 * np.pi / 180:
            u1 = 10 * np.pi / 180
        if u1 < -10 * np.pi / 180:
            u1 = -10 * np.pi / 180

        if u2 > 10 * np.pi / 180:
            u2 = 10 * np.pi / 180
        if u2 < -10 * np.pi / 180:
            u2 = -10 * np.pi / 180

        ####    Start descending for small errors
        if sqrt(goal_body[0]**2 + goal_body[1]**2) < 0.8 and abs(
                goal_body[2]) < 1:
            rospy.loginfo("LAND")
            u0 = 0.0
            u1 = 0.0
            u2 = 0.0

        ####    Convert to quaternions and publish
        quater = tf.transformations.quaternion_from_euler(u2, u1, yaw)  #0
        msg.header = Header()
        msg.type_mask = 0
        msg.orientation.x = quater[0]
        msg.orientation.y = quater[1]
        msg.orientation.z = quater[2]
        msg.orientation.w = quater[3]
        msg.body_rate.x = 0.0
        msg.body_rate.y = 0.0
        msg.body_rate.z = 0.0
        msg.thrust = u0

        pub.publish(msg)

        rate = rospy.Rate(100)
        rate.sleep
Пример #35
0
def talker():
    cmd_publisher = rospy.Publisher('cmd_drive', cmd_drive, queue_size=10)
    rospy.Subscriber("/IMU", Odometry, ImuCallback)
    rospy.Subscriber("/GPS/fix", NavSatFix, retour_gps)
    rospy.init_node('LQR', anonymous=True)
    r = rospy.Rate(10)  # 10hz
    simul_time = rospy.get_param('~simulation_time', '10')
    # == Dynamic Model ======================================================

    # == Steady State   ======================================================
    A = get_model_A_matrix()
    B = get_model_B_matrix()

    Vyss = -(k * vit * (A[(0, 1)] * B[(1, 0)] - A[(1, 1)] * B[(0, 0)] - A[
        (0, 1)] * B[(1, 1)] + A[(1, 1)] * B[(0, 1)])) / (A[(0, 0)] * B[
            (1, 0)] - A[(1, 0)] * B[(0, 0)] - A[(0, 0)] * B[(1, 1)] +
                                                         A[(1, 0)] * B[(0, 1)])
    Vpsiss = vit * k
    eyss = 0
    epsiss = -Vyss / vit

    bfss = -(k * vit * (A[(0, 0)] * A[(1, 1)] - A[(0, 1)] * A[
        (1, 0)])) / (A[(0, 0)] * B[(1, 0)] - A[(1, 0)] * B[(0, 0)] -
                     A[(0, 0)] * B[(1, 1)] + A[(1, 0)] * B[(0, 1)])
    brss = -bfss

    xsss = np.array([[Vyss], [Vpsiss], [eyss], [epsiss]])
    usss = np.array([[bfss], [brss]])

    # == LQR control (Gains)   ======================================================

    Q = np.array([[0.0001, 0, 0, 0], [0, 0.0001, 0, 0], [0, 0, 0.0001, 0],
                  [0, 0, 0, 0.0001]])

    R = np.array([[20000, 0], [0, 20000]])

    C = np.array([[1, 0, 0, 0], [0, 1, 0, 0]])

    P = solve_continuous_are(A, B, Q, R)
    #print(P)

    G = np.linalg.inv(R).dot(np.transpose(B)).dot(P)
    #print(G)
    #np.array([[-0.5,4.3e+13],[-0.5,-4.2e+13]])#
    M = pinv(C.dot(pinv(A - B.dot(G))).dot(B))
    #print(M)

    # == Observer  ======================================================

    xhat = np.array([[0], [0], [1.5], [0]])
    #print(xhat)
    Gammax = 0.01 * eye(4, 4)

    dt = 0.01  #periode d'échantionnage

    Gammaalpha = dt * 0.00001 * eye(4, 4)
    Gammabeta = dt**2 * eye(2, 2) * 0.00001
    Psiref = 0 * pi / 180
    Psipref = 0 * pi / 180
    vyref = 0
    mat = np.loadtxt('/home/bachir/spido_ws/src/spido_riding/scripts/mat.txt')
    coords = curve[:, 1:3]
    line = geom.LineString(coords)
    t0 = rospy.get_time()

    while (rospy.get_time() - t0 <= simul_time):
        cmd = cmd_drive()
        point = geom.Point(X, Y)
        nearest_pt = line.interpolate(line.project(point))
        distance, index = spatial.KDTree(coords).query(nearest_pt)
        xref = coords[index, 0]
        yref = coords[index, 1]
        Psiref = curve[index, 3]
        ey = -sin(Psiref) * (X - xref) + cos(Psiref) * (Y - yref)
        epsi = (Psi - Psiref)
        #vy=-Xp*sin(Psi)+Yp*cos(Psi)
        vy = xhat[0, 0]
        x = np.array([[vy], [Psip], [ey], [epsi]])
        yd = np.array([[vyref], [Psipref]])

        y = C.dot(x)
        #print('u',u)
        u = M.dot(yd) - G.dot(x)
        xhat, Gammax = kalman(xhat, Gammax, dt * B.dot(u), y, Gammaalpha,
                              Gammabeta,
                              eye(4, 4) + dt * A, C)
        #print('xhat',xhat)
        print(Psi * 180 / pi)
        vy1 = -Xp * sin(Psi) + Yp * cos(Psi)
        # // vy:vitesse latérale expriméé dans le repère véhicule
        print(vy, vy1)
        #;//-xpref*sin(psiref)+ypref*cos(psiref); // vy:vitesse latérale expriméé dans le repère véhicule
        cmd.linear_speed = vit
        cmd.steering_angle_front = u[0, 0]
        cmd.steering_angle_rear = u[1, 0]
        cmd_publisher.publish(cmd)
        r.sleep()
 def getRiccatiSolution(self):
     S = solve_continuous_are(self.A, self.B, self.Q, self.R, s=self.N)
     return S
Пример #37
0
    full[mask] = triu

    return full


def full_to_triu(full):
    mask = np.triu(np.ones(full.shape, dtype=bool))
    return full[mask]


# LISTING_END triuconvert

# LISTING_START riccatiinit
# Get initial value S for matrix Riccati ODE by solving algebraic Riccati equation
A_f, B_f = system_matrices(t_traj[-1], xd_traj[-1], ud_traj[-1], sys_para)
S = scilin.solve_continuous_are(A_f, B_f, Q, R)
# LISTING_END riccatiinit
# LISTING_START riccatiint
Pbar_triu_traj = np.empty(
    (n_samples,
     int(sys_para.n * (sys_para.n + 1) / 2)))  # allocate array for P
Pbar_triu_traj[0, :] = full_to_triu(S)  # initialize with Pbar(0) = S

K_traj = np.empty((n_samples, sys_para.m, sys_para.n))  # allocate array for K

# get trajectories for P and K via numerical integration
for i_tau in range(n_samples):  # iterate forward in tau direction
    i_t = n_samples - 1 - i_tau  # index in t vector (counting down from last element)
    t_i = t_traj[i_t]
    tau_i = t_traj[i_tau]
    xd_i = xd_traj[i_t]
inputA.close()
inputB.close()
input_one.close()
input_two.close()
input_three.close()

Q = ((1/.6)**2)*eye(6)
Q[0][0] = ((1.0/0.1)**2)
Q[1][1] = ((1.0/0.1)**2)
Q[2][2] = ((1.0/0.1)**2)
Q[3][3] = ((1.0/0.001)**2)
Q[4][4] = ((1.0/0.001)**2)
Q[5][5] = ((1.0/0.001)**2)
R = eye(3)
R[0][0] = (1/0.000000000000000001)**2
R[1][1] = ((1.0/10.0)**2)
R[2][2] = ((1.0/10.0)**2)

K = []

for a,b in zip(A,B):
  S = solve_continuous_are(a,b,Q,R)
  K.append(dot(dot(inv(R), b.T), S))

outputK = open('triple_pen_LQR_K_useful.pkl', 'wb')

pickle.dump(K,outputK)

outputK.close()
Пример #39
0
def LQR(A, B, Q, R):
    return la.solve_continuous_are(A, B, Q, R)
Пример #40
0
    def check_case(self, a, b, q, r):
        """Checks if (A'X + XA - XBR^-1B'X+Q=0) is true"""

        x = solve_continuous_are(a, b, q, r)
        assert_array_almost_equal(
            a.getH()*x + x*a - x*b*inv(r)*b.getH()*x + q, 0.0)
Пример #41
0
 def solve_lqr(A, B, Q, R):
     P = solve_continuous_are(A, B, Q, R)
     K = np.dot(np.dot(np.linalg.inv(R), B.T), P)
     return K
Пример #42
0
def run_cl_simulation(rom, name, Re=110, level=2, palpha=1e-3, control='bc'):
    """Run the closed-loop simulation with reduced LQG controller."""

    # define strings, directories and paths for data storage
    setup_str = 'lvl_' + str(level) + ('_' + control if control is not None else '') \
                + '_re_' + str(Re) + ('_palpha_' + str(palpha) if control == 'bc' else '')
    data_path = '../data/' + 'lvl_' + str(level) + ('_' + control if control
                                                    is not None else '')
    setup_path = data_path + '/re_' + str(Re) + ('_palpha_' + str(palpha)
                                                 if control == 'bc' else '')
    simulation_path = setup_str + '/' + name + '_simulation'

    if not os.path.exists(simulation_path):
        os.makedirs(simulation_path)

    with open(simulation_path + '/rom_' + str(rom.order) + '.csv',
              'w') as file:
        file.write('t, yerr \n')

    # define first order model and matrices for simulation
    fom = load_fom(Re=110, level=2, palpha=1e-3, control='bc')

    mats = spio.loadmat(data_path + '/mats')

    M = mats['M']
    J = mats['J']
    hmat = mats['H']
    fv = mats['fv'] + 1. / Re * mats['fv_diff'] + mats['fv_conv']
    fp = mats['fp'] + mats['fp_div']
    vcmat = mats['Cv']
    NV, NP = fv.shape[0], fp.shape[0]

    if control == 'bc':
        A = 1. / Re * mats['A'] + mats['L1'] + mats[
            'L2'] + 1. / palpha * mats['Arob']
        B = 1. / palpha * mats['Brob']
    else:
        A = 1. / Re * mats['A'] + mats['L1'] + mats['L2']
        B = mats['B']
        # restrict to less dofs in the input
        NU = B.shape[1]
        B = B[:, [0, NU // 2]]

    # compute steady-state solution and linearized convection
    if not os.path.isfile(setup_path + '/ss_nse_sol'):
        ss_nse_v, _ = solve_steadystate_nse(mats, Re, control, palpha=palpha)
        conv_mat = linearized_convection(mats['H'], ss_nse_v)
        spio.savemat(setup_path + '/ss_nse_sol', {
            'ss_nse_v': ss_nse_v,
            'conv_mat': conv_mat
        })
    else:
        ss_nse_sol = spio.loadmat(setup_path + '/ss_nse_sol')
        ss_nse_v, conv_mat = ss_nse_sol['ss_nse_v'], ss_nse_sol['conv_mat']

    # Define parameters for time stepping
    t0 = 0.
    tE = 8.
    Nts = 2**12
    DT = (tE - t0) / Nts
    trange = np.linspace(t0, tE, Nts + 1)

    # Define functions that represent the system inputs
    if control is None:

        def bbcu(ko_state):
            return np.zeros((NV, 1))

        def update_ko_state(ko_state, Cv, DT):
            return ko_state

    else:
        Arom = to_matrix(rom.A, format='dense')  # .real?
        Brom = to_matrix(rom.B, format='dense')
        Crom = to_matrix(rom.C, format='dense')

        XCARE = spla.solve_continuous_are(Arom,
                                          Brom,
                                          Crom.T @ Crom,
                                          np.eye(Brom.shape[1]),
                                          balanced=False)
        XFARE = spla.solve_continuous_are(Arom.T,
                                          Crom.T,
                                          Brom @ Brom.T,
                                          np.eye(Crom.shape[0]),
                                          balanced=False)

        # define control based on Kalman observer state
        def bbcu(ko_state):
            uvec = -Brom.T @ XCARE @ ko_state
            return B @ uvec

        ko1_mat = Arom - XFARE @ Crom.T @ Crom - Brom @ Brom.T @ XCARE
        ko2_mat = XFARE @ Crom.T
        lu_piv = spla.lu_factor(np.eye(rom.order) - DT * ko1_mat)

        Css = vcmat @ ss_nse_v

        # function that determines the next state of the Kalman observer via implicit euler step
        def update_ko_state(ko_state, Cv, DT):
            return spla.lu_solve(lu_piv, ko_state + DT * ko2_mat @ (Cv - Css))

    # introduce small perturbation to steady-state solution as initial value
    pert = fom.A.source.project_onto_subspace(fom.A.operator.source.ones(),
                                              trans=True).to_numpy().T
    old_v = ss_nse_v + 1e-3 * pert

    # initialize state for observer
    ko_state = np.zeros((rom.order, 1))

    sysmat = sps.vstack([
        sps.hstack([M + DT * A, -J.T]),
        sps.hstack([J, sps.csc_matrix((NP, NP))])
    ]).tocsc()
    sysmati = spsla.factorized(sysmat)

    try:
        for k, t in enumerate(trange):
            crhsv = M * old_v + DT * (fv - eva_quadterm(hmat, old_v) +
                                      bbcu(ko_state))
            crhs = np.vstack([crhsv, fp])
            vp_new = np.atleast_2d(sysmati(crhs.flatten())).T
            old_v = vp_new[:NV]
            Cv = vcmat @ old_v
            ko_state = update_ko_state(ko_state, Cv, DT)

            print(k, '/', Nts)
            print(spla.norm(Cv - Css, 2))

            with open(simulation_path + '/rom_' + str(rom.order) + '.csv',
                      'a') as file:
                file.write(str(t) + ',' + str(spla.norm(Cv - Css, 2)) + '\n')
    except:
        with open('simulation_error_log.txt', 'a') as file:
            file.write(name + '_' + str(rom.order) + '\n')
Пример #43
0
    def lqr_kp(self):
        A, B, _, _ = self.get_state_matrices()

        P = solve_continuous_are(A, B, self.Q, self.R)
        K = self.R.I * B.T * P
        return K, P
Пример #44
0
def test_solve_continuous_are():
    mat6 = _load_data('carex_6_data.npz')
    mat15 = _load_data('carex_15_data.npz')
    mat18 = _load_data('carex_18_data.npz')
    mat19 = _load_data('carex_19_data.npz')
    mat20 = _load_data('carex_20_data.npz')
    cases = [
        # Carex examples taken from (with default parameters):
        # [1] P.BENNER, A.J. LAUB, V. MEHRMANN: 'A Collection of Benchmark
        #     Examples for the Numerical Solution of Algebraic Riccati
        #     Equations II: Continuous-Time Case', Tech. Report SPC 95_23,
        #     Fak. f. Mathematik, TU Chemnitz-Zwickau (Germany), 1995.
        #
        # The format of the data is (a, b, q, r, knownfailure), where
        # knownfailure is None if the test passes or a string
        # indicating the reason for failure.
        #
        # Test Case 0: carex #1
        (np.diag([1.], 1), np.array([[0], [1]]), block_diag(1., 2.), 1, None),
        # Test Case 1: carex #2
        (np.array([[4, 3], [-4.5, -3.5]]), np.array([[1], [-1]]),
         np.array([[9, 6], [6, 4.]]), 1, None),
        # Test Case 2: carex #3
        (np.array([[0, 1, 0, 0], [0, -1.89, 0.39, -5.53],
                   [0, -0.034, -2.98, 2.43], [0.034, -0.0011, -0.99, -0.21]]),
         np.array([[0, 0], [0.36, -1.6], [-0.95, -0.032], [0.03, 0]]),
         np.array([[2.313, 2.727, 0.688, 0.023], [2.727, 4.271, 1.148, 0.323],
                   [0.688, 1.148, 0.313, 0.102], [0.023, 0.323, 0.102,
                                                  0.083]]), np.eye(2), None),
        # Test Case 3: carex #4
        (np.array([[-0.991, 0.529, 0, 0, 0, 0, 0, 0],
                   [0.522, -1.051, 0.596, 0, 0, 0, 0, 0],
                   [0, 0.522, -1.118, 0.596, 0, 0, 0, 0],
                   [0, 0, 0.522, -1.548, 0.718, 0, 0, 0],
                   [0, 0, 0, 0.922, -1.64, 0.799, 0, 0],
                   [0, 0, 0, 0, 0.922, -1.721, 0.901, 0],
                   [0, 0, 0, 0, 0, 0.922, -1.823, 1.021],
                   [0, 0, 0, 0, 0, 0, 0.922, -1.943]]),
         np.array([[3.84, 4.00, 37.60, 3.08, 2.36, 2.88, 3.08, 3.00],
                   [-2.88, -3.04, -2.80, -2.32, -3.32, -3.82, -4.12, -3.96]]).T
         * 0.001,
         np.array([[1.0, 0.0, 0.0, 0.0, 0.5, 0.0, 0.0, 0.1],
                   [0.0, 1.0, 0.0, 0.0, 0.1, 0.0, 0.0, 0.0],
                   [0.0, 0.0, 1.0, 0.0, 0.0, 0.5, 0.0, 0.0],
                   [0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0],
                   [0.5, 0.1, 0.0, 0.0, 0.1, 0.0, 0.0, 0.0],
                   [0.0, 0.0, 0.5, 0.0, 0.0, 0.1, 0.0, 0.0],
                   [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.1, 0.0],
                   [0.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
                    0.1]]), np.eye(2), None),
        # Test Case 4: carex #5
        (np.array(
            [[-4.019, 5.120, 0., 0., -2.082, 0., 0., 0., 0.870],
             [-0.346, 0.986, 0., 0., -2.340, 0., 0.,
              0., 0.970],
             [-7.909, 15.407, -4.069, 0., -6.450, 0., 0., 0., 2.680],
             [-21.816, 35.606, -0.339, -3.870, -17.800, 0., 0., 0., 7.390],
             [-60.196, 98.188, -7.907, 0.340, -53.008, 0., 0., 0., 20.400],
             [0, 0, 0, 0, 94.000, -147.200, 0., 53.200, 0.],
             [0, 0, 0, 0, 0, 94.000, -147.200, 0, 0],
             [0, 0, 0, 0, 0, 12.800, 0.000, -31.600, 0],
             [0, 0, 0, 0, 12.800, 0.000, 0.000, 18.800, -31.600]]),
         np.array([[0.010, -0.011, -0.151], [0.003, -0.021, 0.000],
                   [0.009, -0.059, 0.000], [0.024, -0.162, 0.000],
                   [0.068, -0.445, 0.000], [0.000, 0.000, 0.000],
                   [0.000, 0.000, 0.000], [0.000, 0.000, 0.000],
                   [0.000, 0.000, 0.000]]), np.eye(9), np.eye(3), None),
        # Test Case 5: carex #6
        (mat6['A'], mat6['B'], mat6['Q'], mat6['R'], None),
        # Test Case 6: carex #7
        (np.array([[1, 0], [0, -2.]]), np.array([[1e-6], [0]]), np.ones(
            (2, 2)), 1., 'Bad residual accuracy'),
        # Test Case 7: carex #8
        (block_diag(-0.1, -0.02), np.array([[0.100, 0.000], [0.001, 0.010]]),
         np.array([[100, 1000], [1000, 10000]]), np.ones(
             (2, 2)) + block_diag(1e-6, 0), None),
        # Test Case 8: carex #9
        (np.array([[0, 1e6], [0, 0]]), np.array([[0],
                                                 [1.]]), np.eye(2), 1., None),
        # Test Case 9: carex #10
        (np.array([[1.0000001, 1],
                   [1., 1.0000001]]), np.eye(2), np.eye(2), np.eye(2), None),
        # Test Case 10: carex #11
        (np.array([[3, 1.], [4, 2]]), np.array([[1], [1]]),
         np.array([[-11, -5], [-5, -2.]]), 1., None),
        # Test Case 11: carex #12
        (np.array([[7000000., 2000000., -0.], [2000000., 6000000., -2000000.],
                   [0., -2000000., 5000000.]]) / 3, np.eye(3),
         np.array([[1., -2., -2.], [-2., 1., -2.], [-2., -2., 1.]]).dot(
             np.diag([1e-6, 1, 1e6])).dot(
                 np.array([[1., -2., -2.], [-2., 1., -2.], [-2., -2., 1.]])) /
         9, np.eye(3) * 1e6, 'Bad Residual Accuracy'),
        # Test Case 12: carex #13
        (np.array([[0, 0.4, 0, 0], [0, 0, 0.345, 0],
                   [0, -0.524e6, -0.465e6, 0.262e6], [0, 0, 0, -1e6]]),
         np.array([[0, 0, 0, 1e6]]).T, np.diag([1, 0, 1, 0]), 1., None),
        # Test Case 13: carex #14
        (np.array([[-1e-6, 1, 0, 0], [-1, -1e-6, 0, 0], [0, 0, 1e-6, 1],
                   [0, 0, -1, 1e-6]]), np.ones((4, 1)), np.ones(
                       (4, 4)), 1., None),
        # Test Case 14: carex #15
        (mat15['A'], mat15['B'], mat15['Q'], mat15['R'], None),
        # Test Case 15: carex #16
        (np.eye(64, 64, k=-1) + np.eye(64, 64) * (-2.) +
         np.rot90(block_diag(1, np.zeros((62, 62)), 1)) + np.eye(64, 64, k=1),
         np.eye(64), np.eye(64), np.eye(64), None),
        # Test Case 16: carex #17
        (np.diag(np.ones((20, )), 1), np.flipud(np.eye(21, 1)),
         np.eye(21, 1) * np.eye(21, 1).T, 1, 'Bad Residual Accuracy'),
        # Test Case 17: carex #18
        (mat18['A'], mat18['B'], mat18['Q'], mat18['R'], None),
        # Test Case 18: carex #19
        (mat19['A'], mat19['B'], mat19['Q'], mat19['R'],
         'Bad Residual Accuracy'),
        # Test Case 19: carex #20
        (mat20['A'], mat20['B'], mat20['Q'], mat20['R'],
         'Bad Residual Accuracy')
    ]
    # Makes the minimum precision requirements customized to the test.
    # Here numbers represent the number of decimals that agrees with zero
    # matrix when the solution x is plugged in to the equation.
    #
    # res = array([[8e-3,1e-16],[1e-16,1e-20]]) --> min_decimal[k] = 2
    #
    # If the test is failing use "None" for that entry.
    #
    min_decimal = (14, 12, 13, 14, 11, 6, None, 5, 7, 14, 14, None, 9, 14, 13,
                   14, None, 12, None, None)

    def _test_factory(case, dec):
        """Checks if 0 = XA + A'X - XB(R)^{-1} B'X + Q is true"""
        a, b, q, r, knownfailure = case
        if knownfailure:
            pytest.xfail(reason=knownfailure)

        x = solve_continuous_are(a, b, q, r)
        res = x.dot(a) + a.conj().T.dot(x) + q
        out_fact = x.dot(b)
        res -= out_fact.dot(solve(np.atleast_2d(r), out_fact.conj().T))
        assert_array_almost_equal(res, np.zeros_like(res), decimal=dec)
Пример #45
0
def solve_ricc_lrcf(A, E, B, C, R=None, S=None, trans=False, options=None):
    """Compute an approximate low-rank solution of a Riccati equation.

    See :func:`pymor.algorithms.riccati.solve_ricc_lrcf` for a general
    description.

    This function uses `scipy.linalg.solve_continuous_are`, which
    is a dense solver.
    Therefore, we assume all |Operators| and |VectorArrays| can be
    converted to |NumPy arrays| using
    :func:`~pymor.algorithms.to_matrix.to_matrix` and
    :func:`~pymor.vectorarrays.interfaces.VectorArrayInterface.to_numpy`.

    Parameters
    ----------
    A
        The |Operator| A.
    E
        The |Operator| E or `None`.
    B
        The operator B as a |VectorArray| from `A.source`.
    C
        The operator C as a |VectorArray| from `A.source`.
    R
        The operator R as a 2D |NumPy array| or `None`.
    S
        The operator S as a |VectorArray| from `A.source` or `None`.
    trans
        Whether the first |Operator| in the Riccati equation is
        transposed.
    options
        The solver options to use (see :func:`ricc_lrcf_solver_options`).

    Returns
    -------
    Z
        Low-rank Cholesky factor of the Riccati equation solution,
        |VectorArray| from `A.source`.
    """

    _solve_ricc_check_args(A, E, B, C, R, S, trans)
    options = _parse_options(options, ricc_lrcf_solver_options(), 'scipy', None, False)
    if options['type'] != 'scipy':
        raise ValueError(f"Unexpected Riccati equation solver ({options['type']}).")

    A_source = A.source
    A = to_matrix(A, format='dense')
    E = to_matrix(E, format='dense') if E else None
    B = B.to_numpy().T
    C = C.to_numpy()
    S = S.to_numpy().T if S else None
    if R is None:
        R = np.eye(C.shape[0] if not trans else B.shape[1])
    if not trans:
        if E is not None:
            E = E.T
        X = solve_continuous_are(A.T, C.T, B.dot(B.T), R, E, S)
    else:
        X = solve_continuous_are(A, B, C.T.dot(C), R, E, S)

    return A_source.from_numpy(_chol(X).T)