44 std::vector<double> genes;
45 std::vector<double> gradients;
52 size_t variable_count, tip_count;
53 std::vector<double> table;
54 std::vector<double> chain_lengths;
55 std::vector<std::vector<double>> chain_lengths_2;
59 HeuristicErrorTree(moveit::core::RobotModelConstPtr robot_model,
const std::vector<std::string>& tip_names)
61 tip_count = tip_names.size();
62 variable_count = robot_model->getVariableCount();
63 table.resize(tip_count * variable_count);
64 for(
size_t tip_index = 0; tip_index < tip_count; tip_index++)
66 auto& tip_name = tip_names[tip_index];
67 for(
auto* link_model = robot_model->getLinkModel(tip_name); link_model; link_model = link_model->getParentLinkModel())
69 auto* joint_model = link_model->getParentJointModel();
70 size_t v1 = joint_model->getFirstVariableIndex();
71 size_t vn = joint_model->getVariableCount();
72 for(
size_t variable_index = v1; variable_index < v1 + vn; variable_index++)
73 table[variable_index * tip_count + tip_index] = 1;
76 for(
size_t variable_index = 0; variable_index < variable_count; variable_index++)
79 for(
size_t tip_index = 0; tip_index < tip_count; tip_index++)
80 sum += table[variable_index * tip_count + tip_index];
82 for(
size_t tip_index = 0; tip_index < tip_count; tip_index++)
83 table[variable_index * tip_count + tip_index] /= sum;
86 chain_lengths.resize(tip_count);
87 for(
size_t tip_index = 0; tip_index < tip_count; tip_index++)
89 auto& tip_name = tip_names[tip_index];
90 double chain_length = 0;
91 for(
auto* link_model = robot_model->getLinkModel(tip_name); link_model; link_model = link_model->getParentLinkModel())
93 chain_length += Frame(link_model->getJointOriginTransform()).pos.length();
95 chain_lengths[tip_index] = chain_length;
98 chain_lengths_2.resize(tip_count);
99 for(
size_t tip_index = 0; tip_index < tip_count; tip_index++)
101 auto& tip_name = tip_names[tip_index];
102 double chain_length = 0;
103 chain_lengths_2[tip_index].resize(variable_count, 0.0);
104 for(
auto* link_model = robot_model->getLinkModel(tip_name); link_model; link_model = link_model->getParentLinkModel())
107 auto* joint_model = link_model->getParentJointModel();
108 int vmin = joint_model->getFirstVariableIndex();
109 int vmax = vmin + joint_model->getVariableCount();
110 for(
int vi = vmin; vi < vmax; vi++)
111 chain_lengths_2[tip_index][vi] = chain_length;
112 chain_length += Frame(link_model->getJointOriginTransform()).pos.length();
116 inline double getInfluence(
size_t variable_index,
size_t tip_index)
const {
return table[variable_index * tip_count + tip_index]; }
117 inline double getChainLength(
size_t tip_index)
const {
return chain_lengths[tip_index]; }
118 inline double getJointVariableChainLength(
size_t tip_index,
size_t variable_index)
const {
return chain_lengths_2[tip_index][variable_index]; }
122 std::vector<double> solution;
123 std::vector<Individual> population;
124 int populationSize, eliteCount;
125 std::vector<Individual*> tempPool;
126 std::vector<Individual> tempOffspring;
127 std::vector<double> initialGuess;
135 opt_no_wipeout = p.opt_no_wipeout;
136 populationSize = p.population_size;
137 eliteCount = p.elite_count;
138 linear_fitness = p.linear_fitness;
141 bool in_final_adjustment_loop;
143 template <
class t>
inline t select(
const std::vector<t>& v)
147 size_t index = d(rng);
151 inline double clip(
double v,
size_t i) {
return modelInfo.clip(v, i); }
153 inline double getMutationStrength(
size_t i,
const Individual& parentA,
const Individual& parentB)
155 double extinction = 0.5 * (parentA.extinction + parentB.extinction);
156 double span = modelInfo.getSpan(i);
157 return span * extinction;
160 double computeAngularScale(
size_t tip_index,
const Frame& tip_frame)
162 double angular_scale = sqrt(heuristicErrorTree.getChainLength(tip_index) * tip_frame.pos.length()) / M_PI;
163 return angular_scale;
171 double getHeuristicError(
size_t variable_index,
bool balanced)
175 double heuristic_error = 0;
177 for(
int tip_index = 0; tip_index < problem.goals.size(); tip_index++)
179 double influence = heuristicErrorTree.getInfluence(variable_index, tip_index);
180 if(influence == 0)
continue;
183 const auto& ta = problem.goals[tip_index].frame;
184 const auto& tb = model.getTipFrame(tip_index);
186 double length = heuristicErrorTree.getJointVariableChainLength(tip_index, variable_index);
194 if(modelInfo.isPrismatic(variable_index))
201 heuristic_error += ta.pos.distance(tb.pos) * influence * 0.5;
202 heuristic_error += ta.rot.angle(tb.rot) * length * influence * 0.5;
206 heuristic_error += ta.pos.distance(tb.pos) * influence;
210 if(modelInfo.isRevolute(variable_index))
217 heuristic_error += ta.pos.distance(tb.pos) / length * influence * 0.5;
218 heuristic_error += ta.rot.angle(tb.rot) * influence * 0.5;
222 heuristic_error += ta.rot.angle(tb.rot) * influence;
233 return heuristic_error;
236 bool in_adjustment_2, in_get_solution_fitness;
242 for(
auto i : problem.active_variables)
244 offspring.genes[i] = random(modelInfo.getMin(i), modelInfo.getMax(i));
246 offspring.genes[i] = mix(offspring.genes[i], (modelInfo.getMin(i) + modelInfo.getMax(i)) * 0.5, random(0.0, 0.1));
248 offspring.gradients[i] = 0;
250 offspring.fitness = computeFitness(offspring.genes,
false);
253 double computeFitness(
const std::vector<double>& genes,
bool balanced)
257 model.applyConfiguration(genes);
258 double fitness_sum = 0.0;
259 for(
size_t goal_index = 0; goal_index < problem.goals.size(); goal_index++)
261 const auto& ta = problem.goals[goal_index].frame;
262 const auto& tb = model.getTipFrame(problem.goals[goal_index].tip_index);
264 double tdist = ta.pos.distance(tb.pos) / computeAngularScale(problem.goals[goal_index].tip_index, ta);
265 double rdist = ta.rot.angle(tb.rot);
267 fitness_sum += mix(tdist, rdist, (balanced || in_final_adjustment_loop) ? 0.5 : random());
273 return IKBase::computeFitness(genes);
280 auto& genes = population[0].genes;
282 for(
auto i : problem.active_variables)
284 double v0 = genes[i];
285 double fitness = computeFitness(genes,
true);
286 double heuristicError = getHeuristicError(i,
true);
288 genes[i] = modelInfo.clip(v0 + random(0, heuristicError), i);
289 double incFitness = computeFitness(genes,
true);
290 genes[i] = modelInfo.clip(v0 - random(0, heuristicError), i);
291 double decFitness = computeFitness(genes,
true);
293 if(incFitness < fitness || decFitness < fitness)
303 void computeExtinctions()
305 double min = population.front().fitness;
306 double max = population.back().fitness;
307 for(
size_t i = 0; i < populationSize; i++)
309 double grading = (double)i / (
double)(populationSize - 1);
310 population[i].extinction = (population[i].fitness + min * (grading - 1)) / max;
314 bool tryUpdateSolution()
317 double solutionFitness = computeFitness(solution,
true);
318 double candidateFitness = computeFitness(population[0].genes,
true);
321 if(candidateFitness < solutionFitness)
323 solution = population[0].genes;
334 double extinction = 0.5 * (parentA.extinction + parentB.extinction);
335 double inverse = 1.0 / parentA.genes.size();
336 return extinction * (1.0 - inverse) + inverse;
342 sort(population.begin(), population.end(), [](
const Individual& a,
const Individual& b) {
return a.fitness < b.fitness; });
345 double bounce(
double v,
int i)
347 double c = clip(v, i);
357 for(
size_t i = 0; i < offspring.genes.size(); i++)
360 offspring.genes[i] = mix(parentA.genes[i], parentB.genes[i], random());
361 offspring.genes[i] += parentA.gradients[i] * random();
362 offspring.genes[i] += parentB.gradients[i] * random();
364 double storage = offspring.genes[i];
366 if(random() < getMutationProbability(parentA, parentB)) offspring.genes[i] += random(-1, 1) * getMutationStrength(i, parentA, parentB);
369 offspring.genes[i] += mix(random() * (0.5 * (parentA.genes[i] + parentB.genes[i]) - offspring.genes[i]), random() * (prototype.genes[i] - offspring.genes[i]), random());
377 offspring.genes[i] = clip(offspring.genes[i], i);
381 offspring.gradients[i] = random() * offspring.gradients[i] + offspring.genes[i] - storage;
384 offspring.fitness = computeFitness(offspring.genes,
false);
391 double fitness_sum = 0;
395 for(
auto i : problem.active_variables)
397 double fitness = computeFitness(individual.genes,
true);
399 double heuristicError = getHeuristicError(i,
true);
400 double v_0 = individual.genes[i];
402 double v_inc = clip(v_0 + random(0, heuristicError), i);
403 double v_dec = clip(v_0 - random(0, heuristicError), i);
405 individual.genes[i] = v_inc;
406 double inc_fitness = computeFitness(individual.genes,
true);
407 individual.genes[i] = v_dec;
408 double dec_fitness = computeFitness(individual.genes,
true);
410 if(inc_fitness < fitness && inc_fitness <= dec_fitness)
412 individual.genes[i] = v_inc;
413 individual.gradients[i] = v_0 * random() + v_inc - v_0;
414 fitness_sum += inc_fitness;
416 else if(dec_fitness < fitness && dec_fitness <= inc_fitness)
418 individual.genes[i] = v_dec;
419 individual.gradients[i] = v_0 * random() + v_dec - v_0;
420 fitness_sum += dec_fitness;
424 individual.genes[i] = v_0;
425 fitness_sum += fitness;
431 individual.fitness = fitness_sum / individual.genes.size();
438 , in_final_adjustment_loop(
false)
439 , in_adjustment_2(
false)
440 , in_get_solution_fitness(
false)
447 initialGuess = problem.initial_guess;
448 solution = initialGuess;
450 population.resize(populationSize);
453 auto& p = population[0];
456 p.gradients.resize(p.genes.size(), 0);
457 p.fitness = computeFitness(p.genes,
false);
460 for(
int i = 1; i < populationSize; i++)
462 auto& p = population[i];
465 p.gradients.resize(p.genes.size(), 0);
470 computeExtinctions();
473 void initialize(
const Problem& problem)
475 IKBase::initialize(problem);
477 std::vector<std::string> tips;
478 for(
auto tip_link_index : problem.tip_link_indices)
479 tips.push_back(params.robot_model->getLinkModelNames()[tip_link_index]);
485 const std::vector<double>& getSolution()
const {
return solution; }
487 double getSolutionFitness()
489 in_get_solution_fitness =
true;
490 double f = computeFitness(solution,
true);
491 in_get_solution_fitness =
false;
495 const std::vector<Frame>& getSolutionTipFrames()
497 model.applyConfiguration(solution);
498 return model.getTipFrames();
505 auto& offspring = tempOffspring;
506 offspring = population;
508 for(
size_t i = 0; i < eliteCount; i++)
510 offspring[i] = population[i];
511 exploit(offspring[i]);
514 auto& pool = tempPool;
515 pool.resize(populationSize);
516 iota(pool.begin(), pool.end(), &population[0]);
518 for(
size_t i = eliteCount; i < populationSize; i++)
522 auto& parentA = *select(pool);
523 auto& parentB = *select(pool);
524 auto& prototype = *select(pool);
525 reproduce(offspring[i], parentA, parentB, prototype);
526 if(offspring[i].fitness < parentA.fitness) pool.erase(
remove(pool.begin(), pool.end(), &parentA), pool.end());
527 if(offspring[i].fitness < parentB.fitness) pool.erase(
remove(pool.begin(), pool.end(), &parentB), pool.end());
531 reroll(offspring[i]);
535 population = offspring;
539 computeExtinctions();
541 if(tryUpdateSolution())
return true;
542 if(opt_no_wipeout)
return false;
543 if(!checkWipeout())
return false;
547 return tryUpdateSolution();
552 in_adjustment_2 =
false;
556 virtual size_t concurrency()
const {
return 4; }