30 #include <Ice/Current.h>
34 #include <opencv2/core.hpp>
40 #include <RobotAPI/interface/core/PoseBase.h>
45 #include <opencv2/core/core_c.h>
47 using namespace Eigen;
53 double ManagedObstacle::calculateObstacleArea(
const obstacledetection::Obstacle& o)
58 bool ManagedObstacle::point_ellipsis_coverage(
const Eigen::Vector2f e_origin,
const float e_rx,
const float e_ry,
const float e_yaw,
const Eigen::Vector2f point)
61 const float sin = std::sin(e_yaw);
62 const float cos = std::cos(e_yaw);
64 const float a = cos * (point(0) - e_origin(0)) + sin * (point(1) - e_origin(1));
65 const float b = sin * (point(0) - e_origin(0)) - cos * (point(1) - e_origin(1));
67 const float e_rx_sq = e_rx * e_rx;
68 const float e_ry_sq = e_ry * e_ry;
70 return a *
a * e_ry_sq + b * b * e_rx_sq <= e_rx_sq * e_ry_sq;
73 float ManagedObstacle::ellipsis_ellipsis_coverage(
const Eigen::Vector2f e1_origin,
const float e1_rx,
const float e1_ry,
const float e1_yaw,
const Eigen::Vector2f e2_origin,
const float e2_rx,
const float e2_ry,
const float e2_yaw)
78 unsigned int SAMPLES = 100;
80 for (
unsigned int i = 0; i < SAMPLES; ++i)
82 float theta =
static_cast<float>(rand()) /
static_cast<float>(RAND_MAX / 2 *
M_PI);
83 float k =
sqrt(
static_cast<float>(rand()) /
static_cast<float>(RAND_MAX));
84 Eigen::Vector2f sample(k * e2_rx * cos(theta), k * e2_ry * sin(theta));
88 if (ManagedObstacle::point_ellipsis_coverage(e1_origin, e1_rx, e1_ry, e1_yaw, sample))
94 return (1.0f *
matches) / SAMPLES;
97 float ManagedObstacle::line_segment_ellipsis_coverage(
const Eigen::Vector2f e_origin,
const float e_rx,
const float e_ry,
const float e_yaw,
const Eigen::Vector2f line_seg_start,
const Eigen::Vector2f line_seg_end)
100 const Eigen::Vector2f difference_vec = line_seg_end - line_seg_start;
101 const Eigen::Vector2f difference_vec_normed = difference_vec.normalized();
102 const float distance = difference_vec.norm();
105 const Vector2f difference_start_origin = e_origin - line_seg_start;
106 const Vector2f difference_end_origin = e_origin - line_seg_end;
119 const float step_size =
distance / SAMPLES;
120 const Eigen::Vector2f dir = difference_vec_normed * step_size;
122 unsigned int samples_in_ellipsis = 0;
125 for (
unsigned int i = 0; i < SAMPLES * 0.5; ++i)
127 Eigen::Vector2f start_sample = line_seg_start + i * dir;
128 Eigen::Vector2f end_sample = line_seg_end - i * dir;
129 unsigned int samples_in_ellipsis_this_iteration = 0;
131 for (
const auto& point :
133 start_sample, end_sample
136 if (ManagedObstacle::point_ellipsis_coverage(e_origin, e_rx, e_ry, e_yaw, point))
138 ++samples_in_ellipsis;
139 ++samples_in_ellipsis_this_iteration;
143 if (samples_in_ellipsis_this_iteration == 2)
148 const unsigned int remaining_samples = SAMPLES - 2 * (i + 1);
149 return (1.0f * samples_in_ellipsis + remaining_samples) / SAMPLES;
152 return (1.0f * samples_in_ellipsis) / SAMPLES;
155 void ManagedObstacle::update_position(
const unsigned int thickness)
157 if (line_matches.size() < 2)
162 ARMARX_DEBUG <<
"Obstacle " << m_obstacle.name <<
" has " << line_matches.size() <<
" matching line segments since last update";
164 std::vector<float> x_pos;
165 std::vector<float> y_pos;
166 for (Eigen::Vector2f& match : line_matches)
169 x_pos.push_back(match(0));
170 y_pos.push_back(match(1));
173 cv::Mat x(x_pos.size(), 1, CV_32F, x_pos.data());
174 cv::Mat y(y_pos.size(), 1, CV_32F, y_pos.data());
179 cv::Mat
data(x_pos.size(), 2, CV_32F);
180 x.col(0).copyTo(
data.col(0));
181 y.col(0).copyTo(
data.col(1));
185 cv::PCA pca(
data, cv::Mat(), CV_PCA_DATA_AS_ROW, 2);
187 cv::Mat
mean = pca.mean;
189 cv::Mat eigenvalues = pca.eigenvalues;
191 cv::Mat eigenvectors = pca.eigenvectors;
194 Eigen::Vector2f pca_center(
mean.at<
float>(0, 0),
mean.at<
float>(0, 1));
195 Eigen::Vector2f pca1_direction(eigenvectors.at<
float>(0, 0), eigenvectors.at<
float>(0, 1));
196 Eigen::Vector2f pca2_direction(eigenvectors.at<
float>(1, 0), eigenvectors.at<
float>(1, 1));
197 double pca1_eigenvalue = eigenvalues.at<
float>(0, 0);
198 double pca2_eigenvalue = eigenvalues.at<
float>(1, 0);
201 ARMARX_DEBUG <<
"PCA1: Eigenvector: " << pca1_direction <<
", Eigenvalue: " << pca1_eigenvalue;
202 ARMARX_DEBUG <<
"PCA2: Eigenvector: " << pca2_direction <<
", Eigenvalue: " << pca2_eigenvalue;
205 const Eigen::Vector2f difference_vec = pca1_direction;
206 const Eigen::Vector2f center_vec = pca_center;
209 const float yaw1 = getXAxisAngle(difference_vec);
210 const float yaw2 = getXAxisAngle(-1 * difference_vec);
212 const float diff_origin_yaw1 =
std::abs(yaw1 - m_obstacle.yaw);
213 const float diff_origin_yaw2 =
std::abs(yaw2 - m_obstacle.yaw);
214 const float diff_origin_yaw1_opposite =
std::abs(2 *
M_PI - diff_origin_yaw1);
215 const float diff_origin_yaw2_opposite =
std::abs(2 *
M_PI - diff_origin_yaw2);
219 if ((diff_origin_yaw1 < diff_origin_yaw2 && diff_origin_yaw1 < diff_origin_yaw2_opposite) || (diff_origin_yaw1_opposite < diff_origin_yaw2 && diff_origin_yaw1_opposite < diff_origin_yaw2_opposite))
235 position_buffer.at(position_buffer_index++) = std::make_tuple(center_vec(0), center_vec(1), yaw,
sqrt(pca1_eigenvalue) * 1.3,
std::max(1.0f * thickness,
static_cast<float>(
sqrt(pca2_eigenvalue)) * 1.3f));
236 position_buffer_index %= position_buffer.size();
238 position_buffer_fillctr++;
239 position_buffer_fillctr =
std::min(position_buffer_fillctr,
static_cast<unsigned int>(position_buffer.size()));
242 double sum_x_pos = 0;
243 double sum_y_pos = 0;
245 double sum_sin_yaw = 0;
246 double sum_cos_yaw = 0;
247 double sum_axisX = 0;
248 double sum_axisY = 0;
251 for (
unsigned int i = 0; i < position_buffer_fillctr; ++i)
253 double current_x_pos = std::get<0>(position_buffer[i]);
254 double current_y_pos = std::get<1>(position_buffer[i]);
255 double current_yaw = std::get<2>(position_buffer[i]);
256 double current_axisX = std::get<3>(position_buffer[i]);
257 double current_axisY = std::get<4>(position_buffer[i]);
258 sum_x_pos += current_x_pos;
259 sum_y_pos += current_y_pos;
260 sum_yaw += current_yaw;
261 sum_sin_yaw += sin(current_yaw);
262 sum_cos_yaw += cos(current_yaw);
263 sum_axisX += current_axisX;
264 sum_axisY += current_axisY;
269 double mean_x_pos = sum_x_pos / position_buffer_fillctr;
270 double mean_y_pos = sum_y_pos / position_buffer_fillctr;
271 double mean_yaw = atan2((1.0 / position_buffer_fillctr) * sum_sin_yaw, (1.0 / position_buffer_fillctr) * sum_cos_yaw);
272 double mean_axisX = sum_axisX / position_buffer_fillctr;
273 double mean_axisY = sum_axisY / position_buffer_fillctr;
274 mean_yaw = normalizeYaw(mean_yaw);
277 m_obstacle.posX = mean_x_pos;
278 m_obstacle.posY = mean_y_pos;
279 m_obstacle.refPosX = mean_x_pos;
280 m_obstacle.refPosY = mean_y_pos;
281 m_obstacle.yaw = mean_yaw;
284 m_obstacle.axisLengthX = mean_axisX;
288 m_obstacle.axisLengthY = mean_axisY;
291 line_matches.clear();
295 float ManagedObstacle::normalizeYaw(
float yaw)
const
297 float pi2 = 2.0 *
M_PI;
312 const Eigen::Vector2f v1_vec_normed = v1.normalized();
313 const Eigen::Vector2f v2_vec_normed = v2.normalized();
314 const float dot_product_vec = v1_vec_normed(0) * v2_vec_normed(0) + v1_vec_normed(1) * v2_vec_normed(1);
315 float yaw = acos(dot_product_vec);
319 float ManagedObstacle::getXAxisAngle(
const Eigen::Vector2f&
v)
const
322 const Eigen::Vector2f v_vec_normed =
v.normalized();
323 const float dot_product_vec = v_vec_normed(0);
324 const float cross_product_vec = v_vec_normed(1);
325 float yaw = acos(dot_product_vec);
326 if (cross_product_vec < 0)
328 yaw = 2 *
M_PI - yaw;