rsLQR  0.1
Using the Riccati Solver

This page provides some details on how to use the rsLQR solver to solve an LQR problem.

Part I: Defining the problem

First, create a new LQRProblem with ndlqr_NewLQRProblem

LQRProblem* lqrprob = ndlqr_NewLQRProblem(nstates, ninputs, nhorizon);

Next, fill in the LQRProblem data. You can choose to define an array of LQRData structs and use ndlqr_InitializeLQRProblem(), or loop over time steps and do it yourself

lqrprob->nhorizon = nhorizon;
for (int i = 0; i < nstates; ++i) {
lqrprob->x0[i] = x0[i]; // assumes x0 is defined somewhere
}
for (int k = 0; i < nhorizon; ++k) {
// Assumes all of the following data is defined
LQRData* data = lqrprob->lqrdata[k];
ndlqr_InitializeLQRData(data, Q, R, q, r, c, A, B, d);
}

Part II: Setting up the solver

Initialize a new solver:

RiccatiSolver* solver = rdlqr_NewRiccatiSolver(lqrprob);

Part III: Solving

Call the ndlqr_SolveRiccati() method to solve the system using Riccati recursion:

Part IV: Getting the solution and post-processing

A summary of the solve can be printed using:

Like the rsLQR solver, the solution can vector can be obtained either one of two ways:

int nvars = ndlqr_GetNumVarsRiccati(solver); // can also use solver->nvars
double* soln = (double*) malloc(nvars * sizeof(double));

or

Note that the second method return a Matrix whose data is still owned by the solver (avoids a memory allocation or copy). Do not free this memory and be aware that editing it will edit the data stored in the solver.

Part V: Freeing the solver

Don't forget to free the solver!

ndlqr_PrintRiccatiSummary
int ndlqr_PrintRiccatiSummary(RiccatiSolver *solver)
Prints a summary of the solve.
Definition: riccati_solver.c:155
ndlqr_FreeRiccatiSolver
int ndlqr_FreeRiccatiSolver(RiccatiSolver *solver)
Free the memory for a Riccati solver.
Definition: riccati_solver.c:139
ndlqr_GetRiccatiSolution
Matrix ndlqr_GetRiccatiSolution(RiccatiSolver *solver)
Get the solution vector.
Definition: riccati_solver.c:167
ndlqr_InitializeLQRData
int ndlqr_InitializeLQRData(LQRData *lqrdata, double *Q, double *R, double *q, double *r, double c, double *A, double *B, double *d)
Copy data into an initialized LQRData structure.
Definition: lqr_data.c:10
ndlqr_CopyRiccatiSolution
int ndlqr_CopyRiccatiSolution(RiccatiSolver *solver, double *soln)
Copies the solution to a user-supplied array.
Definition: riccati_solver.c:181
RiccatiSolver
Solver that uses Riccati recursion to solve an LQR problem.
Definition: riccati_solver.h:62
Matrix
Represents a matrix of double-precision data.
Definition: matrix.h:71
ndlqr_NewLQRProblem
LQRProblem * ndlqr_NewLQRProblem(int nstates, int ninputs, int nhorizon)
Initialize a new LQRProblem data with unitialized data.
Definition: lqr_problem.c:16
LQRData
Holds the data for a single time step of LQR.
Definition: lqr_data.h:54
ndlqr_SolveRiccati
int ndlqr_SolveRiccati(RiccatiSolver *solver)
Solve the LQR problem using Riccati recursion and a forward simulation of the linear dynamics.
Definition: riccati_solve.c:7
LQRProblem
Describes an LQR problem with affine terms.
Definition: lqr_problem.h:31