| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /* | ||
| 2 | * Copyright 2017, LAAS-CNRS | ||
| 3 | * Author: Pierre Fernbach | ||
| 4 | */ | ||
| 5 | |||
| 6 | #include <hpp/bezier-com-traj/common_solve_methods.hh> | ||
| 7 | #include <hpp/bezier-com-traj/solve.hh> | ||
| 8 | #include <hpp/bezier-com-traj/waypoints/waypoints_definition.hh> | ||
| 9 | #include <limits> | ||
| 10 | |||
| 11 | using namespace bezier_com_traj; | ||
| 12 | |||
| 13 | namespace bezier_com_traj { | ||
| 14 | typedef std::pair<double, point3_t> coefs_t; | ||
| 15 | const int DIM_POINT = 3; | ||
| 16 | // const int NUM_DISCRETIZATION = 11; | ||
| 17 | const bool verbose = false; | ||
| 18 | |||
| 19 | /** | ||
| 20 | * @brief solveEndEffector Tries to produce a trajectory represented as a bezier | ||
| 21 | * curve that satisfy position, velocity and acceleration constraint for the | ||
| 22 | * initial and final point and that follow as close as possible the input | ||
| 23 | * trajectory | ||
| 24 | * @param pData problem Data. | ||
| 25 | * @param path the path to follow, the class Path must implement the operator | ||
| 26 | * (double t) , t \in [0,1] return a Vector3 that give the position on the path | ||
| 27 | * for a given time | ||
| 28 | * @param T time lenght of the trajectory | ||
| 29 | * @param timeStep time that the solver has to stop | ||
| 30 | * @return ResultData a struct containing the resulting trajectory, if success | ||
| 31 | * is true. | ||
| 32 | */ | ||
| 33 | template <typename Path> | ||
| 34 | ResultDataCOMTraj solveEndEffector(const ProblemData& pData, const Path& path, | ||
| 35 | const double T, const double weightDistance, | ||
| 36 | bool useVelCost = true); | ||
| 37 | |||
| 38 | ✗ | coefs_t initCoefs() { | |
| 39 | ✗ | coefs_t c; | |
| 40 | ✗ | c.first = 0; | |
| 41 | ✗ | c.second = point3_t::Zero(); | |
| 42 | ✗ | return c; | |
| 43 | } | ||
| 44 | |||
| 45 | // up to jerk second derivativ constraints for init, pos vel and acc constraint | ||
| 46 | // for goal | ||
| 47 | ✗ | std::vector<bezier_t::point_t> computeConstantWaypointsInitPredef( | |
| 48 | const ProblemData& pData, double T) { | ||
| 49 | ✗ | const double n = 4; | |
| 50 | ✗ | std::vector<bezier_t::point_t> pts; | |
| 51 | ✗ | pts.push_back(pData.c0_); // c0 | |
| 52 | ✗ | pts.push_back((pData.dc0_ * T / n) + pData.c0_); // dc0 | |
| 53 | ✗ | pts.push_back( | |
| 54 | ✗ | (n * n * pData.c0_ - n * pData.c0_ + 2 * n * pData.dc0_ * T - | |
| 55 | ✗ | 2 * pData.dc0_ * T + pData.ddc0_ * T * T) / | |
| 56 | ✗ | (n * (n - 1))); // ddc0 // * T because derivation make a T appear | |
| 57 | ✗ | pts.push_back((n * n * pData.c0_ - n * pData.c0_ + 3 * n * pData.dc0_ * T - | |
| 58 | ✗ | 3 * pData.dc0_ * T + 3 * pData.ddc0_ * T * T) / | |
| 59 | ✗ | (n * (n - 1))); // j0 | |
| 60 | // pts.push_back((n*n*pData.c0_ - n*pData.c0_ + 4*n*pData.dc0_*T - | ||
| 61 | // 4*pData.dc0_ *T+ 6*pData.ddc0_*T*T)/(n*(n - 1))) ; //dj0 | ||
| 62 | // pts.push_back((n*n*pData.c0_ - n*pData.c0_ + 5*n*pData.dc0_*T - | ||
| 63 | // 5*pData.dc0_ *T+ 10*pData.ddc0_*T*T)/(n*(n - 1))) ; //ddj0 | ||
| 64 | |||
| 65 | // pts.push_back((n*n*pData.c1_ - n*pData.c1_ - 2*n*pData.dc1_*T + | ||
| 66 | // 2*pData.dc1_*T + pData.ddc1_*T*T)/(n*(n - 1))) ; | ||
| 67 | // //ddc1 // * T ?? pts.push_back((-pData.dc1_ * T / n) + pData.c1_); // dc1 | ||
| 68 | ✗ | pts.push_back(pData.c1_); // c1 | |
| 69 | ✗ | return pts; | |
| 70 | ✗ | } | |
| 71 | |||
| 72 | // up to jerk second derivativ constraints for goal, pos vel and acc constraint | ||
| 73 | // for init | ||
| 74 | ✗ | std::vector<bezier_t::point_t> computeConstantWaypointsGoalPredef( | |
| 75 | const ProblemData& pData, double T) { | ||
| 76 | ✗ | const double n = 4; | |
| 77 | ✗ | std::vector<bezier_t::point_t> pts; | |
| 78 | ✗ | pts.push_back(pData.c0_); // c0 | |
| 79 | // pts.push_back((pData.dc0_ * T / n )+ pData.c0_); //dc0 | ||
| 80 | // pts.push_back((n*n*pData.c0_ - n*pData.c0_ + 2*n*pData.dc0_*T - | ||
| 81 | // 2*pData.dc0_*T + pData.ddc0_*T*T)/(n*(n - 1))); | ||
| 82 | // //ddc0 // * T because derivation make a T appear | ||
| 83 | |||
| 84 | // pts.push_back((n*n*pData.c1_ - n*pData.c1_ - 5*n*pData.dc1_*T + | ||
| 85 | // 5*pData.dc1_*T + 10*pData.ddc1_*T*T)/(n*(n - 1))) ; //ddj1 | ||
| 86 | // pts.push_back((n*n*pData.c1_ - n*pData.c1_ - 4*n*pData.dc1_*T + | ||
| 87 | // 4*pData.dc1_*T + 6*pData.ddc1_*T*T)/(n*(n - 1))) ; //dj1 | ||
| 88 | ✗ | pts.push_back((n * n * pData.c1_ - n * pData.c1_ - 3 * n * pData.dc1_ * T + | |
| 89 | ✗ | 3 * pData.dc1_ * T + 3 * pData.ddc1_ * T * T) / | |
| 90 | ✗ | (n * (n - 1))); // j1 | |
| 91 | ✗ | pts.push_back((n * n * pData.c1_ - n * pData.c1_ - 2 * n * pData.dc1_ * T + | |
| 92 | ✗ | 2 * pData.dc1_ * T + pData.ddc1_ * T * T) / | |
| 93 | ✗ | (n * (n - 1))); // ddc1 * T ?? | |
| 94 | ✗ | pts.push_back((-pData.dc1_ * T / n) + pData.c1_); // dc1 | |
| 95 | ✗ | pts.push_back(pData.c1_); // c1 | |
| 96 | ✗ | return pts; | |
| 97 | ✗ | } | |
| 98 | |||
| 99 | ✗ | void computeConstraintsMatrix( | |
| 100 | const ProblemData& pData, const std::vector<waypoint_t>& wps_acc, | ||
| 101 | const std::vector<waypoint_t>& wps_vel, const VectorX& acc_bounds, | ||
| 102 | const VectorX& vel_bounds, MatrixXX& A, VectorX& b, | ||
| 103 | const std::vector<waypoint_t>& wps_jerk = std::vector<waypoint_t>(), | ||
| 104 | const VectorX& jerk_bounds = VectorX(DIM_POINT)) { | ||
| 105 | ✗ | assert(acc_bounds.size() == DIM_POINT && | |
| 106 | "Acceleration bounds should have the same dimension as the points"); | ||
| 107 | ✗ | assert(vel_bounds.size() == DIM_POINT && | |
| 108 | "Velocity bounds should have the same dimension as the points"); | ||
| 109 | ✗ | assert(jerk_bounds.size() == DIM_POINT && | |
| 110 | "Jerk bounds should have the same dimension as the points"); | ||
| 111 | ✗ | const int DIM_VAR = dimVar(pData); | |
| 112 | ✗ | int empty_acc = 0; | |
| 113 | ✗ | int empty_vel = 0; | |
| 114 | ✗ | int empty_jerk = 0; | |
| 115 | ✗ | for (std::vector<waypoint_t>::const_iterator wpcit = wps_acc.begin(); | |
| 116 | ✗ | wpcit != wps_acc.end(); ++wpcit) { | |
| 117 | ✗ | if (wpcit->first.isZero(std::numeric_limits<double>::epsilon())) | |
| 118 | ✗ | empty_acc++; | |
| 119 | } | ||
| 120 | ✗ | for (std::vector<waypoint_t>::const_iterator wpcit = wps_vel.begin(); | |
| 121 | ✗ | wpcit != wps_vel.end(); ++wpcit) { | |
| 122 | ✗ | if (wpcit->first.isZero(std::numeric_limits<double>::epsilon())) | |
| 123 | ✗ | empty_vel++; | |
| 124 | } | ||
| 125 | ✗ | for (std::vector<waypoint_t>::const_iterator wpcit = wps_jerk.begin(); | |
| 126 | ✗ | wpcit != wps_jerk.end(); ++wpcit) { | |
| 127 | ✗ | if (wpcit->first.isZero(std::numeric_limits<double>::epsilon())) | |
| 128 | ✗ | empty_jerk++; | |
| 129 | } | ||
| 130 | |||
| 131 | ✗ | A = MatrixXX::Zero( | |
| 132 | ✗ | (2 * DIM_POINT * | |
| 133 | ✗ | (wps_acc.size() - empty_acc + wps_vel.size() - empty_vel + | |
| 134 | ✗ | wps_jerk.size() - empty_jerk)) + | |
| 135 | ✗ | DIM_VAR, | |
| 136 | ✗ | DIM_VAR); // *2 because we have to put the lower and upper bound for each | |
| 137 | // one, +DIM_VAR for the constraint on x[z] | ||
| 138 | ✗ | b = VectorX::Zero(A.rows()); | |
| 139 | ✗ | int i = 0; | |
| 140 | |||
| 141 | // upper acc bounds | ||
| 142 | ✗ | for (std::vector<waypoint_t>::const_iterator wpcit = wps_acc.begin(); | |
| 143 | ✗ | wpcit != wps_acc.end(); ++wpcit) { | |
| 144 | ✗ | if (!wpcit->first.isZero(std::numeric_limits<double>::epsilon())) { | |
| 145 | ✗ | A.block(i * DIM_POINT, 0, DIM_POINT, DIM_VAR) = wpcit->first; | |
| 146 | ✗ | b.segment<DIM_POINT>(i * DIM_POINT) = acc_bounds - wpcit->second; | |
| 147 | ✗ | ++i; | |
| 148 | } | ||
| 149 | } | ||
| 150 | // lower acc bounds | ||
| 151 | ✗ | for (std::vector<waypoint_t>::const_iterator wpcit = wps_acc.begin(); | |
| 152 | ✗ | wpcit != wps_acc.end(); ++wpcit) { | |
| 153 | ✗ | if (!wpcit->first.isZero(std::numeric_limits<double>::epsilon())) { | |
| 154 | ✗ | A.block(i * DIM_POINT, 0, DIM_POINT, DIM_VAR) = -wpcit->first; | |
| 155 | ✗ | b.segment<DIM_POINT>(i * DIM_POINT) = acc_bounds + wpcit->second; | |
| 156 | ✗ | ++i; | |
| 157 | } | ||
| 158 | } | ||
| 159 | |||
| 160 | // upper velocity bounds | ||
| 161 | ✗ | for (std::vector<waypoint_t>::const_iterator wpcit = wps_vel.begin(); | |
| 162 | ✗ | wpcit != wps_vel.end(); ++wpcit) { | |
| 163 | ✗ | if (!wpcit->first.isZero(std::numeric_limits<double>::epsilon())) { | |
| 164 | ✗ | A.block(i * DIM_POINT, 0, DIM_POINT, DIM_VAR) = wpcit->first; | |
| 165 | ✗ | b.segment<DIM_POINT>(i * DIM_POINT) = vel_bounds - wpcit->second; | |
| 166 | ✗ | ++i; | |
| 167 | } | ||
| 168 | } | ||
| 169 | // lower velocity bounds | ||
| 170 | ✗ | for (std::vector<waypoint_t>::const_iterator wpcit = wps_vel.begin(); | |
| 171 | ✗ | wpcit != wps_vel.end(); ++wpcit) { | |
| 172 | ✗ | if (!wpcit->first.isZero(std::numeric_limits<double>::epsilon())) { | |
| 173 | ✗ | A.block(i * DIM_POINT, 0, DIM_POINT, DIM_VAR) = -wpcit->first; | |
| 174 | ✗ | b.segment<DIM_POINT>(i * DIM_POINT) = vel_bounds + wpcit->second; | |
| 175 | ✗ | ++i; | |
| 176 | } | ||
| 177 | } | ||
| 178 | |||
| 179 | // upper jerk bounds | ||
| 180 | ✗ | for (std::vector<waypoint_t>::const_iterator wpcit = wps_jerk.begin(); | |
| 181 | ✗ | wpcit != wps_jerk.end(); ++wpcit) { | |
| 182 | ✗ | if (!wpcit->first.isZero(std::numeric_limits<double>::epsilon())) { | |
| 183 | ✗ | A.block(i * DIM_POINT, 0, DIM_POINT, DIM_VAR) = wpcit->first; | |
| 184 | ✗ | b.segment<DIM_POINT>(i * DIM_POINT) = vel_bounds - wpcit->second; | |
| 185 | ✗ | ++i; | |
| 186 | } | ||
| 187 | } | ||
| 188 | // lower jerk bounds | ||
| 189 | ✗ | for (std::vector<waypoint_t>::const_iterator wpcit = wps_jerk.begin(); | |
| 190 | ✗ | wpcit != wps_jerk.end(); ++wpcit) { | |
| 191 | ✗ | if (!wpcit->first.isZero(std::numeric_limits<double>::epsilon())) { | |
| 192 | ✗ | A.block(i * DIM_POINT, 0, DIM_POINT, DIM_VAR) = -wpcit->first; | |
| 193 | ✗ | b.segment<DIM_POINT>(i * DIM_POINT) = jerk_bounds + wpcit->second; | |
| 194 | ✗ | ++i; | |
| 195 | } | ||
| 196 | } | ||
| 197 | |||
| 198 | // test : constraint x[z] to be always higher than init[z] and goal[z]. | ||
| 199 | // TODO replace z with the direction of the contact normal ... need to change | ||
| 200 | // the API | ||
| 201 | ✗ | MatrixXX mxz = MatrixXX::Zero(DIM_VAR, DIM_VAR); | |
| 202 | ✗ | int j = DIM_POINT - 1; | |
| 203 | ✗ | VectorX nxz = VectorX::Zero(DIM_VAR); | |
| 204 | ✗ | while (j < (DIM_VAR)) { | |
| 205 | ✗ | mxz(j, j) = -1; | |
| 206 | ✗ | nxz[j] = -std::min(pData.c0_[2], pData.c1_[2]); | |
| 207 | ✗ | j += DIM_POINT; | |
| 208 | } | ||
| 209 | ✗ | A.block(i * DIM_POINT, 0, DIM_VAR, DIM_VAR) = mxz; | |
| 210 | ✗ | b.segment(i * DIM_POINT, DIM_VAR) = nxz; | |
| 211 | |||
| 212 | // std::cout<<"(i*DIM_POINT + DIM_VAR) = " << (i*DIM_POINT + | ||
| 213 | // DIM_VAR)<<std::endl; std::cout<<"A rows = "<<A.rows()<<std::endl; | ||
| 214 | ✗ | assert((i * DIM_POINT + DIM_VAR) == A.rows() && | |
| 215 | "Constraints matrix were not correctly initialized"); | ||
| 216 | // TEST : | ||
| 217 | /* A.block<DIM_POINT,DIM_POINT>(i*DIM_POINT,0) = Matrix3::Identity(); | ||
| 218 | b.segment<DIM_POINT>(i*DIM_POINT) = Vector3(10,10,10); | ||
| 219 | i++; | ||
| 220 | A.block<DIM_POINT,DIM_POINT>(i*DIM_POINT,0) = -Matrix3::Identity(); | ||
| 221 | b.segment<DIM_POINT>(i*DIM_POINT) = Vector3(10,10,10);*/ | ||
| 222 | ✗ | } | |
| 223 | |||
| 224 | ✗ | std::pair<MatrixXX, VectorX> computeDistanceCostFunction( | |
| 225 | size_t numPoints, const ProblemData& pData, double T, | ||
| 226 | std::vector<point3_t> pts_path) { | ||
| 227 | ✗ | assert(numPoints == pts_path.size() && | |
| 228 | "Pts_path size must be equal to numPoints"); | ||
| 229 | ✗ | double step = 1. / (double)(numPoints - 1); | |
| 230 | ✗ | std::vector<point_t> pi = computeConstantWaypoints(pData, T); | |
| 231 | ✗ | waypoint_t c_wp; | |
| 232 | ✗ | MatrixXX H = MatrixXX::Zero(dimVar(pData), dimVar(pData)); | |
| 233 | ✗ | VectorX g = VectorX::Zero(dimVar(pData)); | |
| 234 | ✗ | point3_t pk; | |
| 235 | ✗ | for (size_t i = 0; i < numPoints; ++i) { | |
| 236 | ✗ | c_wp = evaluateCurveWaypointAtTime(pData, pi, (double)i * step); | |
| 237 | ✗ | pk = pts_path[i]; | |
| 238 | // std::cout<<"pk = "<<pk.transpose()<<std::endl; | ||
| 239 | // std::cout<<"coef First : "<<ckcit->first<<std::endl; | ||
| 240 | // std::cout<<"coef second : "<<ckcit->second.transpose()<<std::endl; | ||
| 241 | ✗ | H += (c_wp.first.transpose() * c_wp.first); | |
| 242 | ✗ | g += ((c_wp.second - pk).transpose() * c_wp.first).transpose(); | |
| 243 | } | ||
| 244 | ✗ | double norm = H.norm(); | |
| 245 | ✗ | H /= norm; | |
| 246 | ✗ | g /= norm; | |
| 247 | ✗ | return std::make_pair(H, g); | |
| 248 | ✗ | } | |
| 249 | |||
| 250 | template <typename Path> | ||
| 251 | ✗ | std::pair<MatrixXX, VectorX> computeDistanceCostFunction( | |
| 252 | size_t numPoints, const ProblemData& pData, double T, const Path& path) { | ||
| 253 | ✗ | double step = 1. / (double)(numPoints - 1); | |
| 254 | ✗ | std::vector<point3_t> pts_path; | |
| 255 | ✗ | for (size_t i = 0; i < numPoints; ++i) | |
| 256 | ✗ | pts_path.push_back(path(((double)i * step))); | |
| 257 | ✗ | return computeDistanceCostFunction(numPoints, pData, T, pts_path); | |
| 258 | ✗ | } | |
| 259 | |||
| 260 | // TODO | ||
| 261 | ✗ | void computeC_of_T(const ProblemData& pData, double T, ResultDataCOMTraj& res) { | |
| 262 | ✗ | std::vector<Vector3> wps = computeConstantWaypoints(pData, T); | |
| 263 | ✗ | if (dimVar(pData) == 3) | |
| 264 | ✗ | wps[4] = res.x; // FIXME : compute id from constraints | |
| 265 | ✗ | else if (dimVar(pData) == 9) { | |
| 266 | ✗ | wps[4] = res.x.segment<3>(0); | |
| 267 | ✗ | wps[5] = res.x.segment<3>(3); | |
| 268 | ✗ | wps[6] = res.x.segment<3>(6); | |
| 269 | ✗ | } else if (dimVar(pData) == 15) { | |
| 270 | ✗ | wps[4] = res.x.segment<3>(0); | |
| 271 | ✗ | wps[5] = res.x.segment<3>(3); | |
| 272 | ✗ | wps[6] = res.x.segment<3>(6); | |
| 273 | ✗ | wps[7] = res.x.segment<3>(9); | |
| 274 | ✗ | wps[8] = res.x.segment<3>(12); | |
| 275 | } | ||
| 276 | ✗ | res.c_of_t_ = bezier_t(wps.begin(), wps.end(), 0, T); | |
| 277 | if (verbose) | ||
| 278 | std::cout << "bezier curve created, size = " << res.c_of_t_.size_ | ||
| 279 | << std::endl; | ||
| 280 | ✗ | } | |
| 281 | |||
| 282 | ✗ | void computeVelCostFunctionDiscretized(int numPoints, const ProblemData& pData, | |
| 283 | double T, MatrixXX& H, VectorX& g) { | ||
| 284 | ✗ | double step = 1. / (numPoints - 1); | |
| 285 | ✗ | std::vector<waypoint_t> cks; | |
| 286 | ✗ | std::vector<point_t> pi = computeConstantWaypoints(pData, T); | |
| 287 | ✗ | for (int i = 0; i < numPoints; ++i) { | |
| 288 | ✗ | cks.push_back(evaluateVelocityCurveWaypointAtTime(pData, T, pi, i * step)); | |
| 289 | } | ||
| 290 | ✗ | H = MatrixXX::Zero(dimVar(pData), dimVar(pData)); | |
| 291 | ✗ | g = VectorX::Zero(dimVar(pData)); | |
| 292 | ✗ | for (std::vector<waypoint_t>::const_iterator ckcit = cks.begin(); | |
| 293 | ✗ | ckcit != cks.end(); ++ckcit) { | |
| 294 | // H+=(ckcit->first.transpose() * ckcit->first); | ||
| 295 | // g+=ckcit->second.transpose() * ckcit->first; | ||
| 296 | ✗ | for (int i = 0; i < (dimVar(pData) / 3); ++i) { | |
| 297 | ✗ | H.block<3, 3>(i * 3, i * 3) += | |
| 298 | ✗ | Matrix3::Identity() * ckcit->first(0, i * 3) * ckcit->first(0, i * 3); | |
| 299 | ✗ | g.segment<3>(i * 3) += | |
| 300 | ✗ | ckcit->second.segment<3>(0) * ckcit->first(0, i * 3); | |
| 301 | } | ||
| 302 | } | ||
| 303 | // TEST : don't consider z axis for minimum acceleration cost | ||
| 304 | // H(2,2) = 1e-6; | ||
| 305 | // g[2] = 1e-6 ; | ||
| 306 | // normalize : | ||
| 307 | // double norm=H.norm(); // because H is always diagonal | ||
| 308 | // H /= norm; | ||
| 309 | // g /= norm; | ||
| 310 | ✗ | } | |
| 311 | |||
| 312 | ✗ | void computeAccelerationCostFunctionDiscretized(int numPoints, | |
| 313 | const ProblemData& pData, | ||
| 314 | double T, MatrixXX& H, | ||
| 315 | VectorX& g) { | ||
| 316 | ✗ | double step = 1. / (numPoints - 1); | |
| 317 | ✗ | std::vector<waypoint_t> cks; | |
| 318 | ✗ | std::vector<point_t> pi = computeConstantWaypoints(pData, T); | |
| 319 | ✗ | for (int i = 0; i < numPoints; ++i) { | |
| 320 | ✗ | cks.push_back( | |
| 321 | ✗ | evaluateAccelerationCurveWaypointAtTime(pData, T, pi, i * step)); | |
| 322 | } | ||
| 323 | ✗ | H = MatrixXX::Zero(dimVar(pData), dimVar(pData)); | |
| 324 | ✗ | g = VectorX::Zero(dimVar(pData)); | |
| 325 | ✗ | for (std::vector<waypoint_t>::const_iterator ckcit = cks.begin(); | |
| 326 | ✗ | ckcit != cks.end(); ++ckcit) { | |
| 327 | ✗ | H += (ckcit->first.transpose() * ckcit->first); | |
| 328 | ✗ | g += ckcit->first.transpose() * ckcit->second; | |
| 329 | } | ||
| 330 | // TEST : don't consider z axis for minimum acceleration cost | ||
| 331 | // H(2,2) = 1e-6; | ||
| 332 | // g[2] = 1e-6 ; | ||
| 333 | // normalize : | ||
| 334 | // double norm=H.norm(); // because H is always diagonal | ||
| 335 | // H /= norm; | ||
| 336 | // g /= norm; | ||
| 337 | ✗ | } | |
| 338 | |||
| 339 | ✗ | void computeJerkCostFunctionDiscretized(int numPoints, const ProblemData& pData, | |
| 340 | double T, MatrixXX& H, VectorX& g) { | ||
| 341 | ✗ | double step = 1. / (numPoints - 1); | |
| 342 | |||
| 343 | ✗ | std::vector<waypoint_t> cks; | |
| 344 | ✗ | std::vector<point_t> pi = computeConstantWaypoints(pData, T); | |
| 345 | ✗ | for (int i = 0; i < numPoints; ++i) { | |
| 346 | ✗ | cks.push_back(evaluateJerkCurveWaypointAtTime(pData, T, pi, i * step)); | |
| 347 | } | ||
| 348 | ✗ | H = MatrixXX::Zero(dimVar(pData), dimVar(pData)); | |
| 349 | ✗ | g = VectorX::Zero(dimVar(pData)); | |
| 350 | ✗ | for (std::vector<waypoint_t>::const_iterator ckcit = cks.begin(); | |
| 351 | ✗ | ckcit != cks.end(); ++ckcit) { | |
| 352 | ✗ | H += (ckcit->first.transpose() * ckcit->first); | |
| 353 | ✗ | g += ckcit->first.transpose() * ckcit->second; | |
| 354 | } | ||
| 355 | // TEST : don't consider z axis for minimum acceleration cost | ||
| 356 | // H(2,2) = 1e-6; | ||
| 357 | // g[2] = 1e-6 ; | ||
| 358 | // normalize : | ||
| 359 | // double norm=H.norm(); // because H is always diagonal | ||
| 360 | // H /= norm; | ||
| 361 | // g /= norm; | ||
| 362 | ✗ | } | |
| 363 | |||
| 364 | ✗ | std::pair<MatrixXX, VectorX> computeEndEffectorConstraints( | |
| 365 | const ProblemData& pData, const double T, | ||
| 366 | std::vector<bezier_t::point_t> pi) { | ||
| 367 | ✗ | std::vector<waypoint_t> wps_jerk = computeJerkWaypoints(pData, T, pi); | |
| 368 | ✗ | std::vector<waypoint_t> wps_acc = computeAccelerationWaypoints(pData, T, pi); | |
| 369 | ✗ | std::vector<waypoint_t> wps_vel = computeVelocityWaypoints(pData, T, pi); | |
| 370 | // stack the constraint for each waypoint : | ||
| 371 | Vector3 jerk_bounds(10000, 10000, | ||
| 372 | ✗ | 10000); // TODO : read it from somewhere (ProblemData ?) | |
| 373 | ✗ | Vector3 acc_bounds(10000, 10000, 10000); | |
| 374 | ✗ | Vector3 vel_bounds(10000, 10000, 10000); | |
| 375 | ✗ | MatrixXX A; | |
| 376 | ✗ | VectorX b; | |
| 377 | ✗ | computeConstraintsMatrix(pData, wps_acc, wps_vel, acc_bounds, vel_bounds, A, | |
| 378 | b, wps_jerk, jerk_bounds); | ||
| 379 | ✗ | return std::make_pair(A, b); | |
| 380 | ✗ | } | |
| 381 | |||
| 382 | template <typename Path> | ||
| 383 | ✗ | std::pair<MatrixXX, VectorX> computeEndEffectorCost( | |
| 384 | const ProblemData& pData, const Path& path, const double T, | ||
| 385 | const double weightDistance, bool /*useVelCost*/, | ||
| 386 | std::vector<bezier_t::point_t> pi) { | ||
| 387 | ✗ | assert(weightDistance >= 0. && weightDistance <= 1. && | |
| 388 | "WeightDistance must be between 0 and 1"); | ||
| 389 | ✗ | double weightSmooth = 1. - weightDistance; | |
| 390 | ✗ | const int DIM_VAR = dimVar(pData); | |
| 391 | // compute distance cost function (discrete integral under the curve defined | ||
| 392 | // by 'path') | ||
| 393 | ✗ | MatrixXX H; | |
| 394 | ✗ | VectorX g; | |
| 395 | ✗ | std::pair<MatrixXX, VectorX> Hg_smooth, Hg_rrt; | |
| 396 | |||
| 397 | ✗ | if (weightDistance > 0) | |
| 398 | ✗ | Hg_rrt = computeDistanceCostFunction<Path>(50, pData, T, path); | |
| 399 | else { | ||
| 400 | ✗ | Hg_rrt.first = MatrixXX::Zero(DIM_VAR, DIM_VAR); | |
| 401 | ✗ | Hg_rrt.second = VectorX::Zero(DIM_VAR); | |
| 402 | } | ||
| 403 | |||
| 404 | ✗ | Hg_smooth = computeVelocityCost(pData, T, pi); | |
| 405 | |||
| 406 | /* std::cout<<"End eff H_rrt = "<<std::endl<<H_rrt<<std::endl; | ||
| 407 | std::cout<<"End eff g_rrt = "<<std::endl<<g_rrt<<std::endl; | ||
| 408 | std::cout<<"End eff H_acc = "<<std::endl<<H_acc<<std::endl; | ||
| 409 | std::cout<<"End eff g_acc = "<<std::endl<<g_acc<<std::endl; | ||
| 410 | */ | ||
| 411 | // add the costs : | ||
| 412 | ✗ | H = MatrixXX::Zero(DIM_VAR, DIM_VAR); | |
| 413 | ✗ | g = VectorX::Zero(DIM_VAR); | |
| 414 | ✗ | H = weightSmooth * (Hg_smooth.first) + weightDistance * Hg_rrt.first; | |
| 415 | ✗ | g = weightSmooth * (Hg_smooth.second) + weightDistance * Hg_rrt.second; | |
| 416 | // H = Hg_smooth.first; | ||
| 417 | // g = Hg_smooth.second; | ||
| 418 | |||
| 419 | ✗ | return std::make_pair(H, g); | |
| 420 | ✗ | } | |
| 421 | |||
| 422 | template <typename Path> | ||
| 423 | ✗ | ResultDataCOMTraj solveEndEffector(const ProblemData& pData, const Path& path, | |
| 424 | const double T, const double weightDistance, | ||
| 425 | bool useVelCost) { | ||
| 426 | if (verbose) std::cout << "solve end effector, T = " << T << std::endl; | ||
| 427 | ✗ | std::vector<bezier_t::point_t> pi = computeConstantWaypoints(pData, T); | |
| 428 | ✗ | std::pair<MatrixXX, VectorX> Ab = computeEndEffectorConstraints(pData, T, pi); | |
| 429 | ✗ | std::pair<MatrixXX, VectorX> Hg = | |
| 430 | computeEndEffectorCost(pData, path, T, weightDistance, useVelCost, pi); | ||
| 431 | if (verbose) { | ||
| 432 | std::cout << "End eff A = " << std::endl << Ab.first << std::endl; | ||
| 433 | std::cout << "End eff b = " << std::endl << Ab.second << std::endl; | ||
| 434 | std::cout << "End eff H = " << std::endl << Hg.first << std::endl; | ||
| 435 | std::cout << "End eff g = " << std::endl << Hg.second << std::endl; | ||
| 436 | std::cout << "Dim Var = " << dimVar(pData) << std::endl; | ||
| 437 | std::cout << "Dim H = " << Hg.first.rows() << " x " << Hg.first.cols() | ||
| 438 | << std::endl; | ||
| 439 | std::cout << "Dim g = " << Hg.second.rows() << std::endl; | ||
| 440 | std::cout << "Dim A = " << Ab.first.rows() << " x " << Ab.first.cols() | ||
| 441 | << std::endl; | ||
| 442 | std::cout << "Dim b = " << Ab.first.rows() << std::endl; | ||
| 443 | } | ||
| 444 | |||
| 445 | ✗ | VectorX init = VectorX(dimVar(pData)); | |
| 446 | // init = (pData.c0_ + pData.c1_)/2.; | ||
| 447 | // init =pData.c0_; | ||
| 448 | if (verbose) | ||
| 449 | std::cout << "Init = " << std::endl << init.transpose() << std::endl; | ||
| 450 | |||
| 451 | ✗ | ResultData resQp = solve(Ab, Hg, init); | |
| 452 | |||
| 453 | ✗ | ResultDataCOMTraj res; | |
| 454 | ✗ | if (resQp.success_) { | |
| 455 | ✗ | res.success_ = true; | |
| 456 | ✗ | res.x = resQp.x; | |
| 457 | // computeRealCost(pData, res); | ||
| 458 | ✗ | computeC_of_T(pData, T, res); | |
| 459 | // computedL_of_T(pData,Ts,res); | ||
| 460 | } | ||
| 461 | if (verbose) { | ||
| 462 | std::cout << "Solved, success = " << res.success_ | ||
| 463 | << " x = " << res.x.transpose() << std::endl; | ||
| 464 | std::cout << "Final cost : " << resQp.cost_ << std::endl; | ||
| 465 | } | ||
| 466 | ✗ | return res; | |
| 467 | ✗ | } | |
| 468 | |||
| 469 | } // namespace bezier_com_traj | ||
| 470 |