worked on grid-walker and synthetic steps/turns

This commit is contained in:
k-a-z-u
2017-11-29 16:35:29 +01:00
parent 55c061b344
commit 63bc2f3046
5 changed files with 370 additions and 232 deletions

View File

@@ -193,10 +193,22 @@ namespace GW3 {
return bbox.contains(pt); return bbox.contains(pt);
} }
// /** does one of the given grid-nodes contains the provided point-in-question? */
// static const Node* contains(const Grid<Node>& grid, const Nodes<Node>& nodes, Point2 pt) {
// for (const Node* n : nodes) {
// if (contains(grid, n, pt)) {
// return n;
// }
// }
// return nullptr;
// }
/** does one of the given grid-nodes contains the provided point-in-question? */ /** does one of the given grid-nodes contains the provided point-in-question? */
static const Node* contains(const Grid<Node>& grid, const Nodes<Node>& nodes, Point2 pt) { static const Node* contains(const Grid<Node>& grid, const std::vector<const Node*>& nodes, Point2 pt) {
for (const Node* n : nodes) { for (const Node* n : nodes) {
if (contains(grid, n, pt)) {return n;} if (contains(grid, n, pt)) {
return n;
}
} }
return nullptr; return nullptr;
} }

View File

@@ -252,6 +252,89 @@ public:
}; };
/**
* data-structure to track to-be-visited nodes
* push_back, pop_front
* as pop_front is costly, we omit the pop and use a head-index instead
* memory-consumption vs speed
*/
struct _ToVisit {
size_t nextIdx = 0;
std::vector<uint32_t> vec;
_ToVisit() {vec.reserve(256);}
void add(const uint32_t nodeIdx) {vec.push_back(nodeIdx);}
uint32_t next() {return vec[nextIdx++];}
bool empty() const {return nextIdx >= vec.size();}
};
/** get a list of all nodes that are reachable after checking several conditions */
template <typename Node, typename Conditions> class ReachableByConditionUnsorted {
public:
static std::vector<const Node*> get(const Grid<Node>& grid, const Node& start, const Conditions cond) {
//Node* curNode = nullptr;
std::unordered_set<uint32_t> scheduled;
_ToVisit toVisit;
toVisit.add(start.getIdx());
std::vector<const Node*> res;
while(!toVisit.empty()) {
// get the next to-be-visited node
const uint32_t curIdx = toVisit.next(); //visit from inside out (needed for correct distance)
const Node& curNode = grid[curIdx];
// process current node
res.push_back(&curNode);
scheduled.insert(curIdx);
// get all neighbors
const int numNeighbors = curNode.getNumNeighbors();
for (int i = 0; i < numNeighbors; ++i) {
const uint32_t neighborIdx = curNode.getNeighborIdx(i);
// already visited?
if (scheduled.find(neighborIdx) != scheduled.end()) {continue;}
scheduled.insert(neighborIdx);
// matches the used condition?
const Node& neighbor = grid[neighborIdx];
if (!cond.visit(neighbor)) {continue;}
// OK!
toVisit.add(neighborIdx);
}
}
// done
return res;
}
//const Node& next(const std::function<bool(const Node&)>& skip) {
//template <typename Skip> const Node& next(const Skip skip) {
const Node& next() {
}
};
} }
#endif // REACHABLE_H #endif // REACHABLE_H

View File

@@ -65,35 +65,63 @@ namespace GW3 {
const GridPoint gpStart = Helper::p3ToGp(params.start); const GridPoint gpStart = Helper::p3ToGp(params.start);
const Node* startNode = grid.getNodePtrFor(gpStart); const Node* startNode = grid.getNodePtrFor(gpStart);
// calculate a walk's probability
auto getP = [&] (const Point3 dst) {
double p = 1;
for (const WalkEvaluator<Node>* eval : evals) {
const double p1 = eval->getProbability(params.start, dst, params.start.getDistance(dst), params);
p *= p1;
}
return p;
};
// include one additional grid-cell (increased distance) // include one additional grid-cell (increased distance)
const float secBuffer_m = (grid.getGridSize_cm() / 100.0f) + (params.distance_m * 0.1); //const float secBuffer_m = (grid.getGridSize_cm() * 2/ 100.0f);// + (params.distance_m * 0.1);
ReachableSettings set; const float secBuffer_m = (grid.getGridSize_cm() * 1.15 / 100.0f);// + (params.distance_m * 0.15);
set.limitDistance = true;
set.dist_m = params.distance_m + secBuffer_m; // ReachableSettings set;
set.limitHeading = false; // set.limitDistance = true;
set.heading = params.heading; // set.dist_m = params.distance_m + secBuffer_m;
set.maxHeadingDiff_rad = M_PI/2; // set.limitHeading = false;
const Nodes reachableNodes = Helper::getAllReachableNodes(grid, startNode, set); // set.heading = params.heading;
// set.maxHeadingDiff_rad = M_PI/2;
// // get all nodes that satisfy above constraints
// const Nodes reachableNodes = Helper::getAllReachableNodes(grid, startNode, set);
struct Cond {
const float maxDist_m;
const Node* startNode;
Cond(float maxDist_m, const Node* startNode) : maxDist_m(maxDist_m), startNode(startNode) {;}
bool visit(const Node& n) const {
return (startNode->getDistanceInMeter(n)) < maxDist_m;
}
};
Cond cond(params.distance_m+secBuffer_m, startNode);
std::vector<const Node*> reachableNodes = ReachableByConditionUnsorted<Node, Cond>::get(grid, *startNode, cond);
WalkResult res; WalkResult res;
res.heading = params.heading; res.heading = params.heading;
res.position = params.start; res.position = params.start;
// get the to-be-reached destination's position (using start+distance+heading)
const Point2 dir = res.heading.asVector(); const Point2 dir = res.heading.asVector();
const Point2 dst = params.start.xy() + (dir * params.distance_m); const Point2 dst = params.start.xy() + (dir * params.distance_m);
// is dst reachable? // is above destination reachable?
const Node* n = Helper::contains(grid, reachableNodes, dst); const Node* n = Helper::contains(grid, reachableNodes, dst);
//const Node* n = ri.contains(dst);
if (n) { if (n) {
const Point3 p3(dst.x, dst.y, n->z_cm / 100.0f); const Point3 p3(dst.x, dst.y, n->z_cm / 100.0f);
const GridPoint gp = Helper::p3ToGp(p3); const GridPoint gp = Helper::p3ToGp(p3);
if (grid.hasNodeFor(gp)) { if (grid.hasNodeFor(gp)) {
res.position = p3; // update position res.position = p3; // update position
//res.heading; // keep as-is //res.heading; // keep as-is
//res.probability; // keep as-is res.probability *= getP(p3); // keep as-is
return res; // done return res; // done
} else { } else {
@@ -129,7 +157,7 @@ namespace GW3 {
} }
res.heading = Heading(start.xy(), end.xy()); res.heading = Heading(start.xy(), end.xy());
res.probability = p; res.probability *= getP(end);
res.position = end; res.position = end;
return res; return res;

View File

@@ -37,14 +37,22 @@ private:
Distribution::Normal<float> dY = Distribution::Normal<float>(0, 0.3); Distribution::Normal<float> dY = Distribution::Normal<float>(0, 0.3);
Distribution::Normal<float> dZ = Distribution::Normal<float>(0, 0.4); Distribution::Normal<float> dZ = Distribution::Normal<float>(0, 0.4);
int stepPatternPos = -1; int stepPatternPos = -1;
std::vector<Listener*> listeners; std::vector<Listener*> listeners;
//float stepSize_m;
//float stepSizeSigma_m;
float noiseLevel;
Distribution::Normal<float> dNextStep;
public: public:
/** ctor with the walker to follow */ /** ctor with the walker to follow */
SyntheticSteps(SyntheticWalker* walker) { SyntheticSteps(SyntheticWalker* walker, const float stepSize_m = 0.7, const float stepSizeSigma_m = 0.1, const float noiseLevel = 0.33) :
//stepSize_m(stepSize_m), drift(drift), stepSizeSigma_m(stepSizeSigma_m),
noiseLevel(noiseLevel), dNextStep(stepSize_m, stepSizeSigma_m) {
walker->addListener(this); walker->addListener(this);
dX.setSeed(1); dX.setSeed(1);
@@ -82,15 +90,15 @@ protected:
void onWalk(const Timestamp walkedTime, float walkedDistance, const Point3 curPos) override { void onWalk(const Timestamp walkedTime, float walkedDistance, const Point3 curPos) override {
(void) curPos; (void) curPos;
const float nextStepAt = (lastStepAtDistance + stepSize_m); const float nextStepAt = lastStepAtDistance + dNextStep.draw();
// 1st, start with random noise on the accelerometer // 1st, start with random noise on the accelerometer
const float x = dX.draw(); const float x = dX.draw();
const float y = dY.draw(); const float y = dY.draw();
const float z = dZ.draw(); const float z = dZ.draw();
const AccelerometerData base(0, 4, 9.7); const AccelerometerData aBase(0, 4, 9.7);
const AccelerometerData noise(x, y, z); const AccelerometerData aNoise(x, y, z);
AccelerometerData acc = base + noise; AccelerometerData acc = aBase + aNoise * noiseLevel;
// is it time to inject a "step" into the accelerometer data? // is it time to inject a "step" into the accelerometer data?
if (walkedDistance > nextStepAt) { if (walkedDistance > nextStepAt) {
@@ -105,7 +113,7 @@ protected:
refStepPattern = Timestamp::fromMS(0); refStepPattern = Timestamp::fromMS(0);
} else { } else {
const AccelerometerData step = stepPattern.get(curPatPos); const AccelerometerData step = stepPattern.get(curPatPos);
acc = base + noise*2.5f + step; acc = aBase + (aNoise * noiseLevel) + step;
} }
} }

View File

@@ -39,17 +39,23 @@ private:
Distribution::Normal<float> dMaxChange = Distribution::Normal<float>(0.011, 0.003); Distribution::Normal<float> dMaxChange = Distribution::Normal<float>(0.011, 0.003);
Distribution::Normal<float> dChange = Distribution::Normal<float>(1.0, 0.25); Distribution::Normal<float> dChange = Distribution::Normal<float>(1.0, 0.25);
Distribution::Normal<float> dHeadErr = Distribution::Normal<float>(0.15, 0.10); // heading error, slightly biased
Distribution::Uniform<float> dRadDiff = Distribution::Uniform<float>(40,100); Distribution::Uniform<float> dRadDiff = Distribution::Uniform<float>(40,100);
//float headingDrift_rad;
//float headingSigma_rad;
float noiseLevel;
Distribution::Normal<float> dHeadErr;
std::vector<Listener*> listeners; std::vector<Listener*> listeners;
public: public:
/** ctor with the walker to follow */ /** ctor with the walker to follow */
SyntheticTurns(SyntheticWalker* walker) { SyntheticTurns(SyntheticWalker* walker, const float headingDrift_rad = 0, const float headingSigma_rad = 0, const float noiseLevel = 0) :
//headingDrift_rad(headingDrift_rad), headingSigma_rad(headingSigma_rad),
noiseLevel(noiseLevel + 0.00001f), dHeadErr(headingDrift_rad, headingSigma_rad) {
walker->addListener(this); walker->addListener(this);
dAccX.setSeed(1); dAccX.setSeed(1);
dAccY.setSeed(3); dAccY.setSeed(3);
@@ -57,6 +63,7 @@ public:
dGyroX.setSeed(7); dGyroX.setSeed(7);
dGyroY.setSeed(9); dGyroY.setSeed(9);
dGyroZ.setSeed(11); dGyroZ.setSeed(11);
} }
/** attach a listener to this provider */ /** attach a listener to this provider */
@@ -116,14 +123,14 @@ protected:
// convert to gyro's radians-per-second // convert to gyro's radians-per-second
const double radPerSec = change * 1000 / deltaTs.ms();; const double radPerSec = change * 1000 / deltaTs.ms();;
const float accX = 0.00 + dAccX.draw(); const float accX = 0.00 + dAccX.draw() * (noiseLevel);
const float accY = 0.00 + dAccY.draw(); const float accY = 0.00 + dAccY.draw() * (noiseLevel);
const float accZ = 9.81 + dAccZ.draw(); const float accZ = 9.81 + dAccZ.draw() * (noiseLevel);
AccelerometerData acc(accX, accY, accZ); AccelerometerData acc(accX, accY, accZ);
const float gyroX = dGyroX.draw(); const float gyroX = dGyroX.draw() * (noiseLevel);
const float gyroY = dGyroY.draw(); const float gyroY = dGyroY.draw() * (noiseLevel);
const float gyroZ = dGyroZ.draw() + radPerSec; const float gyroZ = dGyroZ.draw() * (noiseLevel) + radPerSec;
GyroscopeData gyro(gyroX, gyroY, gyroZ); GyroscopeData gyro(gyroX, gyroY, gyroZ);
for (Listener* l : listeners) {l->onSyntheticTurnData(walkedTime, acc, gyro);} for (Listener* l : listeners) {l->onSyntheticTurnData(walkedTime, acc, gyro);}