balls_in_box.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2018, The Regents of the University of California (Regents).
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  *
12  * 2. Redistributions in binary form must reproduce the above
13  * copyright notice, this list of conditions and the following
14  * disclaimer in the documentation and/or other materials provided
15  * with the distribution.
16  *
17  * 3. Neither the name of the copyright holder 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 AS IS
22  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  *
33  * Please contact the author(s) of this library if you have any questions.
34  * Authors: David Fridovich-Keil ( dfk@eecs.berkeley.edu )
35  */
36 
38 //
39 // BallsInBox is derived from the Environment base class. This class models
40 // obstacles as spheres to provide a simple demo.
41 //
43 
45 
46 namespace fastrack {
47 namespace environment {
48 
49 // Derived classes must provide a collision checker which returns true if
50 // and only if the provided position is a valid collision-free configuration.
51 // Ignores 'time' since this is a time-invariant environment.
52 bool BallsInBox::IsValid(const Vector3d& position, const TrackingBound& bound,
53  double time) const {
54  if (!initialized_) {
55  ROS_WARN("%s: Tried to collision check an uninitialized BallsInBox.",
56  name_.c_str());
57  return false;
58  }
59 
60  // Check that this position is within the outer environment boundaries.
61  if (!bound.ContainedWithinBox(position, lower_, upper_)) return false;
62 
63  // Check against each obstacle.
64  // NOTE! Just using a linear search here for simplicity.
65  if (centers_.size() > 100) {
66  ROS_WARN_THROTTLE(1.0,
67  "%s: Caution! Linear search may be slowing you down.",
68  name_.c_str());
69  }
70 
71  for (size_t ii = 0; ii < centers_.size(); ii++) {
72  if (bound.OverlapsSphere(position, centers_[ii], radii_[ii])) return false;
73  }
74 
75  return true;
76 }
77 
78 // Update this environment with the information contained in the given
79 // sensor measurement.
80 // NOTE! This function needs to publish on `updated_topic_`.
82  const fastrack_msgs::SensedSpheres::ConstPtr& msg) {
83  // Check list lengths.
84  if (msg->centers.size() != msg->radii.size())
85  ROS_WARN("%s: Malformed SensedSpheres msg.", name_.c_str());
86 
87  const size_t num_obstacles = std::min(msg->centers.size(), msg->radii.size());
88 
89  // Add each unique obstacle to list.
90  // NOTE! Just using a linear search here for simplicity.
91  if (centers_.size() > 100)
92  ROS_WARN_THROTTLE(1.0,
93  "%s: Caution! Linear search may be slowing you down.",
94  name_.c_str());
95 
96  bool any_unique = false;
97  for (size_t ii = 0; ii < num_obstacles; ii++) {
98  const Vector3d p(msg->centers[ii].x, msg->centers[ii].y,
99  msg->centers[ii].z);
100  const double r = msg->radii[ii];
101 
102  // If not unique, discard.
103  bool unique = true;
104  for (size_t jj = 0; jj < centers_.size(); jj++) {
105  if (p.isApprox(centers_[jj], constants::kEpsilon) &&
106  std::abs(r - radii_[jj]) < constants::kEpsilon) {
107  unique = false;
108  break;
109  }
110  }
111 
112  if (unique) {
113  any_unique = true;
114  centers_.push_back(p);
115  radii_.push_back(r);
116  }
117  }
118 
119  if (any_unique) {
120  // Let the system know this environment has been updated.
121  updated_pub_.publish(std_msgs::Empty());
122 
123  // Visualize.
124  Visualize();
125  }
126 }
127 
128 // Generate a sensor measurement as a service response.
129 fastrack_msgs::SensedSpheres BallsInBox::SimulateSensor(
130  const SphereSensorParams& params) const {
131  // Set up msg.
132  fastrack_msgs::SensedSpheres msg;
133  msg.sensor_position.x = params.position(0);
134  msg.sensor_position.y = params.position(1);
135  msg.sensor_position.z = params.position(2);
136  msg.sensor_radius = params.range;
137 
138  // Check each obstacle and, if in range, add to response.
139  geometry_msgs::Vector3 c;
140  for (size_t ii = 0; ii < centers_.size(); ii++) {
141  if ((params.position - centers_[ii]).norm() < params.range + radii_[ii]) {
142  c.x = centers_[ii](0);
143  c.y = centers_[ii](1);
144  c.z = centers_[ii](2);
145 
146  msg.centers.push_back(c);
147  msg.radii.push_back(radii_[ii]);
148  }
149  }
150 
151  return msg;
152 }
153 
154 // Derived classes must have some sort of visualization through RViz.
155 void BallsInBox::Visualize() const {
156  if (vis_pub_.getNumSubscribers() <= 0) return;
157 
158  // Set up box marker.
159  visualization_msgs::Marker cube;
160  cube.ns = "cube";
161  cube.header.frame_id = fixed_frame_;
162  cube.header.stamp = ros::Time::now();
163  cube.id = 0;
164  cube.type = visualization_msgs::Marker::CUBE;
165  cube.action = visualization_msgs::Marker::ADD;
166  cube.color.a = 0.5;
167  cube.color.r = 0.3;
168  cube.color.g = 0.7;
169  cube.color.b = 0.7;
170 
171  geometry_msgs::Point center;
172 
173  // Fill in center and scale.
174  cube.scale.x = upper_(0) - lower_(0);
175  center.x = lower_(0) + 0.5 * cube.scale.x;
176 
177  cube.scale.y = upper_(1) - lower_(1);
178  center.y = lower_(1) + 0.5 * cube.scale.y;
179 
180  cube.scale.z = upper_(2) - lower_(2);
181  center.z = lower_(2) + 0.5 * cube.scale.z;
182 
183  cube.pose.position = center;
184  cube.pose.orientation.x = 0.0;
185  cube.pose.orientation.y = 0.0;
186  cube.pose.orientation.z = 0.0;
187  cube.pose.orientation.w = 1.0;
188 
189  // Publish cube marker.
190  vis_pub_.publish(cube);
191 
192  // Visualize obstacles as spheres.
193  for (size_t ii = 0; ii < centers_.size(); ii++) {
194  visualization_msgs::Marker sphere;
195  sphere.ns = "sphere";
196  sphere.header.frame_id = fixed_frame_;
197  sphere.header.stamp = ros::Time::now();
198  sphere.id = static_cast<int>(ii);
199  sphere.type = visualization_msgs::Marker::SPHERE;
200  sphere.action = visualization_msgs::Marker::ADD;
201 
202  sphere.scale.x = 2.0 * radii_[ii];
203  sphere.scale.y = 2.0 * radii_[ii];
204  sphere.scale.z = 2.0 * radii_[ii];
205 
206  sphere.color.a = 0.9;
207  sphere.color.r = 0.7;
208  sphere.color.g = 0.5;
209  sphere.color.b = 0.5;
210 
211  geometry_msgs::Point p;
212  const Vector3d point = centers_[ii];
213  p.x = point(0);
214  p.y = point(1);
215  p.z = point(2);
216 
217  sphere.pose.position = p;
218 
219  // Publish sphere marker.
220  vis_pub_.publish(sphere);
221  ros::Duration(0.01).sleep();
222  }
223 }
224 
225 // Load parameters. This may be overridden by derived classes if needed
226 // (they should still call this one via Environment::LoadParameters).
227 bool BallsInBox::LoadParameters(const ros::NodeHandle& n) {
228  if (!Environment<fastrack_msgs::SensedSpheres,
229  SphereSensorParams>::LoadParameters(n))
230  return false;
231 
232  ros::NodeHandle nl(n);
233 
234  // Pre-specified obstacles.
235  std::vector<double> obstacle_xs, obstacle_ys, obstacle_zs, obstacle_rs;
236  if (nl.getParam("env/obstacle/xs", obstacle_xs) &&
237  nl.getParam("env/obstacle/ys", obstacle_ys) &&
238  nl.getParam("env/obstacle/zs", obstacle_zs) &&
239  nl.getParam("env/obstacle/rs", obstacle_rs)) {
240  if (obstacle_xs.size() != obstacle_ys.size() ||
241  obstacle_zs.size() != obstacle_rs.size() ||
242  obstacle_ys.size() != obstacle_zs.size()) {
243  ROS_WARN("%s: Pre-specified obstacles are malformed.", name_.c_str());
244  } else {
245  for (size_t ii = 0; ii < obstacle_xs.size(); ii++) {
246  centers_.emplace_back(
247  Vector3d(obstacle_xs[ii], obstacle_ys[ii], obstacle_zs[ii]));
248  radii_.push_back(obstacle_rs[ii]);
249  }
250  }
251  } else {
252  // No pre-specified obstacles.
253  ROS_INFO("%s: No pre-specified obstacles.", name_.c_str());
254  }
255 
256  // Number/size of random obstacles.
257  int num;
258  double min_radius, max_radius;
259  if (!nl.getParam("env/num_random_obstacles", num)) return false;
260  if (!nl.getParam("env/min_radius", min_radius)) return false;
261  if (!nl.getParam("env/max_radius", max_radius)) return false;
262 
263  // Random seed.
264  int seed;
265  if (!nl.getParam("env/seed", seed)) return false;
266 
267  // Generate obstacles.
268  GenerateObstacles(static_cast<size_t>(num), min_radius, max_radius, seed);
269 
270  return true;
271 }
272 
273 // Generate random obstacles.
274 void BallsInBox::GenerateObstacles(size_t num, double min_radius,
275  double max_radius, unsigned int seed) {
276  // Create a random number generator.
277  std::random_device rd;
278  std::default_random_engine rng(rd());
279  rng.seed(seed);
280 
281  // Set up x/y/z and radius distributions.
282  std::uniform_real_distribution<double> unif_x(lower_(0), upper_(0));
283  std::uniform_real_distribution<double> unif_y(lower_(1), upper_(1));
284  std::uniform_real_distribution<double> unif_z(lower_(2), upper_(2));
285  std::uniform_real_distribution<double> unif_r(min_radius, max_radius);
286 
287  // Create obstacles.
288  for (size_t ii = 0; ii < num; ii++) {
289  centers_.push_back(Vector3d(unif_x(rng), unif_y(rng), unif_z(rng)));
290  radii_.push_back(unif_r(rng));
291  }
292 }
293 
294 } //\namespace environment
295 } //\namespace fastrack
bool LoadParameters(const ros::NodeHandle &n)
std::vector< Vector3d > centers_
Definition: balls_in_box.h:97
static constexpr double kEpsilon
Definition: types.h:70
fastrack_msgs::SensedSpheres SimulateSensor(const SphereSensorParams &params) const
void GenerateObstacles(size_t num, double min_radius, double max_radius, unsigned int seed=0)
Definition: box.h:53
std::vector< double > radii_
Definition: balls_in_box.h:98
bool IsValid(const Vector3d &position, const TrackingBound &bound, double time=std::numeric_limits< double >::quiet_NaN()) const
void SensorCallback(const fastrack_msgs::SensedSpheres::ConstPtr &msg)


fastrack
Author(s): David Fridovich-Keil
autogenerated on Mon Aug 3 2020 21:28:37