Skip to content

Commit

Permalink
Fix reported entropy (#408)
Browse files Browse the repository at this point in the history
* Add entropy as a class member of ParticleFilter
* Compute entropy in the measure method
* Use getEntropy from the particle filter object
* Check if the particle probability is greater than 0
* Add simple tests
  • Loading branch information
f-fl0 authored Nov 14, 2023
1 parent 8d8835f commit bbf2e52
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 19 deletions.
11 changes: 11 additions & 0 deletions include/mcl_3dl/pf.h
Original file line number Diff line number Diff line change
Expand Up @@ -256,10 +256,16 @@ class ParticleFilter
}
if (sum > 0.0)
{
entropy_ = 0;
for (auto& p : particles_)
{
p.probability_ /= sum;
if (p.probability_ > 0)
{
entropy_ += p.probability_ * std::log(p.probability_);
}
}
entropy_ *= -1;
}
else
{
Expand Down Expand Up @@ -437,12 +443,17 @@ class ParticleFilter
{
return particles_.end();
}
FLT_TYPE getEntropy() const
{
return entropy_;
}

protected:
std::vector<Particle<T, FLT_TYPE>> particles_;
std::vector<Particle<T, FLT_TYPE>> particles_dup_;
RANDOM_ENGINE engine_;
T ie_;
FLT_TYPE entropy_;
};

} // namespace pf
Expand Down
21 changes: 2 additions & 19 deletions src/mcl_3dl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1119,25 +1119,8 @@ class MCL3dlNode
pm.orientation.w = p.rot_.w_;
pa.poses.push_back(pm);
}
pub_particle_.publish(pa);
}

float getEntropy()
{
float sum = 0.0f;
for (auto& particle : *pf_)
{
sum += particle.probability_;
}

float entropy = 0.0f;
for (auto& particle : *pf_)
{
if (particle.probability_ / sum > 0.0)
entropy += particle.probability_ / sum * std::log(particle.probability_ / sum);
}

return -entropy;
pub_particle_.publish(pa);
}

void diagnoseStatus(diagnostic_updater::DiagnosticStatusWrapper& stat)
Expand All @@ -1159,7 +1142,7 @@ class MCL3dlNode
stat.add("Odometry Availability", has_odom_ ? "true" : "false");
stat.add("IMU Availability", has_imu_ ? "true" : "false");

status_.entropy = getEntropy();
status_.entropy = pf_->getEntropy();
pub_status_.publish(status_);
}

Expand Down
63 changes: 63 additions & 0 deletions test/src/test_pf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,69 @@ TEST(Pf, AppendParticles)
ASSERT_EQ(pf.getParticle(i)[0], val1);
}

TEST(Pf, Entropy)
{
mcl_3dl::pf::ParticleFilter<State, float> pf(10);

// no uncertainty
{
unsigned int idx = 0;
auto likelihood = [&idx](const State& s) -> float
{
return idx++ == 0 ? 1.0 : 0.0;
};
pf.init(State(0), State(0.1));
pf.measure(likelihood);
ASSERT_EQ(pf.getEntropy(), 0);
}

// uniform distribution
{
auto likelihood = [](const State& s) -> float
{
return 0.1;
};
pf.init(State(0), State(0.1));
pf.measure(likelihood);
ASSERT_NEAR(pf.getEntropy(), 2.303, 1e-3);
}

// compare the entropy of two distributions with first one having a narrower peak
// i.e. less uncertainty that the other
{
unsigned int idx = 0;
auto likelihood1 = [&idx](const State& s) -> float
{
float lk = 0.025;
if (idx >= 4 && idx < 6)
{
lk = 0.4;
}
idx++;
return lk;
};
pf.init(State(0), State(0.1));
pf.measure(likelihood1);
const float entropy1 = pf.getEntropy();

idx = 0;
auto likelihood2 = [&idx](const State& s) -> float
{
float lk = 0.025;
if (idx >= 2 && idx < 8)
{
lk = 0.15;
}
idx++;
return lk;
};
pf.init(State(0), State(0.1));
pf.measure(likelihood2);
const float entropy2 = pf.getEntropy();
ASSERT_GT(entropy2, entropy1);
}
}

int main(int argc, char** argv)
{
testing::InitGoogleTest(&argc, argv);
Expand Down

0 comments on commit bbf2e52

Please sign in to comment.