Example #1
0
int SundialsIda::JvProd(realtype t, N_Vector yIn, N_Vector ydotIn, N_Vector resIn,
                        N_Vector vIn, N_Vector JvIn, realtype c_j, void* jac_data,
                        N_Vector tmp1, N_Vector tmp2)
{
    sdVector y(yIn), ydot(ydotIn), res(resIn), v(vIn), Jv(JvIn);
    return ((sdDAE*) jac_data)->JvProd(t,y , ydot, res, v, Jv , c_j);
}
void RigidResponseMethodBLCP<Scalar, Dim>::collisionResponse()
{
    //initialize
    unsigned int m = this->rigid_driver_->numContactPoint();//m: number of contact points
    unsigned int n = this->rigid_driver_->numRigidBody();//n: number of rigid bodies
    if(m == 0 || n == 0)//no collision or no rigid body
        return;

    unsigned int dof = n * (Dim + RotationDof<Dim>::degree);//DoF(Degree of Freedom) of a rigid-body system
    unsigned int fric_sample_count = 2;//count of friction sample directions
    unsigned int s = m * fric_sample_count;//s: number of friction sample. Here a square sample is adopted
    CompressedJacobianMatrix<Scalar, Dim> J(m, n);//Jacobian matrix. (m, dof) dimension when uncompressed, (m, 12) dimension after compression
    CompressedJacobianMatrix<Scalar, Dim> D(s, n);//Jacobian matrix of friction. (s, dof) dimension when uncompressed, (s, 12) dimension after compression
    CompressedInertiaMatrix<Scalar, Dim> M(n);//inertia matrix. (dof, dof) dimension when uncompressed, (dof, 6) dimension after compression
    CompressedInertiaMatrix<Scalar, Dim> M_inv(n);//inversed inertia matrix. (dof, dof) dimension when uncompressed, (dof, 6) dimension after compression
    CompressedJacobianMatrix<Scalar, Dim> MJ(n, m);//M * J. (dof, m) dimension when uncompressed, (12, m) dimension after compression
    CompressedJacobianMatrix<Scalar, Dim> MD(n, s);//M * D. (dof, s) dimension when uncompressed, (12, s) dimension after compression
    VectorND<Scalar> v(dof, 0);//generalized velocity of the system
    VectorND<Scalar> Jv(m, 0);//normal relative velocity of each contact point (for normal contact impulse calculation)
    VectorND<Scalar> post_Jv(m, 0);//expected post-impact normal relative velocity of each contact point (for normal contact impulse calculation)
    VectorND<Scalar> Dv(s, 0);//tangent relative velocity of each contact point (for frictional contact impulse calculation)
    VectorND<Scalar> CoR(m, 0);//coefficient of restitution (for normal contact impulse calculation)
    VectorND<Scalar> CoF(s, 0);//coefficient of friction (for frictional contact impulse calculation)
    VectorND<Scalar> z_norm(m, 0);//normal contact impulse. The key of collision response
    VectorND<Scalar> z_fric(s, 0);//frictional contact impulse. The key of collision response

    RigidBodyDriverUtility<Scalar, Dim>::computeMassMatrix(this->rigid_driver_, M, M_inv);
    RigidBodyDriverUtility<Scalar, Dim>::computeJacobianMatrix(this->rigid_driver_, J);
    RigidBodyDriverUtility<Scalar, Dim>::computeFricJacobianMatrix(this->rigid_driver_, D);
    RigidBodyDriverUtility<Scalar, Dim>::computeGeneralizedVelocity(this->rigid_driver_, v);
    
    //compute other matrix in need
    CompressedJacobianMatrix<Scalar, Dim> J_T = J;
    J_T = J.transpose();
    CompressedJacobianMatrix<Scalar, Dim> D_T = D;
    D_T = D.transpose();
    MJ = M_inv * J_T;
    MD = M_inv * D_T;
    Jv = J * v;
    Dv = D * v;

    //update CoR and CoF
    RigidBodyDriverUtility<Scalar, Dim>::computeCoefficient(this->rigid_driver_, CoR, CoF);
    
    //calculate the expected post-impact velocity
    for(unsigned int i = 0; i < m; ++i)
        post_Jv[i] = -Jv[i] * CoR[i];

    //solve BLCP with PGS. z_norm and z_fric are the unknown variables
    RigidBodyDriverUtility<Scalar, Dim>::solveBLCPWithPGS(this->rigid_driver_, J, D, MJ, MD, Jv, post_Jv, Dv, z_norm, z_fric, CoR, CoF, 20);
    //apply impulse
    RigidBodyDriverUtility<Scalar, Dim>::applyImpulse(this->rigid_driver_, z_norm, z_fric, J_T, D_T);
}
int main(int argc, char* argv[])
{
    if(argc < 2)
    {
        std::cerr << "You should provide a system as argument, either gazebo or flat_fish." << std::endl;
        return 1;
    }

    //========================================================================================
    //                                  SETTING VARIABLES
    //========================================================================================

    std::string system = argv[1];

    double weight;
    double buoyancy;
    std::string dataFolder;

    if(system == "gazebo")
    {
        weight = 4600;
        buoyancy = 4618;
        dataFolder = "./config/gazebo/";
    }
    else if(system == "flatfish" || system == "flat_fish")
    {
        weight = 2800;
        buoyancy = 2812;
        dataFolder = "./config/flatfish/";
    }
    else
    {
        std::cerr << "Unknown system " << system << "." << std::endl;
        return 1;
    }

    double uncertainty = 0;

     /* true  - Export the code to the specified folder
      * false - Simulates the controller inside Acado's environment */
    std::string rockFolder = "/home/rafaelsaback/rock/1_dev/control/uwv_model_pred_control/src";

    /***********************
     * CONTROLLER SETTINGS
     ***********************/

    // Prediction and control horizon
    double horizon         = 2;
    double sampleTime      = 0.1;
    int    iteractions     = horizon / sampleTime;
    bool   positionControl = false;

    //========================================================================================
    //                                  DEFINING VARIABLES
    //========================================================================================

    DifferentialEquation f;                     // Variable that will carry 12 ODEs (6 for position and 6 for velocity)

    DifferentialState v("Velocity", 6, 1);      // Velocity States
    DifferentialState n("Pose", 6, 1);          // Pose States
    DifferentialState tau("Efforts", 6, 1);     // Effort
    Control tauDot("Efforts rate", 6, 1);       // Effort rate of change

    DVector rg(3);                              // Center of gravity
    DVector rb(3);                              // Center of buoyancy

    DMatrix M(6, 6);                            // Inertia matrix
    DMatrix Minv(6, 6);                         // Inverse of inertia matrix
    DMatrix Dl(6, 6);                           // Linear damping matrix
    DMatrix Dq(6, 6);                           // Quadratic damping matrix

    // H-representation of the output domain's polyhedron
    DMatrix AHRep(12,6);
    DMatrix BHRep(12,1);

    Expression linearDamping(6, 6);             // Dl*v
    Expression quadraticDamping(6, 6);          // Dq*|v|*v
    Expression gravityBuoyancy(6);              // g(n)
    Expression absV(6, 6);                      // |v|
    Expression Jv(6);                           // J(n)*v
    Expression vDot(6);                         // AUV Fossen's equation

    Function J;                                 // Cost function
    Function Jn;                                // Terminal cost function

    AHRep = readVariable("./config/", "a_h_rep.dat");
    BHRep = readVariable("./config/", "b_h_rep.dat");
    M = readVariable(dataFolder, "m_matrix.dat");
    Dl = readVariable(dataFolder, "dl_matrix.dat");
    Dq = readVariable(dataFolder, "dq_matrix.dat");

    /***********************
     * LEAST-SQUARES PROBLEM
     ***********************/

    // Cost Functions
    if (positionControl)
    {
        J  << n;
        Jn << n;
    }
    else
    {
        J  << v;
        Jn << v;
    }

    J << tauDot;

    // Weighting Matrices for simulational controller
    DMatrix Q  = eye<double>(J.getDim());
    DMatrix QN = eye<double>(Jn.getDim());

    Q = readVariable("./config/", "q_matrix.dat");

    //========================================================================================
    //                                  MOTION MODEL EQUATIONS
    //========================================================================================
    rg(0) = 0;  rg(1) = 0;  rg(2) = 0;
    rb(0) = 0;  rb(1) = 0;  rb(2) = 0;

    M  *= (2 -(1 + uncertainty));
    Dl *= 1 + uncertainty;
    Dq *= 1 + uncertainty;

    SetAbsV(absV, v);

    Minv = M.inverse();
    linearDamping = Dl * v;
    quadraticDamping = Dq * absV * v;
    SetGravityBuoyancy(gravityBuoyancy, n, rg, rb, weight, buoyancy);
    SetJv(Jv, v, n);

    // Dynamic Equation
    vDot = Minv * (tau - linearDamping - quadraticDamping - gravityBuoyancy);

    // Differential Equations
    f << dot(v) == vDot;
    f << dot(n) == Jv;
    f << dot(tau) == tauDot;

    //========================================================================================
    //                              OPTIMAL CONTROL PROBLEM (OCP)
    //========================================================================================

    OCP ocp(0, horizon, iteractions);

    // Weighting Matrices for exported controller
    BMatrix Qexp = eye<bool>(J.getDim());
    BMatrix QNexp = eye<bool>(Jn.getDim());

    ocp.minimizeLSQ(Qexp, J);
    ocp.minimizeLSQEndTerm(QNexp, Jn);
    ocp.subjectTo(f);

    // Individual degrees of freedom constraints
    ocp.subjectTo(tau(3) == 0);
    ocp.subjectTo(tau(4) == 0);

    /* Note: If the constraint for Roll is not defined the MPC does not
     * work since there's no possible actuation in that DOF.
     * Always consider Roll equal to zero. */

    // Polyhedron set of inequalities
    ocp.subjectTo(AHRep*tau - BHRep <= 0);


    //========================================================================================
    //                                  CODE GENERATION
    //========================================================================================

    // Export code to ROCK
    OCPexport mpc(ocp);

    int Ni = 1;

    mpc.set(HESSIAN_APPROXIMATION, GAUSS_NEWTON);
    mpc.set(DISCRETIZATION_TYPE, SINGLE_SHOOTING);
    mpc.set(INTEGRATOR_TYPE, INT_RK4);
    mpc.set(NUM_INTEGRATOR_STEPS, iteractions * Ni);
    mpc.set(HOTSTART_QP, YES);
    mpc.set(QP_SOLVER, QP_QPOASES);
    mpc.set(GENERATE_TEST_FILE, NO);
    mpc.set(GENERATE_MAKE_FILE, NO);
    mpc.set(GENERATE_MATLAB_INTERFACE, NO);
    mpc.set(GENERATE_SIMULINK_INTERFACE, NO);
    mpc.set(CG_USE_VARIABLE_WEIGHTING_MATRIX, YES);
    mpc.set(CG_HARDCODE_CONSTRAINT_VALUES, YES);

    if (mpc.exportCode(rockFolder.c_str()) != SUCCESSFUL_RETURN)
        exit( EXIT_FAILURE);

    mpc.printDimensionsQP();

    return EXIT_SUCCESS;
}
void SoftConstrFunction::Evaluate(const arma::vec &x) {
    // Vertex coordinates: First convert control points into vertices
    // verCoords has the form of [x1 x2, x3... y1 y2 y3... z1 z2 z3]
    // We will compute Jacobian w.r.t vertex variables first, then we compute
    // Jacobian w.r.t actual variables using composition rules
    vec vertCoords = this->P * x;
    vec CPx;
    CPx.set_size(this->refEdgeLens.n_elem);
    
    int nVertVars	= this->P.n_rows;				// Number of vertex variables = 3 * #vertices
    int nVerts		= nVertVars / 3;				// Number of vertices
    int nEdges		= this->refEdgeLens.n_elem;		// Number of edges (#constraints)
    
    // TODO: Make Jv to be attribute of class to avoid re-allocating each evaluation
    // Jacobian w.r.t all vertex coordinates. Then this->J = Jv * P since x = P*c
    mat Jv = zeros(nEdges, nVertVars);
    
    // Iterate through all edges to compute function value and derivatives
    for (int i = 0; i < nEdges; i++)
    {
        // An edge has two vertices
        int vertID1 = edges(0, i);
        int vertID2 = edges(1, i);
        
        // Indices of x,y,z coordinates in the vector vertCoords [x1 x2, x3... y1 y2 y3... z1 z2 z3]
        int x1Idx	= vertID1;
        int y1Idx	= x1Idx + nVerts;
        int z1Idx	= y1Idx + nVerts;
        
        int x2Idx	= vertID2;
        int y2Idx	= x2Idx + nVerts;
        int z2Idx	= y2Idx + nVerts;
        
        // Coordinates of two vertices (x1,y1,z1) & (x2,y2,z2)
        double x1	= vertCoords(x1Idx);
        double y1	= vertCoords(y1Idx);
        double z1	= vertCoords(z1Idx);
        
        double x2	= vertCoords(x2Idx);
        double y2	= vertCoords(y2Idx);
        double z2	= vertCoords(z2Idx);
        
        // Edge length
        double edgeLen = sqrt( pow(x2-x1, 2) + pow(y2-y1, 2) + pow(z2-z1, 2) );
        
        // Compute function value = "edge length" - "reference edge length"
        // 有一些存在len大于refLen的边,这不符合实际情况,因此要做constrained optimization
        CPx(i) = edgeLen - refEdgeLens(i);
        // if (edgeLen > refEdgeLens(i))
        // {
        // 	std::cout << "FOUND ONE" << std::endl;
        // }
        
        // Compute derivatives. Recall the derivative: sqrt'(x) = 1/(2*sqrt(x))
        Jv(i, x1Idx) = (x1-x2) / edgeLen;
        Jv(i, y1Idx) = (y1-y2) / edgeLen;
        Jv(i, z1Idx) = (z1-z2) / edgeLen;
        
        Jv(i, x2Idx) = (x2-x1) / edgeLen;
        Jv(i, y2Idx) = (y2-y1) / edgeLen;
        Jv(i, z2Idx) = (z2-z1) / edgeLen;
    }
    
    this->F = MPwAP * x;
    this->C = CPx;
    // Jacobian w.r.t actual variables using composition chain rule
//    mat m1 = arma::join_cols(MPwAP, Jv * P);
    //mat m2 = arma::join_rows(2*trans(MPwAP*x), 2 * trans(CPx));
    this->J = MPwAP;
    this->A = Jv * P;
    
    //cout << this->J << endl;
    vec CPxabs = arma::abs(CPx);
    
#if 0
    cout << "Constraint function mean: " << arma::mean(CPxabs) << endl;
#endif

}