2 #include <boost/foreach.hpp> 3 #include <angles/angles.h> 11 : dynamicVariables_(data.nh, data.nRobots),
12 nh_(data.nh), nParticles_((uint)dynamicVariables_.nParticles), mainRobotID_(data.mainRobotID - 1),
13 nTargets_(data.nTargets), nStatesPerRobot_(data.statesPerRobot), nRobots_(data.nRobots),
14 nSubParticleSets_(data.nTargets *
STATES_PER_TARGET + data.nRobots * data.statesPerRobot + 1),
15 nLandmarks_(data.nLandmarks),
18 seed_(time(0)), initialized_(false),
19 landmarksMap_(data.landmarksMap),
20 robotsUsed_(data.robotsUsed),
22 bufTargetObservations_(data.nRobots),
23 durationSum(ros::WallDuration(0)),
25 state_(data.statesPerRobot, data.nRobots),
26 iteration_oss(new std::ostringstream(
"")),
27 O_TARGET(data.nRobots * data.statesPerRobot),
28 O_WEIGHT(nSubParticleSets_ - 1)
30 ROS_INFO(
"Created particle filter with dimensions %d, %d",
34 dynamic_reconfigure::Server<DynamicConfig>::CallbackType
52 ROS_INFO(
"Dynamic Reconfigure Callback:\n\tparticles = " 53 "%d\n\tresampling_percentage_to_keep = " 54 "%f\n\tpredict_model_stddev = " 55 "%f\n\tOMNI1_alpha=%s\n\tOMNI3_alpha=%s\n\tOMNI4_alpha=%s\n\tOMNI5_" 58 config.groups.resampling.percentage_to_keep,
59 config.groups.target.predict_model_stddev,
60 config.groups.alphas.OMNI1_alpha.c_str(),
61 config.groups.alphas.OMNI3_alpha.c_str(),
62 config.groups.alphas.OMNI4_alpha.c_str(),
63 config.groups.alphas.OMNI5_alpha.c_str());
68 ROS_INFO(
"Resizing particles to %d and re-initializing the pf",
78 config.groups.resampling.percentage_to_keep;
80 config.groups.target.predict_model_stddev;
83 #ifdef RECONFIGURE_ALPHAS 95 uint particlesToSpread =
nParticles_ * particlesRatio;
97 boost::random::uniform_real_distribution<> dist(-radius, radius);
99 for (uint p = 0; p < particlesToSpread; ++p)
110 using namespace boost::random;
139 std::vector<uint> landmarksSeen(
nRobots_, 0);
143 std::vector<subparticles_t> probabilities(
nRobots_,
163 ++(landmarksSeen[r]);
169 Eigen::Matrix<pdata_t, 2, 1> Zrobot(m.
x, m.
y);
175 #pragma omp parallel for 181 Eigen::Matrix<pdata_t, 2, 1> Srobot(
particles_[o_robot +
O_X][p],
185 Eigen::Matrix<pdata_t, 2, 1> LMrobot = Rrobot * (LMglobal - Srobot);
188 Eigen::Matrix<pdata_t, 2, 1> Zerr = LMrobot - Zrobot;
193 float expArg = -0.5 * (Zerr(
O_X) * Zerr(
O_X) / m.
covXX +
195 float detValue = 1.0;
208 probabilities[r][p] *= detValue * exp(expArg);
228 if (0 == landmarksSeen[r])
230 ROS_WARN(
"In this iteration, OMNI%d didn't see any landmarks", r + 1);
251 uint sort_index = sorted[p];
255 o_robot + nStatesPerRobot_ - 1);
269 bool ballSeen =
false;
270 for (std::vector<TargetObservation>::iterator it =
293 pdata_t maxTargetSubParticleWeight, totalWeight;
294 uint m, p, mStar, r, o_robot;
295 float expArg, detValue, Z[3], Zcap[3], Z_Zcap[3];
302 maxTargetSubParticleWeight = -1.0f;
307 #pragma omp parallel for private(p, r, o_robot, obs, expArg, detValue, Z, \ 313 std::vector<pdata_t> probabilities(
nRobots_, 0.0);
340 Z_Zcap[0] = Z[0] - Zcap[0];
341 Z_Zcap[1] = Z[1] - Zcap[1];
342 Z_Zcap[2] = Z[2] - Zcap[2];
344 expArg = -0.5 * (Z_Zcap[0] * Z_Zcap[0] / obs->
covXX +
345 Z_Zcap[1] * Z_Zcap[1] / obs->
covYY +
346 Z_Zcap[2] * Z_Zcap[2] / .04);
351 probabilities[r] = detValue * exp(expArg);
356 std::accumulate(probabilities.begin(), probabilities.end(), 0.0);
360 if (totalWeight > maxTargetSubParticleWeight)
367 if (totalWeight > maxTargetSubParticleWeight)
369 maxTargetSubParticleWeight = totalWeight;
397 std::vector<pdata_t> cumulativeWeights(
nParticles_);
398 cumulativeWeights[0] = duplicate[
O_WEIGHT][0];
402 cumulativeWeights[par] =
403 cumulativeWeights[par - 1] + duplicate[
O_WEIGHT][par];
406 int startParticle = nParticles_ * startAt;
409 for (uint par = startParticle; par <
nParticles_; par++)
411 boost::random::uniform_real_distribution<> dist(0, 1);
412 double randNo = dist(
seed_);
415 while (randNo > cumulativeWeights[m])
424 boost::random::uniform_real_distribution<> dist(0, 1);
425 double randNo = dist(
seed_);
428 while (randNo > cumulativeWeights[m])
470 ROS_WARN(
"Zero weightsum - returning without resampling");
505 normalizedWeights[p] = normalizedWeights[p] / weightSum;
537 std::vector<double> weightedMeans(nStatesPerRobot_ - 1, 0.0);
542 double weightedMeanThetaCartesian[2] = { 0, 0 };
548 for (uint g = 0; g < nStatesPerRobot_ - 1; ++g)
550 weightedMeans[g] +=
particles_[o_robot + g][p] * normalizedWeights[p];
554 weightedMeanThetaCartesian[
O_X] +=
556 weightedMeanThetaCartesian[
O_Y] +=
561 double weightedMeanThetaPolar =
562 atan2(weightedMeanThetaCartesian[
O_Y], weightedMeanThetaCartesian[
O_X]);
579 targetWeightedMeans[t] +=
595 std::ostringstream debug;
596 debug <<
"Weights " << pre;
600 ROS_DEBUG(
"%s", debug.str().c_str());
615 for (
size_t i = 0; i < defRand.size(); i += 2)
618 defRand[i + 1] = rvalue;
621 std::vector<double> defPos((
nRobots_ * 2), 0.0);
624 init(defRand, defPos);
629 const std::vector<double>& customPosInit)
637 bool flag_theta_given = (customPosInit.size() ==
nRobots_ * 3 &&
640 flag_theta_given ? customRandInit.size() / 3 : customRandInit.size() / 2;
642 ROS_INFO(
"Initializing particle filter");
645 for (
size_t i = 0; i < numVars; ++i)
647 ROS_DEBUG(
"Values for distribution: %.4f %.4f", customRandInit[2 * i],
648 customRandInit[2 * i + 1]);
650 boost::random::uniform_real_distribution<> dist(customRandInit[2 * i],
651 customRandInit[2 * i + 1]);
667 if (flag_theta_given)
673 ROS_INFO(
"Particle filter initialized");
677 const ros::Time stamp)
682 *
iteration_oss <<
"predict(OMNI" << robotNumber + 1 <<
") -> ";
690 using namespace boost::random;
697 pdata_t deltaRot = atan2(odom.
y, odom.
x);
698 pdata_t deltaTrans = sqrt(odom.
x * odom.
x + odom.
y * odom.
y);
702 normal_distribution<> deltaRotEffective(deltaRot, alpha[0] * fabs(deltaRot) +
703 alpha[1] * deltaTrans);
705 normal_distribution<> deltaTransEffective(
707 alpha[2] * deltaTrans + alpha[3] * fabs(deltaRot + deltaFinalRot));
709 normal_distribution<> deltaFinalRotEffective(
710 deltaFinalRot, alpha[0] * fabs(deltaFinalRot) + alpha[1] * deltaTrans);
732 uint nLandmarksSeen = 0;
733 for (std::vector<LandmarkObservation>::iterator it =
745 boost::random::uniform_real_distribution<> randPar(-0.05, 0.05);
758 boost::mutex::scoped_lock(
mutex_);
767 ROS_INFO(
"(WALL TIME) Odometry analyzed with = %fms",
777 ROS_INFO_STREAM(
"(WALL TIME) Iteration time: " 794 *
iteration_oss <<
"allLandmarks(OMNI" << robotNumber + 1 <<
") -> ";
799 *
iteration_oss <<
"allTargets(OMNI" << robotNumber + 1 <<
") -> ";
804 : firstCallback(true), alpha(nRobots, std::vector<float>(
NUM_ALPHAS))
815 for (uint r = 0; r < nRobots; ++r)
817 std::string paramName =
818 "OMNI" + boost::lexical_cast<std::string>(r + 1) +
"_alpha";
821 if (readParam<std::string>(nh, paramName, str))
829 const std::string& str)
832 std::istringstream iss(str);
835 while (std::getline(iss, token,
','))
840 std::istringstream tokss(token);
846 ROS_WARN(
"Invalid alpha value %f", val);
850 alpha[robot][tokenCount] = val;
855 "Number of alpha values provided is not the required number %d",
struct pfuclt_omni_dataset::ParticleFilter::dynamicVariables_s dynamicVariables_
void fill_alpha(const uint robot, const std::string &str)
dynamic_reconfigure::Server< DynamicConfig > dynamicServer_
void resetWeights(pdata_t val)
resetWeights - assign the value val to all particle weights
std::vector< pdata_t > subparticles_t
#define STATES_PER_TARGET
void printWeights(std::string pre)
printWeights
std::vector< TargetObservation > bufTargetObservations_
void fuseRobots()
fuseRobots - fuse robot states step
std::size_t size()
size - interface to the size of the particle filter
uint16_t numberIterations
dynamicVariables_s(ros::NodeHandle &nh, const uint nRobots)
struct pfuclt_omni_dataset::ParticleFilter::State::targetState_s target
particles_t weightComponents_
ParticleFilter(struct PFinitData &data)
ParticleFilter - constructor.
ros::Time savedLatestObservationTime_
const uint nStatesPerRobot_
std::vector< std::vector< float > > alpha
void resample()
resample - the resampling step
std::vector< RobotState > robots
double oldTargetRandSTddev
double resamplingPercentageToKeep
void init()
init - initialize the particle filter set with the default randomized values
void modifiedMultinomialResampler(uint startAt)
modifiedMultinomialResampler - a costly resampler that keeps 50% of the particles and implements the ...
ros::Time latestObservationTime_
std::vector< std::vector< LandmarkObservation > > bufLandmarkObservations_
void spreadTargetParticlesSphere(float particlesRatio, pdata_t center[3], float radius)
spreadTargetParticlesSphere - spread a percentage of the target particle in a sphere around center ...
#define TARGET_RAND_STDDEV_LOST
void predictTarget()
predictTarget - predict target state step
void estimate()
estimate - state estimation through weighted means of particle weights
The PFinitData struct - provides encapsulation to the initial data necessary to construct a ParticleF...
void saveAllTargetMeasurementsDone(const uint robotNumber)
saveAllTargetMeasurementsDone - call this function when all target measurements have been performed b...
const uint nSubParticleSets_
ros::WallDuration deltaIteration_
std::vector< pdata_t > pos
void fuseTarget()
fuseTarget - fuse target state step
void dynamicReconfigureCallback(pfuclt_omni_dataset::DynamicConfig &)
dynamicReconfigureCallback - Dynamic reconfigure callback for dynamically setting variables during ru...
const std::vector< bool > & robotsUsed_
TimeEval targetIterationTime_
boost::shared_ptr< std::ostringstream > iteration_oss
virtual void nextIteration()
nextIteration - perform final steps before next iteration
ros::WallDuration durationSum
ros::WallDuration maxDeltaIteration_
std::vector< subparticles_t > particles_t
void predict(const uint robotNumber, const Odometry odom, const ros::Time stamp)
predict - prediction step in the particle filter set with the received odometry
virtual void resize_particles(const uint n)
resize_particles - change to a different number of particles
double updateTime(ros::Time t)
updateTime - adds the newest time available to the struct and returns the time difference ...
ros::WallTime iterationEvalTime_
void copyParticle(particles_t &p_To, particles_t &p_From, uint i_To, uint i_From)
copyParticle - copies a whole particle from one particle set to another
void saveAllLandmarkMeasurementsDone(const uint robotNumber)
saveAllLandmarkMeasurementsDone - call this function when all landmark measurements have been perform...
const std::vector< Landmark > & landmarksMap_