diff --git a/src/solve_transition.cpp b/src/solve_transition.cpp index 6465e4750a3afb90ce7dfadba9e3a11cc61e9434..0e88f1b90e5f73a9175a7ea6dba733390c48204f 100644 --- a/src/solve_transition.cpp +++ b/src/solve_transition.cpp @@ -256,7 +256,7 @@ std::vector<coefs_t> computeDiscretizedAccelerationWaypoints(const ProblemData& -std::pair<MatrixX3, VectorX> computeConstraintsOneStep(const ProblemData& pData,const VectorX& Ts,const double timeStep){ +std::pair<MatrixXX, VectorX> computeConstraintsOneStep(const ProblemData& pData,const VectorX& Ts,const double timeStep,VectorX& constraints_equivalence){ // compute the list of discretized waypoint : double t_total = 0.; for(int i = 0 ; i < Ts.size() ; ++i) @@ -279,6 +279,8 @@ std::pair<MatrixX3, VectorX> computeConstraintsOneStep(const ProblemData& pData, assert(stepIdForPhase.back() == (wps.size()-1)); // -1 because the first one is the index (start at 0) and the second is the size // compute the total number of inequalities (to initialise A and b) int num_ineq = 0; + int num_stab_ineq = 0; + int num_kin_ineq = 0; int numStepForPhase; centroidal_dynamics::MatrixXX Hrow; VectorX h; @@ -292,24 +294,27 @@ std::pair<MatrixX3, VectorX> computeConstraintsOneStep(const ProblemData& pData, numStepForPhase = stepIdForPhase[i] - stepIdForPhase[i-1] +1; // +1 because at the switch point we add the constraints of both phases } std::cout<<"constraint size : Kin = "<<pData.contacts_[i].kin_.rows()<<" ; stab : "<<Hrow.rows()<<" times "<<numStepForPhase<<" steps"<<std::endl; - num_ineq += Hrow.rows() * numStepForPhase; + num_stab_ineq += Hrow.rows() * numStepForPhase; if(i == Ts.size()-1) numStepForPhase--; // we don't consider kinematics constraints for the last point (because it's independant of x) - num_ineq += pData.contacts_[i].kin_.rows() * numStepForPhase; + num_kin_ineq += pData.contacts_[i].kin_.rows() * numStepForPhase; } + num_ineq = num_stab_ineq + num_kin_ineq; std::cout<<"total of inequalities : "<<num_ineq<<std::endl; // init constraints matrix : - MatrixX3 A(num_ineq,3); + MatrixXX A = MatrixXX::Zero(num_ineq,3+num_stab_ineq); // +num_stab_ineq because of the slack constraints + MatrixXX identity = MatrixXX::Identity(num_stab_ineq,num_stab_ineq); + constraints_equivalence = VectorX(num_stab_ineq); VectorX b(num_ineq); Matrix3 S_hat; MatrixX3 A_stab; VectorX b_stab; int id_rows = 0; - int id_phase = 0; int current_size; + int id_phase = 0; ContactData phase = pData.contacts_[id_phase]; // compute some constant matrice for the current phase : const Vector3& g = phase.contactPhase_->m_gravity; @@ -322,28 +327,23 @@ std::pair<MatrixX3, VectorX> computeConstraintsOneStep(const ProblemData& pData, int dimH = (int)(H.rows()); mH = phase.contactPhase_->m_mass * H; - // assign the constraints (kinematics and stability) for each discretized waypoints : + + // assign the Stability constraints for each discretized waypoints : // we don't consider the first point, because it's independant of x. for(int id_step = 1 ; id_step < numStep ; ++id_step ){ - // add constraints for wp id_step, on current phase : - // add kinematics constraints : - // constraint are of the shape A c <= b . But here c(x) = Fx + s so : AFx <= b - As - - if(id_step != numStep-1){ // we don't consider kinematics constraints for the last point (because it's independant of x) - current_size = phase.kin_.rows(); - A.block(id_rows,0,current_size,3) = (phase.Kin_ * wps[id_step].first); - b.segment(id_rows,current_size) = phase.kin_ - (phase.Kin_*wps[id_step].second); - id_rows += current_size; - } - - // add stability constraints : + S_hat = skew(wps[id_step].second*acc_wps[id_step].first - acc_wps[id_step].second*wps[id_step].first + g*wps[id_step].first); A_stab = mH.block(0,3,dimH,3) * S_hat + mH.block(0,0,dimH,3) * acc_wps[id_step].first; b_stab = h + mH.block(0,0,dimH,3)*(g - acc_wps[id_step].second) + mH.block(0,3,dimH,3)*(wps[id_step].second.cross(g) - wps[id_step].second.cross(acc_wps[id_step].second)); Normalize(A_stab,b_stab); A.block(id_rows,0,dimH,3) = A_stab; b.segment(id_rows,dimH) = b_stab; + // assign correspondance vector : + constraints_equivalence.segment(id_rows,dimH) = VectorX::Ones(dimH)*id_step; + // add part of the identity for the slack variable : + A.block(id_rows,3,dimH,num_stab_ineq) = identity.block(id_rows,0,dimH,num_stab_ineq); + id_rows += dimH ; /* @@ -352,6 +352,7 @@ std::pair<MatrixX3, VectorX> computeConstraintsOneStep(const ProblemData& pData, b.segment(id_rows,dimH) = h + mH.block(0,0,dimH,3)*g - mH.block(0,3,dimH,3)*g.cross(wps[id_step].second); id_rows += dimH ; */ + // check if we are going to switch phases : for(int i = 0 ; i < (stepIdForPhase.size()-1) ; ++i){ if(id_step == stepIdForPhase[i]){ @@ -365,17 +366,15 @@ std::pair<MatrixX3, VectorX> computeConstraintsOneStep(const ProblemData& pData, mH = phase.contactPhase_->m_mass * H; // the current waypoint must have the constraints of both phases. So we add it again : // TODO : filter for redunbdant constraints ... - - current_size = phase.kin_.rows(); - A.block(id_rows,0,current_size,3) = (phase.Kin_ * wps[id_step].first); - b.segment(id_rows,current_size) = phase.kin_ - (phase.Kin_*wps[id_step].second); - id_rows += current_size; - - // add stability constraints : + S_hat = skew(wps[id_step].second*acc_wps[id_step].first - acc_wps[id_step].second*wps[id_step].first + g*wps[id_step].first); A.block(id_rows,0,dimH,3) = mH.block(0,3,dimH,3) * S_hat + mH.block(0,0,dimH,3) * acc_wps[id_step].first; b.segment(id_rows,dimH) = h + mH.block(0,0,dimH,3)*(g - acc_wps[id_step].second) + mH.block(0,3,dimH,3)*(wps[id_step].second.cross(g) - wps[id_step].second.cross(acc_wps[id_step].second)); + // assign correspondance vector : + constraints_equivalence.segment(id_rows,dimH) = VectorX::Ones(dimH)*(id_step+0.5); + // add part of the identity for the slack variable : + A.block(id_rows,3,dimH,num_stab_ineq) = identity.block(id_rows,0,dimH,num_stab_ineq); id_rows += dimH ; /* @@ -386,17 +385,52 @@ std::pair<MatrixX3, VectorX> computeConstraintsOneStep(const ProblemData& pData, */ } } + } + + id_phase = 0; + phase = pData.contacts_[id_phase]; + // assign the Kinematics constraints for each discretized waypoints : + // we don't consider the first point, because it's independant of x. + for(int id_step = 1 ; id_step < numStep ; ++id_step ){ + // add constraints for wp id_step, on current phase : + // add kinematics constraints : + // constraint are of the shape A c <= b . But here c(x) = Fx + s so : AFx <= b - As + if(id_step != numStep-1){ // we don't consider kinematics constraints for the last point (because it's independant of x) + current_size = phase.kin_.rows(); + A.block(id_rows,0,current_size,3) = (phase.Kin_ * wps[id_step].first); + b.segment(id_rows,current_size) = phase.kin_ - (phase.Kin_*wps[id_step].second); + id_rows += current_size; + } + + // check if we are going to switch phases : + for(int i = 0 ; i < (stepIdForPhase.size()-1) ; ++i){ + if(id_step == stepIdForPhase[i]){ + // switch to phase i + id_phase=i+1; + phase = pData.contacts_[id_phase]; + // the current waypoint must have the constraints of both phases. So we add it again : + // TODO : filter for redunbdant constraints ... + current_size = phase.kin_.rows(); + A.block(id_rows,0,current_size,3) = (phase.Kin_ * wps[id_step].first); + b.segment(id_rows,current_size) = phase.kin_ - (phase.Kin_*wps[id_step].second); + id_rows += current_size; + } + } + } + + std::cout<<"id rows : "<<id_rows<<" ; total rows : "<<A.rows()<<std::endl; assert(id_rows == (A.rows()) && "The constraints matrices were not fully filled."); return std::make_pair(A,b); } //cost : min distance between x and midPoint : -std::pair<MatrixX3, VectorX> computeCostMidPoint(const ProblemData& pData){ +std::pair<MatrixXX, VectorX> computeCostMidPoint(const ProblemData& pData, size_t size){ Vector3 midPoint = (pData.c0_ + pData.c1_)/2.; // todo : replace it with point found by planning ?? - Matrix3 H = Matrix3::Identity(); - Vector3 g = -midPoint; + MatrixXX H = MatrixXX::Identity(size,size); + VectorX g = VectorX::Zero(size); + g.head<3>() = -midPoint; return std::make_pair(H,g); } @@ -423,6 +457,12 @@ void computeBezierCurve(const ProblemData& pData, const double T, ResultDataCOMT res.c_of_t_ = bezier_t (wps.begin(), wps.end(),T); } +double analyseSlack(const VectorX& slack){ + //TODO + std::cout<<"slack : "<<slack.transpose()<<std::endl; + return slack.squaredNorm(); +} + ResultDataCOMTraj solveOnestep(const ProblemData& pData, const VectorX& Ts, const double timeStep,const Vector3& init_guess){ assert(pData.contacts_.size() ==2 || pData.contacts_.size() ==3); assert(Ts.size() == pData.contacts_.size()); @@ -431,18 +471,23 @@ ResultDataCOMTraj solveOnestep(const ProblemData& pData, const VectorX& Ts, cons T+=Ts[i]; // bool fail = true; ResultDataCOMTraj res; - std::pair<MatrixX3, VectorX> Ab = computeConstraintsOneStep(pData,Ts,timeStep); + VectorX constraint_equivalence; + std::pair<MatrixXX, VectorX> Ab = computeConstraintsOneStep(pData,Ts,timeStep,constraint_equivalence); // std::pair<MatrixX3, VectorX> Hg = computeCostEndVelocity(pData,T); - std::pair<MatrixX3, VectorX> Hg = computeCostMidPoint(pData); + std::pair<MatrixXX, VectorX> Hg = computeCostMidPoint(pData,constraint_equivalence.size()+3); std::cout<<"Init = "<<std::endl<<init_guess.transpose()<<std::endl; + VectorX x = VectorX::Zero(3 + constraint_equivalence.size()); + x.head<3>() = init_guess; // rewriting 0.5 || Dx -d ||^2 as x'Hx + g'x - ResultData resQp = solve(Ab.first,Ab.second,Hg.first,Hg.second, init_guess); + ResultData resQp = solve(Ab.first,Ab.second,Hg.first,Hg.second, x); + double feasability = analyseSlack(resQp.x.tail(constraint_equivalence.size())); + std::cout<<"feasability : "<<feasability<<std::endl; if(resQp.success_) { res.success_ = true; - res.x = resQp.x; + res.x = resQp.x.head<3>(); computeBezierCurve (pData,T,res); // computeFinalVelocity(pData,T,res); // computeFinalAcceleration(pData,T,res);