9 return boost::math::isnan(a);
14 a = atan2(sin(a),cos(a));
15 b = atan2(sin(b),cos(b));
17 double d2 = 2 * M_PI - fabs(d1);
20 if(fabs(d1) < fabs(d2))
35 mRangeCount = scan->ranges.size();
36 mRanges =
new double[mRangeCount][2];
37 mRangeMax = scan->range_max;
39 double angle_min = scan->angle_min;
40 double angle_inc = scan->angle_increment;
42 angle_inc = fmod(angle_inc + 5*M_PI, 2*M_PI) - M_PI;
44 for(
int i = 0; i < mRangeCount; i++)
46 if(scan->ranges[i] <= scan->range_min)
47 mRanges[i][0] = scan->range_max;
49 mRanges[i][0] = scan->ranges[i];
52 mRanges[i][1] = angle_min + (i * angle_inc);
81 : mPublishParticles(publish)
158 double min_x, max_x, min_y, max_y;
169 p.
v[0] = min_x + drand48() * (max_x - min_x);
170 p.
v[1] = min_y + drand48() * (max_y - min_y);
171 p.
v[2] = drand48() * 2 * M_PI - M_PI;
186 double delta_rot1, delta_trans, delta_rot2;
187 double delta_rot1_hat, delta_trans_hat, delta_rot2_hat;
188 double delta_rot1_noise, delta_rot2_noise;
193 if(delta_trans < 0.01)
203 delta_rot1_noise = std::min(fabs(
angle_diff(delta_rot1,0.0)), fabs(
angle_diff(delta_rot1,M_PI)));
204 delta_rot2_noise = std::min(fabs(
angle_diff(delta_rot2,0.0)), fabs(
angle_diff(delta_rot2,M_PI)));
206 for (
int i = 0; i <
set->sample_count; i++)
216 sample->
pose.
v[0] += delta_trans_hat * cos(sample->
pose.
v[2] + delta_rot1_hat);
217 sample->
pose.
v[1] += delta_trans_hat * sin(sample->
pose.
v[2] + delta_rot1_hat);
218 sample->
pose.
v[2] += delta_rot1_hat + delta_rot2_hat;
219 sample->
weight = 1.0 /
set->sample_count;
231 double obsRange, obsBearing;
234 double totalWeight = 0.0;
236 for (
int j = 0; j <
set->sample_count; j++)
238 sample =
set->samples + j;
248 obsRange = data->
mRanges[i][0];
249 obsBearing = data->
mRanges[i][1];
254 z = obsRange - mapRange;
266 if(obsRange < data->mRangeMax)
277 totalWeight += sample->
weight;
285 double obsRange, obsBearing;
286 double totalWeight = 0.0;
292 for (
int j = 0; j <
set->sample_count; j++)
294 sample =
set->samples + j;
302 double zRandMult = 1.0 / data->
mRangeMax;
308 obsRange = data->
mRanges[i][0];
309 obsBearing = data->
mRanges[i][1];
319 hit.
v[0] = pose.
v[0] + obsRange * cos(pose.
v[2] + obsBearing);
320 hit.
v[1] = pose.
v[1] + obsRange * sin(pose.
v[2] + obsBearing);
335 pz +=
sZHit * exp(-(z * z) / zHitDenom);
342 if(pz < 0.0 || pz > 1.0)
343 ROS_WARN(
"Value pz = %.2f, but it should be in range 0..1", pz);
351 totalWeight += sample->
weight;
366 ROS_INFO(
"Initialized PF with %d samples.",
set->sample_count);
396 if(
sMap == NULL)
return;
413 ROS_WARN(
"Failed to compute odometry pose, skipping scan (%s)", e.what());
451 robot2map.
stamp_ = scan->header.stamp;
459 ROS_WARN(
"Failed to subtract base to odom transform");
471 map->
size_x = map_msg.info.width;
472 map->
size_y = map_msg.info.height;
473 map->
scale = map_msg.info.resolution;
482 if(map_msg.data[i] == 0)
484 else if(map_msg.data[i] == 100)
496 ROS_INFO(
"Initializing likelihood field model. This can take some time on large maps...");
504 double max =
set->cov.m[0][0];
505 if(
set->cov.m[1][1] > max) max =
set->cov.m[1][1];
506 if(
set->cov.m[2][2] > max) max =
set->cov.m[2][2];
519 double max_weight = 0.0;
521 for(
int i = 0; i <
set->cluster_count; i++)
528 ROS_ERROR(
"Couldn't get stats on cluster %d", i);
532 if(weight > max_weight)
541 ROS_DEBUG(
"Determined pose at: %.3f %.3f %.3f", pose.
v[0], pose.
v[1], pose.
v[2]);
544 ROS_ERROR(
"Could not get pose from particle filter!");
562 geometry_msgs::PoseArray cloud_msg;
564 cloud_msg.header.frame_id =
mMapFrame.c_str();
565 cloud_msg.poses.resize(
set->sample_count);
566 for(
int i = 0; i <
set->sample_count; i++)
568 double x =
set->samples[i].pose.v[0];
569 double y =
set->samples[i].pose.v[1];
570 double yaw =
set->samples[i].pose.v[2];
575 geometry_msgs::Pose pose_check = cloud_msg.poses.at(i);
576 geometry_msgs::Point pt = pose_check.position;
578 ROS_WARN(
"NaN occured at pt.x before publishing particle cloud...");
580 ROS_WARN(
"NaN occured at pt.y before publishing particle cloud...");
582 ROS_WARN(
"NaN occured at pt.z before publishing particle cloud...");
583 geometry_msgs::Quaternion ori = pose_check.orientation;
585 ROS_WARN(
"NaN occured at ori.x before publishing particle cloud, setting it to zero (original x:%f y:%f yaw:%f) ...",
set->samples[i].pose.v[0],
set->samples[i].pose.v[1],
set->samples[i].pose.v[2]);
586 cloud_msg.poses.at(i).orientation.x = 0;
589 ROS_WARN(
"NaN occured at ori.y before publishing particle cloud, setting it to zero (original x:%f y:%f yaw:%f) ...",
set->samples[i].pose.v[0],
set->samples[i].pose.v[1],
set->samples[i].pose.v[2]);
590 cloud_msg.poses.at(i).orientation.y = 0;
593 ROS_WARN(
"NaN occured at ori.z before publishing particle cloud ...");
595 ROS_WARN(
"NaN occured at ori.w before publishing particle cloud ...");
OdometryData(const tf::StampedTransform &pNewPose, const tf::StampedTransform &pLastPose)
double(* pf_sensor_model_fn_t)(void *sensor_data, struct _pf_sample_set_t *set)
void map_update_cspace(map_t *map, double max_occ_dist)
pf_action_model_fn_t mActionModelFunction
void process(const sensor_msgs::LaserScan::ConstPtr &scan)
void publish(const boost::shared_ptr< M > &message) const
static pf_vector_t sLaserPose
void pf_update_sensor(pf_t *pf, pf_sensor_model_fn_t sensor_fn, void *sensor_data)
void setData(const T &input)
#define MAP_VALID(map, i, j)
static double getYaw(const Quaternion &bt_q)
pf_t * pf_alloc(int min_samples, int max_samples, double alpha_slow, double alpha_fast, pf_init_model_fn_t random_pose_fn, void *random_pose_data)
void publishParticleCloud()
static pf_vector_t distributeParticles(void *map)
#define MAP_INDEX(map, i, j)
TFSIMD_FORCE_INLINE const tfScalar & getY() const
double angle_diff(double a, double b)
TFSIMD_FORCE_INLINE const tfScalar & y() const
double map_calc_range(map_t *map, double ox, double oy, double oa, double max_range)
int pf_get_cluster_stats(pf_t *pf, int cluster, double *weight, pf_vector_t *mean, pf_matrix_t *cov)
TFSIMD_FORCE_INLINE const tfScalar & x() const
ROSCPP_DECL void set(const std::string &key, const XmlRpc::XmlRpcValue &v)
SelfLocalizer(bool publish=true)
void pf_update_action(pf_t *pf, pf_action_model_fn_t action_fn, void *action_data)
static Quaternion createQuaternionFromYaw(double yaw)
void convertMap(const nav_msgs::OccupancyGrid &map_msg)
std::string mOdometryFrame
bool param(const std::string ¶m_name, T ¶m_val, const T &default_val) const
TFSIMD_FORCE_INLINE const tfScalar & y() const
ros::Publisher mParticlePublisher
static double sLikelihoodMaxDist
TFSIMD_FORCE_INLINE const tfScalar & x() const
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
tf::Transform mMapToOdometry
void pf_init_model(pf_t *pf, pf_init_model_fn_t init_fn, void *init_data)
pf_vector_t pf_vector_coord_add(pf_vector_t a, pf_vector_t b)
TFSIMD_FORCE_INLINE const tfScalar & z() const
tf::TransformListener mTransformListener
void(* pf_action_model_fn_t)(void *action_data, struct _pf_sample_set_t *set)
pf_sensor_model_fn_t mSensorModelFunction
static void poseTFToMsg(const Pose &bt, geometry_msgs::Pose &msg)
void pf_update_resample(pf_t *pf)
void map_free(map_t *map)
static double calculateLikelihoodFieldModel(LaserData *data, pf_sample_set_t *set)
LaserData(const sensor_msgs::LaserScan::ConstPtr &scan)
TFSIMD_FORCE_INLINE const tfScalar & getX() const
static double calculateMoveModel(OdometryData *data, pf_sample_set_t *set)
static tf::StampedTransform mLastPose
double pf_ran_gaussian(double sigma)
static double calculateBeamModel(LaserData *data, pf_sample_set_t *set)
static double sLamdaShort
tf::Transform getBestPose()