30 #include <Ice/Current.h>
34 #include <opencv2/core.hpp>
40 #include <opencv2/core/core_c.h>
44 #include <RobotAPI/interface/core/PoseBase.h>
47 using namespace Eigen;
54 ManagedObstacle::calculateObstacleArea(
const obstacledetection::Obstacle& o)
60 ManagedObstacle::point_ellipsis_coverage(
const Eigen::Vector2f e_origin,
64 const Eigen::Vector2f point)
67 const float sin = std::sin(e_yaw);
68 const float cos = std::cos(e_yaw);
70 const float a = cos * (point(0) - e_origin(0)) + sin * (point(1) - e_origin(1));
71 const float b = sin * (point(0) - e_origin(0)) - cos * (point(1) - e_origin(1));
73 const float e_rx_sq = e_rx * e_rx;
74 const float e_ry_sq = e_ry * e_ry;
76 return a *
a * e_ry_sq + b * b * e_rx_sq <= e_rx_sq * e_ry_sq;
80 ManagedObstacle::ellipsis_ellipsis_coverage(
const Eigen::Vector2f e1_origin,
84 const Eigen::Vector2f e2_origin,
92 unsigned int SAMPLES = 100;
94 for (
unsigned int i = 0; i < SAMPLES; ++i)
96 float theta =
static_cast<float>(rand()) /
static_cast<float>(RAND_MAX / 2 *
M_PI);
97 float k =
sqrt(
static_cast<float>(rand()) /
static_cast<float>(RAND_MAX));
98 Eigen::Vector2f sample(k * e2_rx * cos(theta), k * e2_ry * sin(theta));
102 if (ManagedObstacle::point_ellipsis_coverage(e1_origin, e1_rx, e1_ry, e1_yaw, sample))
108 return (1.0f *
matches) / SAMPLES;
112 ManagedObstacle::line_segment_ellipsis_coverage(
const Eigen::Vector2f e_origin,
116 const Eigen::Vector2f line_seg_start,
117 const Eigen::Vector2f line_seg_end)
120 const Eigen::Vector2f difference_vec = line_seg_end - line_seg_start;
121 const Eigen::Vector2f difference_vec_normed = difference_vec.normalized();
122 const float distance = difference_vec.norm();
125 const Vector2f difference_start_origin = e_origin - line_seg_start;
126 const Vector2f difference_end_origin = e_origin - line_seg_end;
128 if (difference_start_origin.norm() >
std::max(e_rx, e_ry) &&
140 const float step_size =
distance / SAMPLES;
141 const Eigen::Vector2f dir = difference_vec_normed * step_size;
143 unsigned int samples_in_ellipsis = 0;
146 for (
unsigned int i = 0; i < SAMPLES * 0.5; ++i)
148 Eigen::Vector2f start_sample = line_seg_start + i * dir;
149 Eigen::Vector2f end_sample = line_seg_end - i * dir;
150 unsigned int samples_in_ellipsis_this_iteration = 0;
152 for (
const auto& point : {start_sample, end_sample})
154 if (ManagedObstacle::point_ellipsis_coverage(e_origin, e_rx, e_ry, e_yaw, point))
156 ++samples_in_ellipsis;
157 ++samples_in_ellipsis_this_iteration;
161 if (samples_in_ellipsis_this_iteration == 2)
166 const unsigned int remaining_samples = SAMPLES - 2 * (i + 1);
167 return (1.0f * samples_in_ellipsis + remaining_samples) / SAMPLES;
170 return (1.0f * samples_in_ellipsis) / SAMPLES;
174 ManagedObstacle::update_position(
const unsigned int thickness)
176 if (line_matches.size() < 2)
181 ARMARX_DEBUG <<
"Obstacle " << m_obstacle.name <<
" has " << line_matches.size()
182 <<
" matching line segments since last update";
184 std::vector<float> x_pos;
185 std::vector<float> y_pos;
186 for (Eigen::Vector2f& match : line_matches)
189 x_pos.push_back(match(0));
190 y_pos.push_back(match(1));
193 cv::Mat x(x_pos.size(), 1, CV_32F, x_pos.data());
194 cv::Mat y(y_pos.size(), 1, CV_32F, y_pos.data());
199 cv::Mat
data(x_pos.size(), 2, CV_32F);
200 x.col(0).copyTo(
data.col(0));
201 y.col(0).copyTo(
data.col(1));
205 cv::PCA pca(
data, cv::Mat(), CV_PCA_DATA_AS_ROW, 2);
207 cv::Mat
mean = pca.mean;
209 cv::Mat eigenvalues = pca.eigenvalues;
211 cv::Mat eigenvectors = pca.eigenvectors;
214 Eigen::Vector2f pca_center(
mean.at<
float>(0, 0),
mean.at<
float>(0, 1));
215 Eigen::Vector2f pca1_direction(eigenvectors.at<
float>(0, 0), eigenvectors.at<
float>(0, 1));
216 Eigen::Vector2f pca2_direction(eigenvectors.at<
float>(1, 0), eigenvectors.at<
float>(1, 1));
217 double pca1_eigenvalue = eigenvalues.at<
float>(0, 0);
218 double pca2_eigenvalue = eigenvalues.at<
float>(1, 0);
222 <<
", Eigenvalue: " << pca1_eigenvalue;
224 <<
", Eigenvalue: " << pca2_eigenvalue;
227 const Eigen::Vector2f difference_vec = pca1_direction;
228 const Eigen::Vector2f center_vec = pca_center;
231 const float yaw1 = getXAxisAngle(difference_vec);
232 const float yaw2 = getXAxisAngle(-1 * difference_vec);
234 const float diff_origin_yaw1 =
std::abs(yaw1 - m_obstacle.yaw);
235 const float diff_origin_yaw2 =
std::abs(yaw2 - m_obstacle.yaw);
236 const float diff_origin_yaw1_opposite =
std::abs(2 *
M_PI - diff_origin_yaw1);
237 const float diff_origin_yaw2_opposite =
std::abs(2 *
M_PI - diff_origin_yaw2);
241 if ((diff_origin_yaw1 < diff_origin_yaw2 && diff_origin_yaw1 < diff_origin_yaw2_opposite) ||
242 (diff_origin_yaw1_opposite < diff_origin_yaw2 &&
243 diff_origin_yaw1_opposite < diff_origin_yaw2_opposite))
259 position_buffer.at(position_buffer_index++) =
260 std::make_tuple(center_vec(0),
263 sqrt(pca1_eigenvalue) * 1.3,
265 static_cast<float>(
sqrt(pca2_eigenvalue)) *
267 position_buffer_index %= position_buffer.size();
269 position_buffer_fillctr++;
270 position_buffer_fillctr =
271 std::min(position_buffer_fillctr,
static_cast<unsigned int>(position_buffer.size()));
274 double sum_x_pos = 0;
275 double sum_y_pos = 0;
277 double sum_sin_yaw = 0;
278 double sum_cos_yaw = 0;
279 double sum_axisX = 0;
280 double sum_axisY = 0;
283 for (
unsigned int i = 0; i < position_buffer_fillctr; ++i)
285 double current_x_pos = std::get<0>(position_buffer[i]);
286 double current_y_pos = std::get<1>(position_buffer[i]);
287 double current_yaw = std::get<2>(position_buffer[i]);
288 double current_axisX = std::get<3>(position_buffer[i]);
289 double current_axisY = std::get<4>(position_buffer[i]);
290 sum_x_pos += current_x_pos;
291 sum_y_pos += current_y_pos;
292 sum_yaw += current_yaw;
293 sum_sin_yaw += sin(current_yaw);
294 sum_cos_yaw += cos(current_yaw);
295 sum_axisX += current_axisX;
296 sum_axisY += current_axisY;
301 double mean_x_pos = sum_x_pos / position_buffer_fillctr;
302 double mean_y_pos = sum_y_pos / position_buffer_fillctr;
303 double mean_yaw = atan2(
304 (1.0 / position_buffer_fillctr) * sum_sin_yaw,
305 (1.0 / position_buffer_fillctr) *
307 double mean_axisX = sum_axisX / position_buffer_fillctr;
308 double mean_axisY = sum_axisY / position_buffer_fillctr;
309 mean_yaw = normalizeYaw(mean_yaw);
312 m_obstacle.posX = mean_x_pos;
313 m_obstacle.posY = mean_y_pos;
314 m_obstacle.refPosX = mean_x_pos;
315 m_obstacle.refPosY = mean_y_pos;
316 m_obstacle.yaw = mean_yaw;
319 m_obstacle.axisLengthX = mean_axisX;
323 m_obstacle.axisLengthY = mean_axisY;
326 line_matches.clear();
331 ManagedObstacle::normalizeYaw(
float yaw)
const
333 float pi2 = 2.0 *
M_PI;
347 const Eigen::Vector2f& v2)
const
350 const Eigen::Vector2f v1_vec_normed = v1.normalized();
351 const Eigen::Vector2f v2_vec_normed = v2.normalized();
352 const float dot_product_vec =
353 v1_vec_normed(0) * v2_vec_normed(0) + v1_vec_normed(1) * v2_vec_normed(1);
354 float yaw = acos(dot_product_vec);
359 ManagedObstacle::getXAxisAngle(
const Eigen::Vector2f&
v)
const
362 const Eigen::Vector2f v_vec_normed =
v.normalized();
363 const float dot_product_vec = v_vec_normed(0);
364 const float cross_product_vec = v_vec_normed(1);
365 float yaw = acos(dot_product_vec);
366 if (cross_product_vec < 0)
368 yaw = 2 *
M_PI - yaw;