39 using namespace Eigen;
42 inline double round(
double number)
44 return number < 0.0 ? ceil(number - 0.5) : floor(number + 0.5);
48 typedef std::map<int, std::map<int, Simulator::LandmarkPtrVector> >
LandmarkGrid;
52 time_t seed = time(0);
53 Rand::seed_rand(static_cast<unsigned int>(seed));
56 Simulator::~Simulator()
60 void Simulator::simulate(
int numNodes,
const SE2& sensorOffset)
67 double maxSensorRangeLandmarks = 2.5 * stepLen;
69 int landMarksPerSquareMeter = 1;
70 double observationProb = 0.8;
74 Vector2d transNoise(0.05, 0.01);
76 Vector2d landmarkNoise(0.05, 0.05);
78 Vector2d bound(boundArea, boundArea);
81 probLimits.resize(MO_NUM_ELEMS);
82 for (
int i = 0; i < probLimits.size(); ++i)
83 probLimits[i] = (i + 1) / (double) MO_NUM_ELEMS;
87 covariance(0, 0) = transNoise[0]*transNoise[0];
88 covariance(1, 1) = transNoise[1]*transNoise[1];
89 covariance(2, 2) = rotNoise*rotNoise;
90 Matrix3d information = covariance.inverse();
92 SE2 maxStepTransf(stepLen * steps, 0, 0);
101 poses.push_back(firstPose);
102 cerr <<
"Simulator: sampling nodes ...";
103 while ((
int)poses.size() < numNodes) {
105 for (
int i = 1; i < steps && (int)poses.size() < numNodes; ++i) {
107 poses.push_back(nextGridPose);
109 if ((
int)poses.size() == numNodes)
114 int motionDirection = 0;
115 while (probLimits[motionDirection] < sampleMove && motionDirection+1 < MO_NUM_ELEMS) {
119 SE2 nextMotionStep = getMotion(motionDirection, stepLen);
120 Simulator::GridPose nextGridPose = generateNewPose(poses.back(), nextMotionStep, transNoise, rotNoise);
123 SE2 nextStepFinalPose = nextGridPose.
truePose * maxStepTransf;
124 if (fabs(nextStepFinalPose.translation().x()) >= bound[0] || fabs(nextStepFinalPose.translation().y()) >= bound[1]) {
127 for (
int i = 0; i < MO_NUM_ELEMS; ++i) {
128 nextMotionStep = getMotion(i, stepLen);
129 nextGridPose = generateNewPose(poses.back(), nextMotionStep, transNoise, rotNoise);
130 nextStepFinalPose = nextGridPose.
truePose * maxStepTransf;
131 if (fabs(nextStepFinalPose.translation().x()) < bound[0] && fabs(nextStepFinalPose.translation().y()) < bound[1])
136 poses.push_back(nextGridPose);
138 cerr <<
"done." << endl;
141 cerr <<
"Simulator: Creating landmarks ... ";
143 for (PosesVector::const_iterator it = poses.begin(); it != poses.end(); ++it) {
144 int ccx = (int)round(it->truePose.translation().x());
145 int ccy = (int)round(it->truePose.translation().y());
146 for (
int a=-landmarksRange; a<=landmarksRange; a++)
147 for (
int b=-landmarksRange; b<=landmarksRange; b++){
151 if (landmarksForCell.size() == 0) {
152 for (
int i = 0; i < landMarksPerSquareMeter; ++i) {
158 }
while (
hypot_sqr(offx, offy) < 0.25*0.25);
161 landmarksForCell.push_back(l);
166 cerr <<
"done." << endl;
168 cerr <<
"Simulator: Simulating landmark observations for the poses ... ";
169 double maxSensorSqr = maxSensorRangeLandmarks * maxSensorRangeLandmarks;
171 for (PosesVector::iterator it = poses.begin(); it != poses.end(); ++it) {
173 int cx = (int)round(it->truePose.translation().x());
174 int cy = (int)round(it->truePose.translation().y());
175 int numGridCells = (int)(maxSensorRangeLandmarks) + 1;
180 for (
int xx = cx - numGridCells; xx <= cx + numGridCells; ++xx)
181 for (
int yy = cy - numGridCells; yy <= cy + numGridCells; ++yy) {
183 if (landmarksForCell.size() == 0)
185 for (
size_t i = 0; i < landmarksForCell.size(); ++i) {
188 if (dSqr > maxSensorSqr)
191 if (obs > observationProb)
195 if (l->
seenBy.size() == 0) {
196 Vector2d trueObservation = trueInv * l->
truePose;
197 Vector2d observation = trueObservation;
208 cerr <<
"done." << endl;
212 cerr <<
"Simulator: Adding odometry measurements ... ";
213 for (
size_t i = 1; i < poses.size(); ++i) {
226 cerr <<
"done." << endl;
229 _landmarkObservations.clear();
232 cerr <<
"Simulator: add landmark observations ... ";
233 Matrix2d covariance; covariance.fill(0.);
234 covariance(0, 0) = landmarkNoise[0]*landmarkNoise[0];
235 covariance(1, 1) = landmarkNoise[1]*landmarkNoise[1];
236 Matrix2d information = covariance.inverse();
238 for (
size_t i = 0; i < poses.size(); ++i) {
240 for (
size_t j = 0; j < p.
landmarks.size(); ++j) {
243 landmarks.push_back(*l);
248 for (
size_t i = 0; i < poses.size(); ++i) {
250 SE2 trueInv = (p.
truePose * sensorOffset).inverse();
251 for (
size_t j = 0; j < p.
landmarks.size(); ++j) {
253 Vector2d observation;
254 Vector2d trueObservation = trueInv * l->
truePose;
255 observation = trueObservation;
274 cerr <<
"done." << endl;
279 for (LandmarkGrid::iterator it = grid.begin(); it != grid.end(); ++it) {
280 for (std::map<int, Simulator::LandmarkPtrVector>::iterator itt = it->second.begin(); itt != it->second.end(); ++itt) {
282 for (
size_t i = 0; i < landmarks.size(); ++i)
292 nextPose.
id = prev.
id + 1;
294 SE2 noiseMotion = sampleTransformation(trueMotion, transNoise, rotNoise);
299 SE2 Simulator::getMotion(
int motionDirection,
double stepLen)
301 switch (motionDirection) {
303 return SE2(stepLen, 0, 0.5*
M_PI);
305 return SE2(stepLen, 0, -0.5*
M_PI);
307 cerr <<
"Unknown motion direction" << endl;
308 return SE2(stepLen, 0, -0.5*
M_PI);
312 SE2 Simulator::sampleTransformation(
const SE2& trueMotion_,
const Eigen::Vector2d& transNoise,
double rotNoise)
314 Vector3d trueMotion = trueMotion_.
toVector();
Eigen::Vector2d simulatedPose
std::vector< int > seenBy
std::vector< GridPose, Eigen::aligned_allocator< GridPose > > PosesVector
Eigen::Matrix3d information
std::map< int, std::map< int, Simulator::LandmarkPtrVector > > LandmarkGrid
double uniform_rand(double lowerBndr, double upperBndr)
Eigen::Vector3d toVector() const
const Eigen::Vector2d & translation() const
LandmarkPtrVector landmarks
the landmarks observed by this node
Eigen::Matrix2d information
Simulator(OptimizableGraph *graph_)
Eigen::Vector2d simulatorMeas
double gauss_rand(double sigma)
std::vector< Landmark, Eigen::aligned_allocator< Landmark > > LandmarkVector
std::vector< Landmark * > LandmarkPtrVector