Try to fix pillar route search
This commit is contained in:
parent
3d6bb38dd4
commit
cdac790163
@ -141,7 +141,9 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<size_t N>
|
template<size_t N>
|
||||||
void set_up(NLopt &nl, const Bounds<N>& bounds)
|
static void set_up(NLopt &nl,
|
||||||
|
const Bounds<N> &bounds,
|
||||||
|
const StopCriteria &stopcr)
|
||||||
{
|
{
|
||||||
std::array<double, N> lb, ub;
|
std::array<double, N> lb, ub;
|
||||||
|
|
||||||
@ -153,15 +155,15 @@ protected:
|
|||||||
nlopt_set_lower_bounds(nl.ptr, lb.data());
|
nlopt_set_lower_bounds(nl.ptr, lb.data());
|
||||||
nlopt_set_upper_bounds(nl.ptr, ub.data());
|
nlopt_set_upper_bounds(nl.ptr, ub.data());
|
||||||
|
|
||||||
double abs_diff = m_stopcr.abs_score_diff();
|
double abs_diff = stopcr.abs_score_diff();
|
||||||
double rel_diff = m_stopcr.rel_score_diff();
|
double rel_diff = stopcr.rel_score_diff();
|
||||||
double stopval = m_stopcr.stop_score();
|
double stopval = stopcr.stop_score();
|
||||||
if(!std::isnan(abs_diff)) nlopt_set_ftol_abs(nl.ptr, abs_diff);
|
if(!std::isnan(abs_diff)) nlopt_set_ftol_abs(nl.ptr, abs_diff);
|
||||||
if(!std::isnan(rel_diff)) nlopt_set_ftol_rel(nl.ptr, rel_diff);
|
if(!std::isnan(rel_diff)) nlopt_set_ftol_rel(nl.ptr, rel_diff);
|
||||||
if(!std::isnan(stopval)) nlopt_set_stopval(nl.ptr, stopval);
|
if(!std::isnan(stopval)) nlopt_set_stopval(nl.ptr, stopval);
|
||||||
|
|
||||||
if(m_stopcr.max_iterations() > 0)
|
if(stopcr.max_iterations() > 0)
|
||||||
nlopt_set_maxeval(nl.ptr, m_stopcr.max_iterations());
|
nlopt_set_maxeval(nl.ptr, stopcr.max_iterations());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Fn, size_t N, class...EqFns, class...IneqFns>
|
template<class Fn, size_t N, class...EqFns, class...IneqFns>
|
||||||
@ -211,7 +213,7 @@ public:
|
|||||||
const std::tuple<IneqFns...> &inequalities)
|
const std::tuple<IneqFns...> &inequalities)
|
||||||
{
|
{
|
||||||
NLopt nl{alg, N};
|
NLopt nl{alg, N};
|
||||||
set_up(nl, bounds);
|
set_up(nl, bounds, m_stopcr);
|
||||||
|
|
||||||
return optimize(nl, std::forward<Func>(func), initvals,
|
return optimize(nl, std::forward<Func>(func), initvals,
|
||||||
equalities, inequalities);
|
equalities, inequalities);
|
||||||
@ -230,6 +232,7 @@ template<nlopt_algorithm glob, nlopt_algorithm loc>
|
|||||||
class NLoptOpt<NLoptAlgComb<glob, loc>>: public NLoptOpt<NLoptAlg<glob>>
|
class NLoptOpt<NLoptAlgComb<glob, loc>>: public NLoptOpt<NLoptAlg<glob>>
|
||||||
{
|
{
|
||||||
using Base = NLoptOpt<NLoptAlg<glob>>;
|
using Base = NLoptOpt<NLoptAlg<glob>>;
|
||||||
|
StopCriteria m_loc_stopcr;
|
||||||
public:
|
public:
|
||||||
|
|
||||||
template<class Fn, size_t N, class...EqFns, class...IneqFns>
|
template<class Fn, size_t N, class...EqFns, class...IneqFns>
|
||||||
@ -241,15 +244,20 @@ public:
|
|||||||
{
|
{
|
||||||
NLopt nl_glob{glob, N}, nl_loc{loc, N};
|
NLopt nl_glob{glob, N}, nl_loc{loc, N};
|
||||||
|
|
||||||
Base::set_up(nl_glob, bounds);
|
Base::set_up(nl_glob, bounds, Base::get_criteria());
|
||||||
Base::set_up(nl_loc, bounds);
|
Base::set_up(nl_loc, bounds, m_loc_stopcr);
|
||||||
nlopt_set_local_optimizer(nl_glob.ptr, nl_loc.ptr);
|
nlopt_set_local_optimizer(nl_glob.ptr, nl_loc.ptr);
|
||||||
|
|
||||||
return Base::optimize(nl_glob, std::forward<Fn>(f), initvals,
|
return Base::optimize(nl_glob, std::forward<Fn>(f), initvals,
|
||||||
equalities, inequalities);
|
equalities, inequalities);
|
||||||
}
|
}
|
||||||
|
|
||||||
explicit NLoptOpt(StopCriteria stopcr = {}) : Base{stopcr} {}
|
explicit NLoptOpt(StopCriteria stopcr = {})
|
||||||
|
: Base{stopcr}, m_loc_stopcr{stopcr}
|
||||||
|
{}
|
||||||
|
|
||||||
|
void set_loc_criteria(const StopCriteria &cr) { m_loc_stopcr = cr; }
|
||||||
|
const StopCriteria &get_loc_criteria() const noexcept { return m_loc_stopcr; }
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace detail;
|
} // namespace detail;
|
||||||
@ -285,6 +293,9 @@ public:
|
|||||||
const StopCriteria &get_criteria() const { return m_opt.get_criteria(); }
|
const StopCriteria &get_criteria() const { return m_opt.get_criteria(); }
|
||||||
|
|
||||||
void seed(long s) { m_opt.seed(s); }
|
void seed(long s) { m_opt.seed(s); }
|
||||||
|
|
||||||
|
void set_loc_criteria(const StopCriteria &cr) { m_opt.set_loc_criteria(cr); }
|
||||||
|
const StopCriteria &get_loc_criteria() const noexcept { return m_opt.get_loc_criteria(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
// Predefinded NLopt algorithms
|
// Predefinded NLopt algorithms
|
||||||
|
@ -105,7 +105,7 @@ struct SupportTreeConfig
|
|||||||
static const double constexpr max_solo_pillar_height_mm = 15.0;
|
static const double constexpr max_solo_pillar_height_mm = 15.0;
|
||||||
static const double constexpr max_dual_pillar_height_mm = 35.0;
|
static const double constexpr max_dual_pillar_height_mm = 35.0;
|
||||||
static const double constexpr optimizer_rel_score_diff = 1e-10;
|
static const double constexpr optimizer_rel_score_diff = 1e-10;
|
||||||
static const unsigned constexpr optimizer_max_iterations = 2000;
|
static const unsigned constexpr optimizer_max_iterations = 30000;
|
||||||
static const unsigned constexpr pillar_cascade_neighbors = 3;
|
static const unsigned constexpr pillar_cascade_neighbors = 3;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -492,17 +492,24 @@ GroundConnection deepsearch_ground_connection(
|
|||||||
// Score is the total lenght of the route. Feasible routes will have
|
// Score is the total lenght of the route. Feasible routes will have
|
||||||
// infinite length (rays not colliding with model), thus the stop score
|
// infinite length (rays not colliding with model), thus the stop score
|
||||||
// should be a reasonably big number.
|
// should be a reasonably big number.
|
||||||
constexpr double StopScore = 1e6;
|
constexpr double Penality = 1e5;
|
||||||
|
constexpr double PenOffs = 1e2;
|
||||||
|
|
||||||
const auto sd = sm.cfg.safety_distance(source.r);
|
const auto sd = sm.cfg.safety_distance(source.r);
|
||||||
const auto gndlvl = ground_level(sm);
|
const auto gndlvl = ground_level(sm);
|
||||||
|
|
||||||
auto criteria = get_criteria(sm.cfg).stop_score(StopScore);
|
auto criteria = get_criteria(sm.cfg);
|
||||||
|
criteria.abs_score_diff(1.);
|
||||||
|
criteria.rel_score_diff(0.1);
|
||||||
|
criteria.max_iterations(5000);
|
||||||
|
|
||||||
Optimizer<opt::AlgNLoptMLSL> solver(criteria);
|
Optimizer<opt::AlgNLoptMLSL> solver(criteria);
|
||||||
|
solver.set_loc_criteria(criteria.max_iterations(100).abs_score_diff(1.));
|
||||||
solver.seed(0); // enforce deterministic behavior
|
solver.seed(0); // enforce deterministic behavior
|
||||||
|
|
||||||
|
size_t icnt = 0;
|
||||||
auto optfn = [&](const opt::Input<3> &input) {
|
auto optfn = [&](const opt::Input<3> &input) {
|
||||||
|
++icnt;
|
||||||
double ret = NaNd;
|
double ret = NaNd;
|
||||||
|
|
||||||
// solver suggests polar, azimuth and bridge length values:
|
// solver suggests polar, azimuth and bridge length values:
|
||||||
@ -511,7 +518,7 @@ GroundConnection deepsearch_ground_connection(
|
|||||||
Vec3d n = spheric_to_dir(plr, azm);
|
Vec3d n = spheric_to_dir(plr, azm);
|
||||||
Vec3d bridge_end = source.pos + bridge_len * n;
|
Vec3d bridge_end = source.pos + bridge_len * n;
|
||||||
|
|
||||||
double full_len = bridge_len + bridge_end.z() - gndlvl;
|
double down_l = bridge_end.z() - gndlvl;
|
||||||
double bridge_r = wideningfn(Ball{source.pos, source.r}, n, bridge_len);
|
double bridge_r = wideningfn(Ball{source.pos, source.r}, n, bridge_len);
|
||||||
double brhit_dist = 0.;
|
double brhit_dist = 0.;
|
||||||
|
|
||||||
@ -524,7 +531,7 @@ GroundConnection deepsearch_ground_connection(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (brhit_dist < bridge_len) {
|
if (brhit_dist < bridge_len) {
|
||||||
ret = brhit_dist;
|
ret = brhit_dist + Penality;
|
||||||
} else {
|
} else {
|
||||||
// check if pillar can be placed below
|
// check if pillar can be placed below
|
||||||
auto gp = Vec3d{bridge_end.x(), bridge_end.y(), gndlvl};
|
auto gp = Vec3d{bridge_end.x(), bridge_end.y(), gndlvl};
|
||||||
@ -532,28 +539,27 @@ GroundConnection deepsearch_ground_connection(
|
|||||||
|
|
||||||
Beam gndbeam {{bridge_end, bridge_r}, {gp, end_radius}};
|
Beam gndbeam {{bridge_end, bridge_r}, {gp, end_radius}};
|
||||||
auto gndhit = beam_mesh_hit(policy, sm.emesh, gndbeam, sd);
|
auto gndhit = beam_mesh_hit(policy, sm.emesh, gndbeam, sd);
|
||||||
|
double gnd_hit_d = std::min(gndhit.distance(), down_l);
|
||||||
|
double penality = 0.;
|
||||||
|
|
||||||
if (std::isinf(gndhit.distance())) {
|
if (!std::isinf(gndhit.distance()))
|
||||||
// Ground route is free with this bridge
|
penality = Penality;
|
||||||
|
else if (sm.cfg.object_elevation_mm < EPSILON) {
|
||||||
if (sm.cfg.object_elevation_mm < EPSILON) {
|
// Dealing with zero elevation mode, to not route pillars
|
||||||
// Dealing with zero elevation mode, to not route pillars
|
// into the gap between the optional pad and the model
|
||||||
// into the gap between the optional pad and the model
|
double gap = std::sqrt(sm.emesh.squared_distance(gp));
|
||||||
double gap = std::sqrt(sm.emesh.squared_distance(gp));
|
double base_r = std::max(sm.cfg.base_radius_mm, end_radius);
|
||||||
double base_r = std::max(sm.cfg.base_radius_mm, end_radius);
|
double min_gap = sm.cfg.pillar_base_safety_distance_mm + base_r;
|
||||||
double max_gap = sm.cfg.pillar_base_safety_distance_mm + base_r;
|
if (gap < min_gap) {
|
||||||
if (gap < max_gap)
|
penality = Penality + PenOffs * (min_gap - gap);
|
||||||
ret = full_len - max_gap + gap;
|
|
||||||
else // success
|
|
||||||
ret = StopScore + EPSILON;
|
|
||||||
} else {
|
|
||||||
// No zero elevation, return success
|
|
||||||
ret = StopScore + EPSILON;
|
|
||||||
}
|
}
|
||||||
} else {
|
// gnd_hit_d += std::max(0., min_gap - gap); //penality = Penality + 100000. * (min_gap - gap);
|
||||||
// Ground route is not free
|
// if (gap < min_gap) {
|
||||||
ret = bridge_len + gndhit.distance();
|
// penality = Penality;
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = bridge_len + gnd_hit_d + penality;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@ -564,7 +570,7 @@ GroundConnection deepsearch_ground_connection(
|
|||||||
// Saturate the polar angle to max tilt defined in config
|
// Saturate the polar angle to max tilt defined in config
|
||||||
plr_init = std::max(plr_init, PI - sm.cfg.bridge_slope);
|
plr_init = std::max(plr_init, PI - sm.cfg.bridge_slope);
|
||||||
|
|
||||||
auto oresult = solver.to_max().optimize(
|
auto oresult = solver.to_min().optimize(
|
||||||
optfn,
|
optfn,
|
||||||
initvals({plr_init, azm_init, 0.}), // start with a zero bridge
|
initvals({plr_init, azm_init, 0.}), // start with a zero bridge
|
||||||
bounds({ {PI - sm.cfg.bridge_slope, PI}, // bounds for polar angle
|
bounds({ {PI - sm.cfg.bridge_slope, PI}, // bounds for polar angle
|
||||||
@ -572,10 +578,12 @@ GroundConnection deepsearch_ground_connection(
|
|||||||
{0., sm.cfg.max_bridge_length_mm} }) // bounds bridge length
|
{0., sm.cfg.max_bridge_length_mm} }) // bounds bridge length
|
||||||
);
|
);
|
||||||
|
|
||||||
|
std::cout << "iters: " << icnt << std::endl;
|
||||||
|
|
||||||
GroundConnection conn;
|
GroundConnection conn;
|
||||||
|
|
||||||
if (oresult.score >= StopScore) {
|
if (oresult.score < Penality) {
|
||||||
// search was successful, extract and apply the result
|
// Extract and apply the result
|
||||||
auto &[plr, azm, bridge_len] = oresult.optimum;
|
auto &[plr, azm, bridge_len] = oresult.optimum;
|
||||||
|
|
||||||
Vec3d n = spheric_to_dir(plr, azm);
|
Vec3d n = spheric_to_dir(plr, azm);
|
||||||
|
@ -177,7 +177,7 @@ TEST_CASE("Avoid disk below junction", "[suptreeutils]")
|
|||||||
|
|
||||||
sla::SupportableMesh sm{disk, sla::SupportPoints{}, cfg};
|
sla::SupportableMesh sm{disk, sla::SupportPoints{}, cfg};
|
||||||
|
|
||||||
SECTION("without elevation") {
|
SECTION("with elevation") {
|
||||||
|
|
||||||
sla::GroundConnection conn =
|
sla::GroundConnection conn =
|
||||||
sla::deepsearch_ground_connection(ex_seq, sm, j, EndRadius, sla::DOWN);
|
sla::deepsearch_ground_connection(ex_seq, sm, j, EndRadius, sla::DOWN);
|
||||||
@ -191,7 +191,7 @@ TEST_CASE("Avoid disk below junction", "[suptreeutils]")
|
|||||||
REQUIRE(pR + FromRadius > CylRadius);
|
REQUIRE(pR + FromRadius > CylRadius);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("with elevation") {
|
SECTION("without elevation") {
|
||||||
sm.cfg.object_elevation_mm = 0.;
|
sm.cfg.object_elevation_mm = 0.;
|
||||||
|
|
||||||
sla::GroundConnection conn =
|
sla::GroundConnection conn =
|
||||||
@ -234,7 +234,7 @@ TEST_CASE("Avoid disk below junction with barrier on the side", "[suptreeutils]"
|
|||||||
|
|
||||||
sla::SupportableMesh sm{disk, sla::SupportPoints{}, cfg};
|
sla::SupportableMesh sm{disk, sla::SupportPoints{}, cfg};
|
||||||
|
|
||||||
SECTION("without elevation") {
|
SECTION("with elevation") {
|
||||||
sla::GroundConnection conn =
|
sla::GroundConnection conn =
|
||||||
sla::deepsearch_ground_connection(ex_seq, sm, j, EndRadius, sla::DOWN);
|
sla::deepsearch_ground_connection(ex_seq, sm, j, EndRadius, sla::DOWN);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user