#ifndef NAV_MESH_FILTER_H #define NAV_MESH_FILTER_H #include "mesh.h" #include #include #include #include #include #include #include #include #include #include struct MyState { /** the state's position (within the mesh) */ MyNavMeshLocation pos; /** the state's heading */ Heading heading; MyState() : pos(), heading(0) {;} MyState& operator += (const MyState& o) { pos.tria = nullptr; // impossible pos.pos += o.pos.pos; return *this; } MyState& operator /= (const double val) { pos.tria = nullptr; // impossible pos.pos /= val; return *this; } MyState operator * (const double val) const { MyState res; res.pos.pos = pos.pos * val; return res; } }; struct MyControl { int numStepsSinceLastEval = 0; float headingChangeSinceLastEval = 0; void afterEval() { numStepsSinceLastEval = 0; headingChangeSinceLastEval = 0; } }; struct MyObservation { }; class MyPFInitUniform : public K::ParticleFilterInitializer { const MyNavMesh* mesh; public: MyPFInitUniform(const MyNavMesh* mesh) : mesh(mesh) { ; } virtual void initialize(std::vector>& particles) override { /** random position and heading within the mesh */ Distribution::Uniform dHead(0, 2*M_PI); MyNavMeshRandom rnd = mesh->getRandom(); for (K::Particle& p : particles) { p.state.pos = rnd.draw(); p.state.heading = dHead.draw(); p.weight = 1.0 / particles.size(); } } }; class MyPFInitFixed : public K::ParticleFilterInitializer { const MyNavMesh* mesh; const Point3 pos; public: MyPFInitFixed(const MyNavMesh* mesh, const Point3 pos) : mesh(mesh), pos(pos) { ; } virtual void initialize(std::vector>& particles) override { /** random position and heading within the mesh */ Distribution::Uniform dHead(0, 2*M_PI); for (K::Particle& p : particles) { p.state.pos = mesh->getLocation(pos); p.state.heading = dHead.draw(); p.weight = 1.0 / particles.size(); } } }; class MyPFTrans : public K::ParticleFilterTransition { using MyNavMeshWalk = NM::NavMeshWalkSimple; MyNavMeshWalk walker; public: MyPFTrans(MyNavMesh& mesh) : walker(mesh) { // how to evaluate drawn points //walker.addEvaluator(new NM::WalkEvalHeadingStartEndNormal(0.04)); //walker.addEvaluator(new NM::WalkEvalDistance(0.1)); walker.addEvaluator(new NM::WalkEvalApproachesTarget(0.9)); // 90% for particles moving towards the target } void transition(std::vector>& particles, const MyControl* control) override { Distribution::Normal dStepSizeFloor(0.70, 0.1); Distribution::Normal dStepSizeStair(0.35, 0.1); Distribution::Normal dHeading(0.0, 0.10); for (K::Particle& p : particles) { // how to walk MyNavMeshWalkParams params; params.heading = p.state.heading + control->headingChangeSinceLastEval + dHeading.draw(); params.numSteps = control->numStepsSinceLastEval; params.start = p.state.pos; params.stepSizes.stepSizeFloor_m = dStepSizeFloor.draw(); params.stepSizes.stepSizeStair_m = dStepSizeStair.draw(); // walk MyNavMeshWalk::ResultEntry res = walker.getOne(params); // assign back to particle's state p.weight *= res.probability; p.state.pos = res.location; p.state.heading = res.heading; } // reset the control (0 steps, 0 delta-heading) //control->afterEval(); } }; class MyPFEval : public K::ParticleFilterEvaluation { public: virtual double evaluation(std::vector>& particles, const MyObservation& observation) override { return 1.0; } }; using MyFilter = K::ParticleFilter; #endif