pfuclt_publisher.cpp
Go to the documentation of this file.
1 #include <read_omni_dataset/read_omni_dataset.h> // defines version of messages
3 
4 namespace pfuclt_omni_dataset {
5 
7  struct PublishData publishData)
8  : ParticleFilter(data), pubData(publishData),
9  particleStdPublishers_(data.nRobots),
10  robotGTPublishers_(data.nRobots), robotEstimatePublishers_(data.nRobots),
11  robotBroadcasters(data.nRobots){
12  // Prepare particle message
14 
15  // Subscribe to GT data
16  GT_sub_ = nh_.subscribe<read_omni_dataset::LRMGTData>(
17  "/gtData_4robotExp", 10,
18  boost::bind(&PFPublisher::gtDataCallback, this, _1));
19 
20  // Other publishers
22  nh_.advertise<read_omni_dataset::Estimate>("/pfuclt_estimate", 100);
24  nh_.advertise<pfuclt_omni_dataset::particles>("/pfuclt_particles", 10);
25 
26  // Rviz visualization publishers
27  // Target
29  nh_.advertise<geometry_msgs::PointStamped>("/target/estimatedPose", 1000);
31  nh_.advertise<geometry_msgs::PointStamped>("/target/gtPose", 1000);
33  nh_.advertise<sensor_msgs::PointCloud>("/target/particles", 10);
34 
35  // target observations publisher
37  nh_.advertise<visualization_msgs::Marker>("/targetObservations", 100);
38 
39  // Robots
40  for (uint r = 0; r < nRobots_; ++r) {
41  std::ostringstream robotName;
42  robotName << "omni" << r + 1;
43 
44  // particle publisher
45  particleStdPublishers_[r] = nh_.advertise<geometry_msgs::PoseArray>(
46  "/" + robotName.str() + "/particles", 1000);
47 
48  // estimated state
49  robotEstimatePublishers_[r] = nh_.advertise<geometry_msgs::PoseStamped>(
50  "/" + robotName.str() + "/estimatedPose", 1000);
51 
52  // build estimate msg
53  msg_estimate_.robotEstimates.push_back(geometry_msgs::Pose());
54  msg_estimate_.targetVisibility.push_back(false);
55 
56 // ground truth publisher, in the simulation package we have PoseStamped
57 #ifndef USE_NEWER_READ_OMNI_PACKAGE
58  robotGTPublishers_[r] = nh_.advertise<geometry_msgs::PointStamped>(
59  "/" + robotName.str() + "/gtPose", 1000);
60 #else
61  robotGTPublishers_[r] = nh_.advertise<geometry_msgs::PoseStamped>(
62  "/" + robotName.str() + "/gtPose", 1000);
63 #endif
64  }
65 
66  ROS_INFO("It's a publishing particle filter!");
67 }
68 
70  // The eval package would rather have the particles in the format
71  // particle->subparticle instead, so we have to inverse it
72  for (uint p = 0; p < nParticles_; ++p) {
73  for (uint s = 0; s < nSubParticleSets_; ++s) {
74  msg_particles_.particles[p].particle[s] = particles_[s][p];
75  }
76  }
77 
78  // Send it!
80 
81  // Also send as a series of PoseArray messages for each robot
82  for (uint r = 0; r < nRobots_; ++r) {
83  if (false == robotsUsed_[r])
84  continue;
85 
86  uint o_robot = r * nStatesPerRobot_;
87  geometry_msgs::PoseArray msgStd_particles;
88  msgStd_particles.header.stamp = savedLatestObservationTime_;
89  msgStd_particles.header.frame_id = "world";
90 
91  for (uint p = 0; p < nParticles_; ++p) {
92  tf2::Quaternion tf2q(tf2::Vector3(0, 0, 1),
93  particles_[o_robot + O_THETA][p]);
94  tf2::Transform tf2t(tf2q, tf2::Vector3(particles_[o_robot + O_X][p],
95  particles_[o_robot + O_Y][p],
97 
98  geometry_msgs::Pose pose;
99  tf2::toMsg(tf2t, pose);
100  msgStd_particles.poses.insert(msgStd_particles.poses.begin(), pose);
101  }
102 
103  particleStdPublishers_[r].publish(msgStd_particles);
104  }
105 
106  // Send target particles as a pointcloud
107  sensor_msgs::PointCloud target_particles;
108  target_particles.header.stamp = ros::Time::now();
109  target_particles.header.frame_id = "world";
110 
111  for (uint p = 0; p < nParticles_; ++p) {
112  geometry_msgs::Point32 point;
113  point.x = particles_[O_TARGET + O_TX][p];
114  point.y = particles_[O_TARGET + O_TY][p];
115  point.z = particles_[O_TARGET + O_TZ][p];
116 
117  target_particles.points.insert(target_particles.points.begin(), point);
118  }
119  targetParticlePublisher_.publish(target_particles);
120 }
121 
123  // This is pretty much copy and paste
124  for (uint r = 0; r < nRobots_; ++r) {
125  if (false == robotsUsed_[r])
126  continue;
127 
128  std::ostringstream robotName;
129  robotName << "omni" << r + 1;
130 
132 
134  geometry_msgs::Pose &rosState = msg_estimate_.robotEstimates[r];
135 
136  // Create from Euler angles
137  tf2::Quaternion tf2q(tf2::Vector3(0, 0, 1), pfState.pose[O_THETA]);
138  tf2::Transform tf2t(tf2q, tf2::Vector3(pfState.pose[O_X], pfState.pose[O_Y],
140 
141  // Transform to our message type
142  tf2::toMsg(tf2t, rosState);
143 
144  // TF2 broadcast
145  geometry_msgs::TransformStamped estTransf;
146  estTransf.header.stamp = savedLatestObservationTime_;
147  estTransf.header.frame_id = "world";
148  estTransf.child_frame_id = robotName.str() + "est";
149  estTransf.transform = tf2::toMsg(tf2t);
150  robotBroadcasters[r].sendTransform(estTransf);
151 
152  // Publish as a standard pose msg using the previous TF
153  geometry_msgs::PoseStamped estPose;
154  estPose.header.stamp = estTransf.header.stamp;
155  estPose.header.frame_id = estTransf.child_frame_id;
156  // Pose is everything at 0 as it's the same as the TF
157 
158  robotEstimatePublishers_[r].publish(estPose);
159  }
160 }
161 
163  msg_estimate_.targetEstimate.header.frame_id = "world";
164 
165  // Our custom message type
166  msg_estimate_.targetEstimate.x = state_.target.pos[O_TX];
167  msg_estimate_.targetEstimate.y = state_.target.pos[O_TY];
168  msg_estimate_.targetEstimate.z = state_.target.pos[O_TZ];
169  msg_estimate_.targetEstimate.found = state_.target.seen;
170 
171  for (uint r = 0; r < nRobots_; ++r) {
172  msg_estimate_.targetVisibility[r] = bufTargetObservations_[r].found;
173  }
174 
175  // Publish as a standard pose msg using the previous TF
176  geometry_msgs::PointStamped estPoint;
177  estPoint.header.stamp = ros::Time::now();
178  estPoint.header.frame_id = "world";
179  estPoint.point.x = state_.target.pos[O_TX];
180  estPoint.point.y = state_.target.pos[O_TY];
181  estPoint.point.z = state_.target.pos[O_TZ];
182 
183  targetEstimatePublisher_.publish(estPoint);
184 }
185 
187  // msg_estimate_ has been built in other methods (publishRobotStates and
188  // publishTargetState)
189  msg_estimate_.computationTime = deltaIteration_.toNSec() * 1e-9;
190  msg_estimate_.converged = converged_;
191 
193 }
194 
196  static std::vector<bool> previouslyPublished(nRobots_, false);
197 
198  for (uint r = 0; r < nRobots_; ++r) {
199  // Publish as rviz standard visualization types (an arrow)
200  visualization_msgs::Marker marker;
201 
202  if (!robotsUsed_[r])
203  continue;
204 
205  // Robot and observation
206  std::ostringstream robotName;
207  robotName << "omni" << r + 1;
208 
210 
211  // If not found, let's just publish that one time
212  if (obs.found == false) {
213  if (previouslyPublished[r])
214  continue;
215  else
216  previouslyPublished[r] = true;
217  } else
218  previouslyPublished[r] = false;
219 
220  marker.header.frame_id = robotName.str() + "est";
221  marker.header.stamp = savedLatestObservationTime_;
222 
223  // Setting the same namespace and id will overwrite the previous marker
224  marker.ns = robotName.str() + "_target_observations";
225  marker.id = 0;
226 
227  marker.type = visualization_msgs::Marker::ARROW;
228  marker.action = visualization_msgs::Marker::ADD;
229 
230  // Arrow draw
231  geometry_msgs::Point tail;
232  tail.x = tail.y = tail.z = 0.0;
233  // Point at index 0 - tail tip - is 0,0,0 because we're in the local frame
234  marker.points.push_back(tail);
235  // Point at index 1 - head - is the target pose in the local frame
236  geometry_msgs::Point head;
237  head.x = obs.x;
238  head.y = obs.y;
239  head.z = obs.z - pubData.robotHeight;
240  marker.points.push_back(head);
241 
242  marker.scale.x = 0.01;
243  marker.scale.y = 0.03;
244  marker.scale.z = 0.05;
245 
246  // Colour
247  marker.color.a = 1;
248  if (obs.found)
249  marker.color.r = marker.color.g = marker.color.b = 0.6;
250  else {
251  marker.color.r = 1.0;
252  marker.color.g = marker.color.b = 0.0;
253  }
254 
255  // Other
256  marker.lifetime = ros::Duration(2);
257 
258  // Send it
259  targetObservationsPublisher_.publish(marker);
260  }
261 }
262 
264  geometry_msgs::PointStamped gtPoint;
265  gtPoint.header.stamp = savedLatestObservationTime_;
266  gtPoint.header.frame_id = "world";
267 
268 #ifdef USE_NEWER_READ_OMNI_PACKAGE
269  geometry_msgs::PoseStamped gtPose;
270  gtPose.header.stamp = savedLatestObservationTime_;
271  gtPose.header.frame_id = "world";
272 
273  for (uint r = 0; r < nRobots_; ++r) {
274  gtPose.pose = msg_GT_.poseOMNI[r].pose;
275  robotGTPublishers_[r].publish(gtPose);
276  }
277 
278 #else
279  if (true == robotsUsed_[0])
280  {
281  gtPoint.point = msg_GT_.poseOMNI1.pose.position;
282  robotGTPublishers_[0].publish(gtPoint);
283  }
284 
285  if (true == robotsUsed_[2])
286  {
287  gtPoint.point = msg_GT_.poseOMNI3.pose.position;
288  robotGTPublishers_[2].publish(gtPoint);
289  }
290 
291  if (true == robotsUsed_[3])
292  {
293  gtPoint.point = msg_GT_.poseOMNI4.pose.position;
294  robotGTPublishers_[3].publish(gtPoint);
295  }
296 
297  if (true == robotsUsed_[4])
298  {
299  gtPoint.point = msg_GT_.poseOMNI5.pose.position;
300  robotGTPublishers_[4].publish(gtPoint);
301  }
302 #endif
303 
304  // Publish for the target as well
305  if (msg_GT_.orangeBall3DGTposition.found) {
306  gtPoint.point.x = msg_GT_.orangeBall3DGTposition.x;
307  gtPoint.point.y = msg_GT_.orangeBall3DGTposition.y;
308  gtPoint.point.z = msg_GT_.orangeBall3DGTposition.z;
309  targetGTPublisher_.publish(gtPoint);
310  }
311 }
312 
314  const read_omni_dataset::LRMGTData::ConstPtr &gtMsgReceived) {
315  msg_GT_ = *gtMsgReceived;
316 }
317 
319  // Call the base class method
321 
322  // Publish the particles first
324 
325  // Publish robot states
327 
328  // Publish target state
330 
331  // Publish estimate
332  publishEstimate();
333 
334  // Publish robot-to-target lines
336 
337 // Publish GT data if we have received any callback
338 #ifdef USE_NEWER_READ_OMNI_PACKAGE
339  if (!msg_GT_.poseOMNI.empty())
340  publishGTData();
341 #else
342  publishGTData();
343 #endif
344 };
345 }
std::vector< ros::Publisher > robotEstimatePublishers_
read_omni_dataset::LRMGTData msg_GT_
#define O_X
#define O_TX
struct pfuclt_omni_dataset::PFPublisher::PublishData pubData
std::vector< TargetObservation > bufTargetObservations_
struct pfuclt_omni_dataset::ParticleFilter::State::targetState_s target
#define O_Y
The robotState_s struct - saves information on the belief of a robot&#39;s state.
#define O_TY
std::vector< ros::Publisher > particleStdPublishers_
void gtDataCallback(const read_omni_dataset::LRMGTData::ConstPtr &)
gtDataCallback - callback of ground truth data
read_omni_dataset::Estimate msg_estimate_
std::vector< tf2_ros::TransformBroadcaster > robotBroadcasters
void nextIteration()
nextIteration - extends the base class method to add the ROS publishing
std::vector< ros::Publisher > robotGTPublishers_
The PFinitData struct - provides encapsulation to the initial data necessary to construct a ParticleF...
#define O_THETA
const std::vector< bool > & robotsUsed_
pfuclt_omni_dataset::particles msg_particles_
virtual void nextIteration()
nextIteration - perform final steps before next iteration
#define O_TZ
PFPublisher(struct PFinitData &data, struct PublishData publishData)
PFPublisher - constructor.
void resize_particles(const uint n)
resize_particles - change to a different number of particles and resize the publishing message ...


pfuclt_omni_dataset
Author(s):
autogenerated on Tue Jul 4 2017 19:38:38