This repository has been archived on 2020-04-08. You can view files and clone it, but cannot push or open issues or pull requests.
Files
Indoor/grid/factory/v2/Importance.h
2018-10-25 11:50:12 +02:00

180 lines
5.0 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* © Copyright 2014 Urheberrechtshinweis
* Alle Rechte vorbehalten / All Rights Reserved
*
* Programmcode ist urheberrechtlich geschuetzt.
* Das Urheberrecht liegt, soweit nicht ausdruecklich anders gekennzeichnet, bei Frank Ebner.
* Keine Verwendung ohne explizite Genehmigung.
* (vgl. § 106 ff UrhG / § 97 UrhG)
*/
#ifndef IMPORTANCE_H
#define IMPORTANCE_H
#include "../../../geo/Units.h"
#include "../../Grid.h"
#include "GridFactoryListener.h"
#include "../../../misc/KNN.h"
#include "../../../misc/KNNArray.h"
#include "../../../math/MiniMat2.h"
#include "../../../math/distribution/Normal.h"
#include "../../../math/distribution/Triangle.h"
class Importance {
private:
static constexpr const char* name = "GridImp";
public:
template <typename T> static void addOutlineNodes(Grid<T>& dst, Grid<T>& src) {
for (const T& n : src) {
if (n.getNumNeighbors() < 8) {
if (!dst.hasNodeFor(n)) {
dst.add(n);
}
}
}
}
/** attach importance-factors to the grid */
template <typename T> static void addImportance(Grid<T>& g, GridFactoryListener* l = nullptr) {
Log::add(name, "adding importance information to all nodes");
if (l) {
l->onGridBuildUpdateMajor(2, 0);
l->onGridBuildUpdateMajor("adding importance information");
l->onGridBuildUpdateMinor("performing initial setups");
}
// get an inverted version of the grid
Grid<T> inv(g.getGridSize_cm());
addOutlineNodes(inv, g);
//GridFactory<T> fac(inv);
//fac.addInverted(g, z_cm);
// sanity check
Assert::isFalse(inv.getNumNodes() == 0, "inverted grid is empty!");
// construct KNN search
KNN<Grid<T>, 3> knn(inv);
// create list of all door-nodes
std::vector<T> doors;
// create list of all stair-nodes
std::vector<T> stairs;
// process each node
for (T& n1 : g) {
switch(n1.getType()) {
case GridNode::TYPE_DOOR: doors.push_back(n1); break;
case GridNode::TYPE_STAIR: stairs.push_back(n1); break;
case GridNode::TYPE_ELEVATOR: stairs.push_back(n1); break;
}
}
// KNN for doors
KNNArray<std::vector<T>> knnArrDoors(doors);
KNN<KNNArray<std::vector<T>>, 3> knnDoors(knnArrDoors);
// KNN for stairs
KNNArray<std::vector<T>> knnArrStairs(stairs);
KNN<KNNArray<std::vector<T>>, 3> knnStairs(knnArrStairs);
// probability adjustments
Distribution::Triangle<float> avoidWalls(0.0, 0.35f);
Distribution::Normal<float> favorDoors(0.0f, 0.4f);
Distribution::Normal<float> favorStairs(0.0f, 1.5f);
if (l) {
l->onGridBuildUpdateMajor(2, 1);
l->onGridBuildUpdateMinor("calculating importance for each node");
}
std::cout << "dunno why, but the KNN for stairs searches extremely slow!" << std::endl;
// process each node again
for (int i = 0; i < g.getNumNodes(); ++i) {
// log
if (i % (g.getNumNodes() / 20) == 0) {
if (l) {
l->onGridBuildUpdateMinor(g.getNumNodes(), i);
}
}
// get the node
T& n1 = g[i];
// get the distance to the nearest outline node [an outline node is directly adjacent to a wall]
const float distToOutline_m = Units::cmToM(knn.getNearestDistance( {n1.x_cm, n1.y_cm, n1.z_cm} ));
// get the distance to the nearest door
const float distToDoor_m = Units::cmToM(knnDoors.getNearestDistance( {n1.x_cm, n1.y_cm, n1.z_cm} ));
// get the distance to the nearest stair
const float distToStair_m = Units::cmToM(knnStairs.getNearestDistance( {n1.x_cm, n1.y_cm, n1.z_cm} ));
// use wall-avoidance?
//const bool useWallAvoidance = (distToWall_m*6.0 < distToDoor_m && distToWall_m*6.0 < distToStair_m);
//const bool useWallAvoidance = (distToDoor_m > 0.4f) && (distToStair_m > 0.4f);
const bool useWallAvoidance =
(distToOutline_m < 0.001f) && // node is an outline node [outline-nodes are adjacent to a wall]
(distToDoor_m > 0.3f) && // doors are 30cm away
(distToStair_m > 0.6f); // stairs are 60cm away;
// final probability
n1.walkImportance = 1.0f;
//n1.walkImportance += favorDoors.getProbability(distToDoor_m) * 0.75f;
n1.walkImportance += favorStairs.getProbability(distToStair_m) * 1.0f;
// use wall avoidance
if (useWallAvoidance) {
//n1.walkImportance -= avoidWalls.getProbability(distToWall_m) * 0.3f;
n1.walkImportance = 0.20f; // only addresses direct outline nodes
}
// navigation importance is calculated using other formulae
n1.navImportance = 1.0f;
if (useWallAvoidance) {
n1.navImportance -= avoidWalls.getProbability(distToOutline_m) * 0.3f;
}
//n1.navImportance += favorDoors.getProbability(distToDoor_m) * 0.5;
n1.navImportance += favorStairs.getProbability(distToStair_m) * 1.0f;
// sanity check
Assert::isNotNaN(n1.walkImportance, "detected NaN walk importance for " + n1.asString());
Assert::isNotNaN(n1.navImportance, "detected NaN walk importance for " + n1.asString());
Assert::isTrue(n1.walkImportance >= 0, "detected negative walk importance. does not make sense!");
Assert::isTrue(n1.navImportance >= 0, "detected negative nav importance. does not make sense!");
}
}
};
#endif // IMPORTANCE_H