people_tracking_node.cpp
Go to the documentation of this file.
1 /*********************************************************************
2 * Software License Agreement (BSD License)
3 *
4 * Copyright (c) 2008, Willow Garage, Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
17 * * Neither the name of the Willow Garage nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
33 *********************************************************************/
34 
35 /* Author: Wim Meeussen */
36 
42 #include <people_msgs/PositionMeasurement.h>
43 #include <algorithm>
44 #include <list>
45 #include <string>
46 #include <vector>
47 
48 static const double sequencer_delay = 0.8; // TODO(noidea): this is probably too big, it was 0.8
49 static const unsigned int sequencer_internal_buffer = 100;
50 static const unsigned int sequencer_subscribe_buffer = 10;
51 static const unsigned int num_particles_tracker = 1000;
52 static const double tracker_init_dist = 4.0;
53 
54 namespace estimation
55 {
56 // constructor
58  : nh_(nh),
59  robot_state_(),
60  tracker_counter_(0)
61 {
62  // initialize
63  meas_cloud_.points = std::vector<geometry_msgs::Point32>(1);
64  meas_cloud_.points[0].x = 0;
65  meas_cloud_.points[0].y = 0;
66  meas_cloud_.points[0].z = 0;
67 
68  // get parameters
69  ros::NodeHandle local_nh("~");
70  local_nh.param("fixed_frame", fixed_frame_, std::string("default"));
71  local_nh.param("freq", freq_, 1.0);
72  local_nh.param("start_distance_min", start_distance_min_, 0.0);
73  local_nh.param("reliability_threshold", reliability_threshold_, 1.0);
74  local_nh.param("sys_sigma_pos_x", sys_sigma_.pos_[0], 0.0);
75  local_nh.param("sys_sigma_pos_y", sys_sigma_.pos_[1], 0.0);
76  local_nh.param("sys_sigma_pos_z", sys_sigma_.pos_[2], 0.0);
77  local_nh.param("sys_sigma_vel_x", sys_sigma_.vel_[0], 0.0);
78  local_nh.param("sys_sigma_vel_y", sys_sigma_.vel_[1], 0.0);
79  local_nh.param("sys_sigma_vel_z", sys_sigma_.vel_[2], 0.0);
80  local_nh.param("follow_one_person", follow_one_person_, false);
81 
82  // advertise filter output
83  people_filter_pub_ = nh_.advertise<people_msgs::PositionMeasurement>("people_tracker_filter", 10);
84 
85  // advertise visualization
86  people_filter_vis_pub_ = nh_.advertise<sensor_msgs::PointCloud>("people_tracker_filter_visualization", 10);
87  people_tracker_vis_pub_ = nh_.advertise<sensor_msgs::PointCloud>("people_tracker_measurements_visualization", 10);
88 
89  // register message sequencer
90  people_meas_sub_ = nh_.subscribe("people_tracker_measurements", 1, &PeopleTrackingNode::callbackRcv, this);
91 }
92 
93 // destructor
95 {
96  // delete sequencer
97  delete message_sequencer_;
98 
99  // delete all trackers
100  for (std::list<Tracker*>::iterator it = trackers_.begin(); it != trackers_.end(); it++)
101  delete *it;
102 };
103 
104 // callback for messages
105 void PeopleTrackingNode::callbackRcv(const people_msgs::PositionMeasurement::ConstPtr& message)
106 {
107  ROS_DEBUG("Tracking node got a people position measurement (%f,%f,%f)",
108  message->pos.x, message->pos.y, message->pos.z);
109  // get measurement in fixed frame
110  tf::Stamped<tf::Vector3> meas_rel, meas;
111  meas_rel.setData(
112  tf::Vector3(message->pos.x, message->pos.y, message->pos.z));
113  meas_rel.stamp_ = message->header.stamp;
114  meas_rel.frame_id_ = message->header.frame_id;
115  robot_state_.transformPoint(fixed_frame_, meas_rel, meas);
116 
117  // get measurement covariance
118  BFL::SymmetricMatrix cov(3);
119  for (unsigned int i = 0; i < 3; i++)
120  for (unsigned int j = 0; j < 3; j++)
121  cov(i + 1, j + 1) = message->covariance[3 * i + j];
122 
123  // ----- LOCKED ------
124  boost::mutex::scoped_lock lock(filter_mutex_);
125 
126  // update tracker if matching tracker found
127  for (std::list<Tracker*>::iterator it = trackers_.begin(); it != trackers_.end(); it++)
128  if ((*it)->getName() == message->object_id)
129  {
130  (*it)->updatePrediction(message->header.stamp.toSec());
131  (*it)->updateCorrection(meas, cov);
132  }
133  // check if reliable message with no name should be a new tracker
134  if (message->object_id == "" && message->reliability > reliability_threshold_)
135  {
136  double closest_tracker_dist = start_distance_min_;
137  BFL::StatePosVel est;
138  for (std::list<Tracker*>::iterator it = trackers_.begin(); it != trackers_.end(); it++)
139  {
140  (*it)->getEstimate(est);
141  double dst = sqrt(pow(est.pos_[0] - meas[0], 2) + pow(est.pos_[1] - meas[1], 2));
142  if (dst < closest_tracker_dist)
143  closest_tracker_dist = dst;
144  }
145  // initialize a new tracker
146  if (follow_one_person_)
147  std::cout << "Following one person" << std::endl;
148  if (message->initialization == 1 &&
149  ((!follow_one_person_ && (closest_tracker_dist >= start_distance_min_)) ||
150  (follow_one_person_ && trackers_.empty())))
151  {
152  // if (closest_tracker_dist >= start_distance_min_ || message->initialization == 1){
153  // if (message->initialization == 1 && trackers_.empty()){
154  ROS_INFO("Passed crazy conditional.");
155  tf::Point pt;
156  tf::pointMsgToTF(message->pos, pt);
157  tf::Stamped<tf::Point> loc(pt, message->header.stamp, message->header.frame_id);
158  robot_state_.transformPoint("base_link", loc, loc);
159  float cur_dist;
160  if ((cur_dist = pow(loc[0], 2.0) + pow(loc[1], 2.0)) < tracker_init_dist)
161  {
162  std::cout << "starting new tracker" << std::endl;
163  std::stringstream tracker_name;
164  BFL::StatePosVel prior_sigma(tf::Vector3(sqrt(cov(1, 1)),
165  sqrt(cov(2, 2)),
166  sqrt(cov(3, 3))),
167  tf::Vector3(0.0000001, 0.0000001, 0.0000001));
168  tracker_name << "person " << tracker_counter_++;
169  Tracker* new_tracker = new TrackerKalman(tracker_name.str(),
170  sys_sigma_);
171  // Tracker* new_tracker = new TrackerParticle(tracker_name.str(), num_particles_tracker, sys_sigma_);
172  new_tracker->initialize(meas, prior_sigma,
173  message->header.stamp.toSec());
174  trackers_.push_back(new_tracker);
175  ROS_INFO("Initialized new tracker %s", tracker_name.str().c_str());
176  }
177  else
178  ROS_INFO("Found a person, but he/she is not close enough to start following. "
179  "Person is %f away, and must be less than %f away.", cur_dist, tracker_init_dist);
180  }
181  else
182  ROS_INFO("Failed crazy conditional.");
183  }
184  lock.unlock();
185  // ------ LOCKED ------
186 
187  // visualize measurement
188  meas_cloud_.points[0].x = meas[0];
189  meas_cloud_.points[0].y = meas[1];
190  meas_cloud_.points[0].z = meas[2];
191  meas_cloud_.header.frame_id = meas.frame_id_;
193 }
194 
195 // callback for dropped messages
196 void PeopleTrackingNode::callbackDrop(const people_msgs::PositionMeasurement::ConstPtr& message)
197 {
198  ROS_INFO("DROPPED PACKAGE for %s from %s with delay %f !!!!!!!!!!!",
199  message->object_id.c_str(), message->name.c_str(), (ros::Time::now() - message->header.stamp).toSec());
200 }
201 
202 // filter loop
204 {
205  ROS_INFO("People tracking manager started.");
206 
207  while (ros::ok())
208  {
209  // ------ LOCKED ------
210  boost::mutex::scoped_lock lock(filter_mutex_);
211 
212  // visualization variables
213  std::vector<geometry_msgs::Point32> filter_visualize(trackers_.size());
214  std::vector<float> weights(trackers_.size());
215  sensor_msgs::ChannelFloat32 channel;
216 
217  // loop over trackers
218  unsigned int i = 0;
219  std::list<Tracker*>::iterator it = trackers_.begin();
220  while (it != trackers_.end())
221  {
222  // update prediction up to delayed time
223  (*it)->updatePrediction(ros::Time::now().toSec() - sequencer_delay);
224 
225  // publish filter result
226  people_msgs::PositionMeasurement est_pos;
227  (*it)->getEstimate(est_pos);
228  est_pos.header.frame_id = fixed_frame_;
229 
230  ROS_DEBUG("Publishing people tracker filter.");
231  people_filter_pub_.publish(est_pos);
232 
233  // visualize filter result
234  filter_visualize[i].x = est_pos.pos.x;
235  filter_visualize[i].y = est_pos.pos.y;
236  filter_visualize[i].z = est_pos.pos.z;
237 
238  // calculate weight
239  {
240  int quality = static_cast<int>(trunc((*it)->getQuality() * 999.0));
241  int index = std::min(998, 999 - std::max(1, quality));
242  weights[i] = *(float*) & (rgb[index]); // NOLINT(readability/casting)
243  }
244 
245  // remove trackers that have zero quality
246  ROS_INFO("Quality of tracker %s = %f", (*it)->getName().c_str(), (*it)->getQuality());
247  if ((*it)->getQuality() <= 0)
248  {
249  ROS_INFO("Removing tracker %s", (*it)->getName().c_str());
250  delete *it;
251  trackers_.erase(it++);
252  }
253  else it++;
254  i++;
255  }
256  lock.unlock();
257  // ------ LOCKED ------
258 
259  // visualize all trackers
260  channel.name = "rgb";
261  channel.values = weights;
262  sensor_msgs::PointCloud people_cloud;
263  people_cloud.channels.push_back(channel);
264  people_cloud.header.frame_id = fixed_frame_;
265  people_cloud.points = filter_visualize;
266  people_filter_vis_pub_.publish(people_cloud);
267 
268  // sleep
269  usleep(1e6 / freq_);
270 
271  ros::spinOnce();
272  }
273 };
274 } // namespace estimation
275 
276 // ----------
277 // -- MAIN --
278 // ----------
279 int main(int argc, char **argv)
280 {
281  // Initialize ROS
282  ros::init(argc, argv, "people_tracker");
283  ros::NodeHandle(nh);
284 
285  // create tracker node
286  estimation::PeopleTrackingNode my_tracking_node(nh);
287 
288  // wait for filter to finish
289  my_tracking_node.spin();
290 
291  return 0;
292 }
static const unsigned int num_particles_tracker
static void pointMsgToTF(const geometry_msgs::Point &msg_v, Point &bt_v)
void publish(const boost::shared_ptr< M > &message) const
void setData(const T &input)
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
void callbackDrop(const people_msgs::PositionMeasurement::ConstPtr &message)
callback for dropped messages
sensor_msgs::PointCloud meas_cloud_
Class representing state with pos and vel.
Definition: state_pos_vel.h:46
void transformPoint(const std::string &target_frame, const geometry_msgs::PointStamped &stamped_in, geometry_msgs::PointStamped &stamped_out) const
void callbackRcv(const people_msgs::PositionMeasurement::ConstPtr &message)
callback for messages
static const unsigned int sequencer_subscribe_buffer
std::list< Tracker * > trackers_
trackers
static const double sequencer_delay
#define ROS_INFO(...)
bool param(const std::string &param_name, T &param_val, const T &default_val) const
virtual void initialize(const BFL::StatePosVel &mu, const BFL::StatePosVel &sigma, const double time)=0
initialize tracker
virtual ~PeopleTrackingNode()
destructor
ROSCPP_DECL bool ok()
static const unsigned int sequencer_internal_buffer
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
message_filters::TimeSequencer< people_msgs::PositionMeasurement > * message_sequencer_
message sequencer
ros::Time stamp_
std::string frame_id_
tf::Vector3 vel_
Definition: state_pos_vel.h:49
static const double tracker_init_dist
static const int rgb[]
Definition: rgb.h:37
PeopleTrackingNode(ros::NodeHandle nh)
constructor
static Time now()
tf::Vector3 pos_
Definition: state_pos_vel.h:49
ROSCPP_DECL void spinOnce()
int main(int argc, char **argv)
#define ROS_DEBUG(...)


people_tracking_filter
Author(s): Caroline Pantofaru
autogenerated on Sun Feb 21 2021 03:56:47