|
| 1 | +#include <chrono> |
| 2 | +#include <vector> |
| 3 | +#include <array> |
| 4 | +#include <utility> |
| 5 | +#include <iostream> |
| 6 | + |
| 7 | +#include <vamp/collision/factory.hh> |
| 8 | +#include <vamp/robots/panda.hh> |
| 9 | +#include <vamp/random/halton.hh> |
| 10 | + |
| 11 | +using Robot = vamp::robots::Panda; |
| 12 | +static constexpr const std::size_t rake = vamp::FloatVectorWidth; |
| 13 | +using EnvironmentInput = vamp::collision::Environment<float>; |
| 14 | +using EnvironmentVector = vamp::collision::Environment<vamp::FloatVector<rake>>; |
| 15 | + |
| 16 | +// Spheres for the cage problem - (x, y, z) center coordinates with fixed, common radius defined below |
| 17 | +static const std::vector<std::array<float, 3>> problem = { |
| 18 | + {0.55, 0, 0.25}, |
| 19 | + {0.35, 0.35, 0.25}, |
| 20 | + {0, 0.55, 0.25}, |
| 21 | + {-0.55, 0, 0.25}, |
| 22 | + {-0.35, -0.35, 0.25}, |
| 23 | + {0, -0.55, 0.25}, |
| 24 | + {0.35, -0.35, 0.25}, |
| 25 | + {-0.35, 0.35, 0.25}, |
| 26 | + {0.35, 0.35, 0.8}, |
| 27 | + {0, 0.55, 0.8}, |
| 28 | + {-0.35, 0.35, 0.8}, |
| 29 | + {-0.55, 0, 0.8}, |
| 30 | + {-0.35, -0.35, 0.8}, |
| 31 | + {0, -0.55, 0.8}, |
| 32 | + {0.35, -0.35, 0.8}, |
| 33 | + {0.55, 0, 0.8}, |
| 34 | +}; |
| 35 | + |
| 36 | +// Radius for obstacle spheres |
| 37 | +static constexpr float radius = 0.2; |
| 38 | + |
| 39 | +auto main(int, char **) -> int |
| 40 | +{ |
| 41 | + // Build sphere cage environment |
| 42 | + EnvironmentInput environment; |
| 43 | + for (const auto &sphere : problem) |
| 44 | + { |
| 45 | + environment.spheres.emplace_back(vamp::collision::factory::sphere::array(sphere, radius)); |
| 46 | + } |
| 47 | + |
| 48 | + environment.sort(); |
| 49 | + auto env_v = EnvironmentVector(environment); |
| 50 | + |
| 51 | + // Benchmark |
| 52 | + vamp::rng::Halton<Robot> sampler; |
| 53 | + int n_samples = 1000; |
| 54 | + int n_success = 0; |
| 55 | + double total_time_ms = 0.0; |
| 56 | + int total_iter = 0; |
| 57 | + std::cout << "Starting Benchmark with " << n_samples << " samples..." << std::endl; |
| 58 | + int i = 0; |
| 59 | + while (i < n_samples) |
| 60 | + { |
| 61 | + auto q_random = sampler.next(); |
| 62 | + // std::cout << "Sample " << i << ": " << q_random << std::endl; |
| 63 | + Robot::ConfigurationBlock<rake> b; |
| 64 | + for (auto k = 0U; k < Robot::dimension; ++k) |
| 65 | + { |
| 66 | + b[k] = q_random.broadcast(k); |
| 67 | + } |
| 68 | + auto valid = Robot::fkcc<rake>(env_v, b); |
| 69 | + if (valid) |
| 70 | + { |
| 71 | + continue; |
| 72 | + } |
| 73 | + i++; |
| 74 | + |
| 75 | + // Project |
| 76 | + auto start_t = std::chrono::steady_clock::now(); |
| 77 | + |
| 78 | + float current_min_dist = -1e9f; |
| 79 | + int iter = 0; |
| 80 | + const int max_iters = 100; |
| 81 | + float alpha = 0.1f; |
| 82 | + |
| 83 | + while (current_min_dist < 0 && iter < max_iters) |
| 84 | + { |
| 85 | + // Re-evaluate |
| 86 | + auto res = Robot::sdf_gradient(env_v, b); |
| 87 | + |
| 88 | + auto dists_arr = res.first.to_array(); |
| 89 | + current_min_dist = 1e9f; |
| 90 | + for (auto d : dists_arr) |
| 91 | + { |
| 92 | + if (d < current_min_dist) |
| 93 | + { |
| 94 | + current_min_dist = d; |
| 95 | + } |
| 96 | + } |
| 97 | + |
| 98 | + if (current_min_dist >= 0) |
| 99 | + { |
| 100 | + break; |
| 101 | + } |
| 102 | + |
| 103 | + Robot::ConfigurationBlock<rake> dq_block; |
| 104 | + Robot::d_collision_d_q(b, res.second, dq_block); // b is already the block for q_new |
| 105 | + std::vector<float> dq(Robot::dimension); |
| 106 | + for (auto k = 0U; k < Robot::dimension; ++k) |
| 107 | + { |
| 108 | + dq[k] = dq_block[k].element(0); |
| 109 | + } |
| 110 | + |
| 111 | + float dq_norm = 0.0f; |
| 112 | + for (float v : dq) |
| 113 | + { |
| 114 | + dq_norm += v * v; |
| 115 | + } |
| 116 | + dq_norm = std::sqrt(dq_norm); |
| 117 | + |
| 118 | + if (dq_norm > std::numeric_limits<float>::epsilon()) |
| 119 | + { |
| 120 | + for (auto k = 0U; k < Robot::dimension; ++k) |
| 121 | + { |
| 122 | + b[k] = b[k] + alpha * (dq[k] / dq_norm); |
| 123 | + } |
| 124 | + } |
| 125 | + else |
| 126 | + { |
| 127 | + break; |
| 128 | + } |
| 129 | + iter++; |
| 130 | + } |
| 131 | + auto end_t = std::chrono::steady_clock::now(); |
| 132 | + auto dur = std::chrono::duration_cast<std::chrono::nanoseconds>(end_t - start_t); |
| 133 | + auto b_final = b; |
| 134 | + valid = Robot::fkcc<rake>(env_v, b_final); |
| 135 | + if (valid) |
| 136 | + { |
| 137 | + n_success++; |
| 138 | + } |
| 139 | + total_time_ms += dur.count() / 1e6; |
| 140 | + total_iter += iter; |
| 141 | + } |
| 142 | + |
| 143 | + std::cout << "Benchmark Results:" << std::endl; |
| 144 | + std::cout << "Total Samples: " << n_samples << std::endl; |
| 145 | + std::cout << "Successful Projections: " << n_success << " (" |
| 146 | + << (n_samples > 0 ? (100.0 * n_success / n_samples) : 0.0) << "%)" << std::endl; |
| 147 | + if (n_success > 0) |
| 148 | + { |
| 149 | + std::cout << "Average Projection Time: " << (total_time_ms / n_samples) << " ms" << std::endl; |
| 150 | + std::cout << "Average Iterations: " << (total_iter / n_samples) << std::endl; |
| 151 | + } |
| 152 | + |
| 153 | + return 0; |
| 154 | +} |
0 commit comments