proxemic_layer.cpp
Go to the documentation of this file.
1 // Copyright 2018 David V. Lu!!
3 #include <math.h>
4 #include <angles/angles.h>
6 #include <algorithm>
7 #include <list>
9 
10 using costmap_2d::NO_INFORMATION;
11 using costmap_2d::LETHAL_OBSTACLE;
12 using costmap_2d::FREE_SPACE;
13 
14 double gaussian(double x, double y, double x0, double y0, double A, double varx, double vary, double skew)
15 {
16  double dx = x - x0, dy = y - y0;
17  double h = sqrt(dx * dx + dy * dy);
18  double angle = atan2(dy, dx);
19  double mx = cos(angle - skew) * h;
20  double my = sin(angle - skew) * h;
21  double f1 = pow(mx, 2.0) / (2.0 * varx),
22  f2 = pow(my, 2.0) / (2.0 * vary);
23  return A * exp(-(f1 + f2));
24 }
25 
26 double get_radius(double cutoff, double A, double var)
27 {
28  return sqrt(-2 * var * log(cutoff / A));
29 }
30 
31 
33 {
35 {
37  ros::NodeHandle nh("~/" + name_), g_nh;
38  server_ = new dynamic_reconfigure::Server<ProxemicLayerConfig>(nh);
39  f_ = boost::bind(&ProxemicLayer::configure, this, _1, _2);
40  server_->setCallback(f_);
41 }
42 
43 void ProxemicLayer::updateBoundsFromPeople(double* min_x, double* min_y, double* max_x, double* max_y)
44 {
45  std::list<people_msgs::Person>::iterator p_it;
46 
47  for (p_it = transformed_people_.begin(); p_it != transformed_people_.end(); ++p_it)
48  {
49  people_msgs::Person person = *p_it;
50 
51  double mag = sqrt(pow(person.velocity.x, 2) + pow(person.velocity.y, 2));
52  double factor = 1.0 + mag * factor_;
53  double point = get_radius(cutoff_, amplitude_, covar_ * factor);
54 
55  *min_x = std::min(*min_x, person.position.x - point);
56  *min_y = std::min(*min_y, person.position.y - point);
57  *max_x = std::max(*max_x, person.position.x + point);
58  *max_y = std::max(*max_y, person.position.y + point);
59  }
60 }
61 
62 void ProxemicLayer::updateCosts(costmap_2d::Costmap2D& master_grid, int min_i, int min_j, int max_i, int max_j)
63 {
64  boost::recursive_mutex::scoped_lock lock(lock_);
65  if (!enabled_) return;
66 
67  if (people_list_.people.size() == 0)
68  return;
69  if (cutoff_ >= amplitude_)
70  return;
71 
72  std::list<people_msgs::Person>::iterator p_it;
74  double res = costmap->getResolution();
75 
76  for (p_it = transformed_people_.begin(); p_it != transformed_people_.end(); ++p_it)
77  {
78  people_msgs::Person person = *p_it;
79  double angle = atan2(person.velocity.y, person.velocity.x);
80  double mag = sqrt(pow(person.velocity.x, 2) + pow(person.velocity.y, 2));
81  double factor = 1.0 + mag * factor_;
82  double base = get_radius(cutoff_, amplitude_, covar_);
83  double point = get_radius(cutoff_, amplitude_, covar_ * factor);
84 
85  unsigned int width = std::max(1, static_cast<int>((base + point) / res)),
86  height = std::max(1, static_cast<int>((base + point) / res));
87 
88  double cx = person.position.x, cy = person.position.y;
89 
90  double ox, oy;
91  if (sin(angle) > 0)
92  oy = cy - base;
93  else
94  oy = cy + (point - base) * sin(angle) - base;
95 
96  if (cos(angle) >= 0)
97  ox = cx - base;
98  else
99  ox = cx + (point - base) * cos(angle) - base;
100 
101 
102  int dx, dy;
103  costmap->worldToMapNoBounds(ox, oy, dx, dy);
104 
105  int start_x = 0, start_y = 0, end_x = width, end_y = height;
106  if (dx < 0)
107  start_x = -dx;
108  else if (dx + width > costmap->getSizeInCellsX())
109  end_x = std::max(0, static_cast<int>(costmap->getSizeInCellsX()) - dx);
110 
111  if (static_cast<int>(start_x + dx) < min_i)
112  start_x = min_i - dx;
113  if (static_cast<int>(end_x + dx) > max_i)
114  end_x = max_i - dx;
115 
116  if (dy < 0)
117  start_y = -dy;
118  else if (dy + height > costmap->getSizeInCellsY())
119  end_y = std::max(0, static_cast<int>(costmap->getSizeInCellsY()) - dy);
120 
121  if (static_cast<int>(start_y + dy) < min_j)
122  start_y = min_j - dy;
123  if (static_cast<int>(end_y + dy) > max_j)
124  end_y = max_j - dy;
125 
126  double bx = ox + res / 2,
127  by = oy + res / 2;
128  for (int i = start_x; i < end_x; i++)
129  {
130  for (int j = start_y; j < end_y; j++)
131  {
132  unsigned char old_cost = costmap->getCost(i + dx, j + dy);
133  if (old_cost == costmap_2d::NO_INFORMATION)
134  continue;
135 
136  double x = bx + i * res, y = by + j * res;
137  double ma = atan2(y - cy, x - cx);
138  double diff = angles::shortest_angular_distance(angle, ma);
139  double a;
140  if (fabs(diff) < M_PI / 2)
141  a = gaussian(x, y, cx, cy, amplitude_, covar_ * factor, covar_, angle);
142  else
143  a = gaussian(x, y, cx, cy, amplitude_, covar_, covar_, 0);
144 
145  if (a < cutoff_)
146  continue;
147  unsigned char cvalue = (unsigned char) a;
148  costmap->setCost(i + dx, j + dy, std::max(cvalue, old_cost));
149  }
150  }
151  }
152 }
153 
154 void ProxemicLayer::configure(ProxemicLayerConfig &config, uint32_t level)
155 {
156  cutoff_ = config.cutoff;
157  amplitude_ = config.amplitude;
158  covar_ = config.covariance;
159  factor_ = config.factor;
160  people_keep_time_ = ros::Duration(config.keep_time);
161  enabled_ = config.enabled;
162 }
163 }; // namespace social_navigation_layers
void setCost(unsigned int mx, unsigned int my, unsigned char cost)
LayeredCostmap * layered_costmap_
std::list< people_msgs::Person > transformed_people_
Definition: social_layer.h:37
double get_radius(double cutoff, double A, double var)
INLINE Rall1d< T, V, S > log(const Rall1d< T, V, S > &arg)
virtual void updateCosts(costmap_2d::Costmap2D &master_grid, int min_i, int min_j, int max_i, int max_j)
PLUGINLIB_EXPORT_CLASS(BAGReader, nodelet::Nodelet)
IMETHOD Vector diff(const Vector &p_w_a, const Vector &p_w_b, double dt=1)
TFSIMD_FORCE_INLINE const tfScalar & y() const
virtual void updateBoundsFromPeople(double *min_x, double *min_y, double *max_x, double *max_y)
std::string name_
TFSIMD_FORCE_INLINE tfScalar angle(const Quaternion &q1, const Quaternion &q2)
unsigned char getCost(unsigned int mx, unsigned int my) const
void configure(ProxemicLayerConfig &config, uint32_t level)
dynamic_reconfigure::Server< ProxemicLayerConfig >::CallbackType f_
double gaussian(double x, double y, double x0, double y0, double A, double varx, double vary, double skew)
TFSIMD_FORCE_INLINE const tfScalar & x() const
INLINE Rall1d< T, V, S > sqrt(const Rall1d< T, V, S > &arg)
unsigned int getSizeInCellsY() const
INLINE Rall1d< T, V, S > exp(const Rall1d< T, V, S > &arg)
void worldToMapNoBounds(double wx, double wy, int &mx, int &my) const
INLINE Rall1d< T, V, S > pow(const Rall1d< T, V, S > &arg, double m)
unsigned int getSizeInCellsX() const
static const unsigned char NO_INFORMATION
INLINE Rall1d< T, V, S > atan2(const Rall1d< T, V, S > &y, const Rall1d< T, V, S > &x)
INLINE Rall1d< T, V, S > cos(const Rall1d< T, V, S > &arg)
double getResolution() const
INLINE Rall1d< T, V, S > sin(const Rall1d< T, V, S > &arg)
def shortest_angular_distance(from_angle, to_angle)
dynamic_reconfigure::Server< ProxemicLayerConfig > * server_


social_navigation_layers
Author(s): David V. Lu!!
autogenerated on Thu Mar 4 2021 04:02:57