45 using namespace gtsam;
50 TEST(HybridEstimation, Full) {
52 std::vector<double> measurements = {0, 1, 2, 2, 2, 3};
54 std::vector<size_t> discrete_seq = {1, 1, 0, 0, 1};
57 Switching switching(
K, 1.0, 0.1, measurements,
"1/1 1/1");
61 for (
size_t k = 0; k <
K; k++) {
62 hybridOrdering.push_back(
X(k));
64 for (
size_t k = 0; k <
K - 1; k++) {
65 hybridOrdering.push_back(
M(k));
78 for (
size_t k = 0; k <
K - 1; k++) {
79 expected_discrete[
M(k)] = discrete_seq[k];
83 Values expected_continuous;
84 for (
size_t k = 0; k <
K; k++) {
85 expected_continuous.
insert(
X(k), measurements[k]);
92 TEST(HybridEstimation, IncrementalSmoother) {
94 std::vector<double> measurements = {0, 1, 2, 2, 2, 2, 3, 4, 5, 6, 6,
95 7, 8, 9, 9, 9, 10, 11, 11, 11, 11};
97 std::vector<size_t> discrete_seq = {1, 1, 0, 0, 0, 1, 1, 1, 1, 0,
98 1, 1, 1, 0, 0, 1, 1, 0, 0, 0};
101 Switching switching(
K, 1.0, 0.1, measurements,
"1/1 1/1");
112 for (
size_t k = 1; k <
K; k++) {
132 for (
size_t k = 0; k <
K - 1; k++) {
133 expected_discrete[
M(k)] = discrete_seq[k];
137 Values expected_continuous;
138 for (
size_t k = 0; k <
K; k++) {
139 expected_continuous.
insert(
X(k), measurements[k]);
148 std::vector<double> measurements = {0, 1, 2, 2, 2, 2, 3, 4, 5, 6, 6,
149 7, 8, 9, 9, 9, 10, 11, 11, 11, 11};
151 std::vector<size_t> discrete_seq = {1, 1, 0, 0, 0, 1, 1, 1, 1, 0,
152 1, 1, 1, 0, 0, 1, 1, 0, 0, 0};
155 Switching switching(
K, 1.0, 0.1, measurements,
"1/1 1/1");
168 for (
size_t k = 1; k <
K; k++) {
187 for (
size_t k = 0; k <
K - 1; k++) {
188 expected_discrete[
M(k)] = discrete_seq[k];
192 Values expected_continuous;
193 for (
size_t k = 0; k <
K; k++) {
194 expected_continuous.
insert(
X(k), measurements[k]);
212 size_t K,
const std::vector<double>& measurements,
213 const std::vector<size_t>& discrete_seq,
double measurement_sigma = 0.1,
214 double between_sigma = 1.0) {
216 Values linearizationPoint;
219 auto measurement_noise = noiseModel::Isotropic::Sigma(1, measurement_sigma);
220 for (
size_t k = 0; k <
K; k++) {
223 linearizationPoint.
insert<
double>(
X(k),
static_cast<double>(k + 1));
229 auto motion_noise_model = noiseModel::Isotropic::Sigma(1, between_sigma);
230 for (
size_t k = 0; k <
K - 1; k++) {
231 auto motion_model = std::make_shared<MotionModel>(
232 X(k),
X(k + 1), discrete_seq.at(k), motion_noise_model);
249 std::bitset<
K - 1>
seq =
x;
250 std::vector<size_t> discrete_seq(
K - 1);
251 for (
size_t i = 0;
i <
K - 1;
i++) {
253 discrete_seq[
K - 2 -
i] =
seq[
i];
271 const auto [
bayesNet, remainingGraph] =
272 graph.eliminatePartialSequential(continuous);
275 DiscreteKeys discrete_keys = last_conditional->discreteKeys();
277 const std::vector<DiscreteValues> assignments =
278 DiscreteValues::CartesianProduct(discrete_keys);
280 std::reverse(discrete_keys.begin(), discrete_keys.end());
282 vector<VectorValues::shared_ptr> vector_values;
285 vector_values.push_back(std::make_shared<VectorValues>(
values));
291 std::vector<double> probPrimes;
297 if (
delta.size() == 0) {
298 probPrimes.push_back(0.0);
306 return probPrimeTree;
313 TEST(HybridEstimation, Probability) {
314 constexpr
size_t K = 4;
315 std::vector<double> measurements = {0, 1, 2, 2};
316 double between_sigma = 1.0, measurement_sigma = 0.1;
320 Switching switching(
K, between_sigma, measurement_sigma, measurements,
327 graph.eliminatePartialSequential(continuous_ordering);
331 auto discreteBayesNet = discreteGraph->eliminateSequential(discrete_ordering);
334 for (
auto discrete_conditional : *discreteBayesNet) {
342 discrete_seq[
M(0)] = 1;
343 discrete_seq[
M(1)] = 1;
344 discrete_seq[
M(2)] = 0;
355 TEST(HybridEstimation, ProbabilityMultifrontal) {
356 constexpr
size_t K = 4;
357 std::vector<double> measurements = {0, 1, 2, 2};
359 double between_sigma = 1.0, measurement_sigma = 0.1;
363 Switching switching(
K, between_sigma, measurement_sigma, measurements,
372 const auto [bayesTree, discreteGraph] =
373 graph.eliminatePartialMultifrontal(continuous_ordering);
376 Key last_continuous_key =
377 continuous_ordering.at(continuous_ordering.size() - 1);
378 auto last_conditional = (*bayesTree)[last_continuous_key]->conditional();
379 DiscreteKeys discrete_keys = last_conditional->discreteKeys();
382 auto discreteBayesTree = discreteGraph->eliminateMultifrontal(discrete);
386 auto discrete_clique = (*discreteBayesTree)[discrete.at(0)];
388 std::set<HybridBayesTreeClique::shared_ptr> clique_set;
389 for (
auto node : bayesTree->nodes()) {
390 clique_set.insert(node.second);
394 for (
auto clique : clique_set) {
395 if (clique->conditional()->parents() ==
396 discrete_clique->conditional()->frontals()) {
397 discreteBayesTree->addClique(clique, discrete_clique);
402 auto clique_it = std::find(clique->parent()->children.begin(),
403 clique->parent()->children.end(), clique);
404 clique->parent()->children.erase(clique_it);
405 discreteBayesTree->addClique(clique, clique->parent());
409 HybridValues hybrid_values = discreteBayesTree->optimize();
413 discrete_seq[
M(0)] = 1;
414 discrete_seq[
M(1)] = 1;
415 discrete_seq[
M(2)] = 0;
426 constexpr
double sigma = 0.5;
435 const auto zero_motion =
436 std::make_shared<BetweenFactor<double>>(
X(0),
X(1), 0,
noise_model);
437 const auto one_motion =
438 std::make_shared<BetweenFactor<double>>(
X(0),
X(1), 1,
noise_model);
439 std::vector<NoiseModelFactor::shared_ptr>
components = {zero_motion,
453 double z0 = 0.0,
z1 = 1.0;
462 TEST(HybridEstimation, eliminateSequentialRegression) {
475 auto dc1 = bn1->back()->asDiscrete();
483 auto dc2 = bn2->back()->asDiscrete();
497 TEST(HybridEstimation, CorrectnessViaSampling) {
505 std::mt19937_64
rng(11);
508 auto compute_ratio = [&](
const HybridValues& sample) ->
double {
509 return bn->evaluate(sample) / fg->probPrime(sample);
515 double expected_ratio = compute_ratio(sample);
520 constexpr
int num_samples = 10;
521 for (
size_t i = 0;
i < num_samples;
i++) {
531 TEST(HybridEstimation, ModeSelection) {
535 auto measurement_model = noiseModel::Isotropic::Sigma(1, 0.1);
536 auto motion_model = noiseModel::Isotropic::Sigma(1, 1.0);
543 double noise_tight = 0.5, noise_loose = 5.0;
545 auto model0 = std::make_shared<MotionModel>(
546 X(0),
X(1), 0.0, noiseModel::Isotropic::Sigma(
d, noise_loose)),
547 model1 = std::make_shared<MotionModel>(
548 X(0),
X(1), 0.0, noiseModel::Isotropic::Sigma(
d, noise_tight));
571 GaussianConditional::sharedMeanAndStddev(
Z(0), -I_1x1,
X(0), Z_1x1, 0.1));
573 GaussianConditional::sharedMeanAndStddev(
Z(0), -I_1x1,
X(1), Z_1x1, 0.1));
575 std::vector<std::pair<Vector, double>>
parameters{{Z_1x1, noise_loose},
576 {Z_1x1, noise_tight}};
590 TEST(HybridEstimation, ModeSelection2) {
595 double noise_tight = 0.5, noise_loose = 5.0;
601 GaussianConditional::sharedMeanAndStddev(
Z(0), -I_3x3,
X(0),
Z_3x1, 0.1));
603 GaussianConditional::sharedMeanAndStddev(
Z(0), -I_3x3,
X(1),
Z_3x1, 0.1));
605 std::vector<std::pair<Vector, double>>
parameters{{
Z_3x1, noise_loose},
606 {
Z_3x1, noise_tight}};
622 auto measurement_model = noiseModel::Isotropic::Sigma(
d, 0.1);
623 auto motion_model = noiseModel::Isotropic::Sigma(
d, 1.0);
628 auto model0 = std::make_shared<BetweenFactor<Vector3>>(
629 X(0),
X(1),
Z_3x1, noiseModel::Isotropic::Sigma(
d, noise_loose)),
631 X(0),
X(1),
Z_3x1, noiseModel::Isotropic::Sigma(
d, noise_tight));