TargetPicking:
- Added selection of targets based on width and similarity in skew.
- Code Review fixes.
Change-Id: Ib5e319d58ef542da4ae74bb218eb44fd7023bdbe
diff --git a/y2016/vision/target_receiver.cc b/y2016/vision/target_receiver.cc
index b3c56ae..3f3c321 100644
--- a/y2016/vision/target_receiver.cc
+++ b/y2016/vision/target_receiver.cc
@@ -19,6 +19,89 @@
namespace y2016 {
namespace vision {
+::aos::vision::Vector<2> CreateCenterFromTarget(double lx, double ly, double rx, double ry) {
+ return ::aos::vision::Vector<2>((lx + rx) / 2.0, (ly + ry) / 2.0);
+}
+
+double TargetWidth(double lx, double ly, double rx, double ry) {
+ double dx = lx - rx;
+ double dy = ly - ry;
+ return ::std::sqrt(dx * dx + dy * dy);
+}
+
+void SelectTargets(const VisionData &left_target,
+ const VisionData &right_target,
+ ::aos::vision::Vector<2> *center_left,
+ ::aos::vision::Vector<2> *center_right) {
+ // No good targets. Let the caller decide defaults.
+ if (right_target.target_size() == 0 || left_target.target_size() == 0) {
+ return;
+ }
+
+ // Only one option, we have to go with it.
+ if (right_target.target_size() == 1 && left_target.target_size() == 1) {
+ *center_left =
+ CreateCenterFromTarget(left_target.target(0).left_corner_x(),
+ left_target.target(0).left_corner_y(),
+ left_target.target(0).right_corner_x(),
+ left_target.target(0).right_corner_y());
+ *center_right =
+ CreateCenterFromTarget(right_target.target(0).left_corner_x(),
+ right_target.target(0).left_corner_y(),
+ right_target.target(0).right_corner_x(),
+ right_target.target(0).right_corner_y());
+ return;
+ }
+
+ // Now we have to make a decision.
+ double max_wid = -1.0;
+ int left_index = 0;
+ // First pick the widest target from the left.
+ for (int i = 0; i < left_target.target_size(); i++) {
+ double wid1 = TargetWidth(left_target.target(i).left_corner_x(),
+ left_target.target(i).left_corner_y(),
+ left_target.target(i).right_corner_x(),
+ left_target.target(i).right_corner_y());
+ if (max_wid == -1.0 || wid1 > max_wid) {
+ max_wid = wid1;
+ left_index = i;
+ }
+ }
+ // Calculate the angle of the bottom edge for the left.
+ double h = left_target.target(left_index).left_corner_y() -
+ left_target.target(left_index).right_corner_y();
+ double good_ang = h / max_wid;
+ double min_ang_err = -1.0;
+ int right_index = -1;
+ // Now pick the bottom edge angle from the right that lines up best with the left.
+ for (int j = 0; j < right_target.target_size(); j++) {
+ double wid2 = TargetWidth(right_target.target(j).left_corner_x(),
+ right_target.target(j).left_corner_y(),
+ right_target.target(j).right_corner_x(),
+ right_target.target(j).right_corner_y());
+ h = right_target.target(j).left_corner_y() -
+ right_target.target(j).right_corner_y();
+ double ang = h/ wid2;
+ double ang_err = ::std::abs(good_ang - ang);
+ if (min_ang_err == -1.0 || min_ang_err > ang_err) {
+ min_ang_err = ang_err;
+ right_index = j;
+ }
+ }
+
+ *center_left =
+ CreateCenterFromTarget(left_target.target(left_index).left_corner_x(),
+ left_target.target(left_index).left_corner_y(),
+ left_target.target(left_index).right_corner_x(),
+ left_target.target(left_index).right_corner_y());
+ *center_right =
+ CreateCenterFromTarget(right_target.target(right_index).left_corner_x(),
+ right_target.target(right_index).left_corner_y(),
+ right_target.target(right_index).right_corner_x(),
+ right_target.target(right_index).right_corner_y());
+}
+
+
void Main() {
StereoGeometry stereo(constants::GetValues().vision_name);
LOG(INFO, "calibration: %s\n",
@@ -71,21 +154,9 @@
new_vision_status->left_image_valid = left_image_valid;
new_vision_status->right_image_valid = right_image_valid;
if (left_image_valid && right_image_valid) {
- const ::aos::vision::Vector<2> center0(
- (left_target.target(0).left_corner_x() +
- left_target.target(0).right_corner_x()) /
- 2.0,
- (left_target.target(0).left_corner_y() +
- left_target.target(0).right_corner_y()) /
- 2.0);
- // out of sync.
- const ::aos::vision::Vector<2> center1(
- (right_target.target(0).left_corner_x() +
- right_target.target(0).right_corner_x()) /
- 2.0,
- (right_target.target(0).left_corner_y() +
- right_target.target(0).right_corner_y()) /
- 2.0);
+ ::aos::vision::Vector<2> center0(0.0, 0.0);
+ ::aos::vision::Vector<2> center1(0.0, 0.0);
+ SelectTargets(left_target, right_target, ¢er0, ¢er1);
double distance, horizontal_angle, vertical_angle;
stereo.Process(center0, center1, &distance, &horizontal_angle,
&vertical_angle);