tracker.cpp

00001
00002 /***************************************************************************
00003  *  camera_tracker.cpp - Implementation of the camera tracker
00004  *
00005  *  Generated: Thu Jul 14 22:18:14 2005
00006  *  Copyright  2005  Tim Niemueller [www.niemueller.de]
00007  *
00008  ****************************************************************************/
00009
00010 /*  This program is free software; you can redistribute it and/or modify
00011  *  it under the terms of the GNU General Public License as published by
00012  *  the Free Software Foundation; either version 2 of the License, or
00013  *  (at your option) any later version. A runtime exception applies to
00014  *  this software (see LICENSE.GPL_WRE file mentioned below for details).
00015  *
00016  *  This program is distributed in the hope that it will be useful,
00017  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  *  GNU Library General Public License for more details.
00020  *
00021  *  Read the full text in the LICENSE.GPL_WRE file in the doc directory.
00022  */
00023
00024 #include <core/exception.h>
00025
00026 #include <fvutils/camera/tracker.h>
00027 #include <utils/system/console_colors.h>
00028 #include <utils/math/angle.h>
00029
00030 #include <models/relative_position/relativepositionmodel.h>
00031
00032 #include <cmath>
00033 
00034 /** @class CameraTracker tracker.h <fvutils/camera/tracker.h>
00035  * Camera Tracker.
00036  * Utility class that allows for tracking and object or a world point
00037  * by using a camera pan/tilt unit. It is NOT meant to track an object
00038  * in a scene!
00039  *
00040  * The camera tracker will try to keep the desired object or point in the middle
00041  * of the image. Given a relative position model or a world point and robot pose
00042  * information and initial information the camera tracker returns pan/tilt angles
00043  * that are required to have the object in the center of the image. The using
00044  * application can then fulfill this desired angles if this lies within the
00045  * physical constraints of the pan/tilt unit.
00046  *
00047  * @author Tim Niemueller
00048  */
00049 
00050 /** Model mode, track by a relative world model. */
00051 const unsigned int CameraTracker::MODE_MODEL = 0;
00052 /** World point mode, track a world point */
00053 const unsigned int CameraTracker::MODE_WORLD = 1;
00054
00055 
00056 /** Constructor.
00057  * @param relative_position_model Relative position model to use if in model tracking
00058  * mode.
00059  * @param camera_height height above ground of the camera, objects are assumed to lie
00060  * on the ground plane.
00061  * @param camera_ori_deg The angle between the forward position and the actual position
00062  * of the camera on the robot in degrees, clock-wise positive.
00063  */
00064 CameraTracker::CameraTracker(RelativePositionModel *relative_position_model,
00065                              float camera_height,
00066                              float camera_ori_deg
00067                              )
00068 {
00069   rpm = relative_position_model;
00070   mode = MODE_MODEL;
00071   this->camera_height = camera_height;
00072   this->camera_orientation = fawkes::deg2rad( camera_ori_deg );
00073 }
00074
00075 
00076 /** Destructor. */
00077 CameraTracker::~CameraTracker()
00078 {
00079 }
00080
00081 
00082 /** Calculate values.
00083  * Based on the set data like robot position, world point and relative position model
00084  * this calculates the new desired values for pan and tilt.
00085  */
00086 void
00087 CameraTracker::calc()
00088 {
00089   if (mode == MODE_MODEL) {
00090     new_pan  = rpm->get_bearing() - camera_orientation;
00091     new_tilt = rpm->get_slope();
00092   } else if (mode == MODE_WORLD) {
00093
00094     float w_r_x = world_x - robot_x;
00095     float w_r_y = world_y - robot_y;
00096
00097     float distance = sqrt( w_r_x * w_r_x + w_r_y * w_r_y );
00098
00099     //cout << msg_prefix << "  world_x=" << world_x << "  world_y=" << world_y
00100     //     << "  robot_x=" << robot_x << "  robot_y=" << robot_y << endl;
00101     //cout << msg_prefix << "  w_r_x=" << w_r_x << "  w_r_y=" << w_r_y
00102     //     << "  dist=" << distance << endl;
00103
00104     /* atan2f magic
00105      * tan alpha = opposite leg / adjacent leg
00106      * => alpha = atan( opposite leg / adjacent leg )
00107      *
00108      * atan2f now takes y = length(opposite leg) and x = length(adjacent leg)
00109      * and calculates the angle alpha. It's exactle the same as the above
00110      *
00111      * So here we want to calculate the bearing to the world point
00112      * So we have a right triangle, where w_r_y is the length of the adjacent
00113      * leg and w_r_x is the length of the opposite leg. So to calculate the
00114      * bearing / new pan we call atan2f(w_r_x, w_r_y).
00115      * For the new tilt we need the distance. This gives us a right triangle
00116      * with distance being the opposite leg and the height of the camera on
00117      * the robot being the adjacent leg. So slope / new tilt is
00118      * atan2f(distance, camera_height).
00119      */
00120
00121     // Calculate bearing to point
00122     new_pan  = atan2f( w_r_y, w_r_x );
00123     new_pan = fawkes::normalize_mirror_rad( new_pan - robot_ori - camera_orientation);
00124     new_tilt = atan2f( camera_height, distance );
00125   }
00126 }
00127
00128 
00129 /** Get the new pan value.
00130  * @return new optimal pan value
00131  */
00132 float
00133 CameraTracker::get_new_pan()
00134 {
00135   return new_pan;
00136 }
00137
00138 
00139 /** Get the new tilt value.
00140  * @return new optimal tilt value
00141  */
00142 float
00143 CameraTracker::get_new_tilt()
00144 {
00145   return new_tilt;
00146 }
00147
00148 
00149 /** Set tracking mode.
00150  * @param mode new tracking mode
00151  * @exception Exception thrown, if mode is neither MODE_WORLD nor MODE_MODEL
00152  */
00153 void
00154 CameraTracker::set_mode(unsigned int mode)
00155 {
00156   if ( (mode == MODE_WORLD) || (mode == MODE_MODEL)) {
00157     this->mode = mode;
00158   } else {
00159     throw fawkes::Exception("CameraTracker: Invalid mode, not setting mode");
00160   }
00161 }
00162
00163 
00164 /** Set relative position model.
00165  * Switch the relative position model.
00166  * @param rpm new relative position model
00167  */
00168 void
00169 CameraTracker::set_relative_position_model(RelativePositionModel *rpm)
00170 {
00171   this->rpm = rpm;
00172 }
00173
00174 
00175 /** Set robot position.
00176  * Set the current robot position.
00177  * @param x new x coordinate in robot system
00178  * @param y new y coordinate in robot system
00179  * @param ori new orientation
00180  */
00181 void
00182 CameraTracker::set_robot_position(float x, float y, float ori)
00183 {
00184   robot_x   = x;
00185   robot_y   = y;
00186   robot_ori = ori;
00187 }
00188
00189 
00190 /** Set world point.
00191  * World point to track for the robot. The world point is given in a robot-relative
00192  * coordinate system on the ground plane. X-axis is pointing forward, Y-axis to
00193  * the right (right-handed coordinate system).
00194  * @param x x coordinate to track
00195  * @param y y coordinate to track
00196  */
00197 void
00198 CameraTracker::set_world_point(float x, float y)
00199 {
00200   world_x = x;
00201   world_y = y;
00202 }
00203