Libbarrett  1.2.4
include/barrett/systems/haptic_box.h
00001 /*
00002         Copyright 2009, 2010 Barrett Technology <support@barrett.com>
00003 
00004         This file is part of libbarrett.
00005 
00006         This version of libbarrett is free software: you can redistribute it
00007         and/or modify it under the terms of the GNU General Public License as
00008         published by the Free Software Foundation, either version 3 of the
00009         License, or (at your option) any later version.
00010 
00011         This version of libbarrett is distributed in the hope that it will be
00012         useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
00013         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014         GNU General Public License for more details.
00015 
00016         You should have received a copy of the GNU General Public License along
00017         with this version of libbarrett.  If not, see
00018         <http://www.gnu.org/licenses/>.
00019 
00020         Further, non-binding information about licensing is available at:
00021         <http://wiki.barrett.com/libbarrett/wiki/LicenseNotes>
00022 */
00023 
00024 /*
00025  * haptic_box.h
00026  *
00027  *  Created on: Apr 16, 2010
00028  *      Author: dc
00029  */
00030 
00031 #ifndef BARRETT_SYSTEMS_HAPTIC_BOX_H_
00032 #define BARRETT_SYSTEMS_HAPTIC_BOX_H_
00033 
00034 
00035 #include <cmath>
00036 
00037 #include <Eigen/Core>
00038 
00039 #include <barrett/detail/ca_macro.h>
00040 #include <barrett/units.h>
00041 #include <barrett/math.h>
00042 #include <barrett/systems/abstract/haptic_object.h>
00043 
00044 
00045 namespace barrett {
00046 namespace systems {
00047 
00048 
00049 class HapticBox : public HapticObject {
00050         BARRETT_UNITS_FIXED_SIZE_TYPEDEFS;
00051 
00052 public:
00053         HapticBox(const cp_type& center, const math::Vector<3>::type& size,
00054                         const std::string& sysName = "HapticBox") :
00055                 HapticObject(sysName),
00056                 c(center), halfSize(0.0), inBox(false), index(-1), keepOutside(true),
00057                 depth(0.0), dir(0.0)
00058         {
00059                 setSize(size);
00060         }
00061         virtual ~HapticBox() { mandatoryCleanUp(); }
00062 
00063         void setCenter(const cp_type& newCenter) {
00064                 BARRETT_SCOPED_LOCK(getEmMutex());
00065                 c = newCenter;
00066         }
00067         void setSize(const math::Vector<3>::type& newSize) {
00068                 BARRETT_SCOPED_LOCK(getEmMutex());
00069                 halfSize = newSize / 2.0;
00070         }
00071 
00072         const cp_type& getCenter() const { return c; }
00073         math::Vector<3>::type getSize() const { return halfSize * 2.0; }
00074 
00075 protected:
00076         virtual void operate() {
00077                 pos = input.getValue() - c;
00078 
00079                 bool outside = (pos.cwise().abs().cwise() > halfSize).any();
00080 
00081                 // if we are inside the box and we shouldn't be
00082                 if (keepOutside  &&  !outside) {
00083                         if ( !inBox ) {  // if we weren't in the box last time
00084                                 // find out what side we entered on
00085                                 (halfSize - pos.cwise().abs()).minCoeff(&index);
00086                         }
00087 
00088                         depth = halfSize[index] - math::abs(pos[index]);
00089                         if (depth > 0.02) {
00090                                 keepOutside = !keepOutside;
00091 
00092                                 depth = 0.0;
00093                                 dir.setZero();
00094                         } else {
00095                                 dir = math::sign(pos[index]) * cf_type::Unit(index);
00096 
00097                                 inBox = true;
00098                         }
00099                 } else {
00100                         inBox = false;
00101 
00102                         // if we are outside the box and we shouldn't be
00103                         if (!keepOutside  &&  outside) {
00104                                 dir = halfSize - pos.cwise().abs();
00105                                 dir = dir.cwise() * (dir.cwise() < 0.0).cast<double>();
00106                                 dir = dir.cwise() * math::sign(pos);
00107 
00108                                 depth = dir.norm();
00109                                 if (depth > 0.02) {
00110                                         keepOutside = !keepOutside;
00111 
00112                                         depth = 0.0;
00113                                         dir.setZero();
00114                                 } else {
00115                                         dir /= depth;
00116                                 }
00117                         } else {
00118                                 depth = 0.0;
00119                                 dir.setZero();
00120                         }
00121                 }
00122 
00123                 depthOutputValue->setData(&depth);
00124                 directionOutputValue->setData(&dir);
00125         }
00126 
00127         cp_type c;
00128         math::Vector<3>::type halfSize;
00129 
00130         // state & temporaries
00131         cf_type pos;
00132         bool inBox;
00133         int index;
00134         bool keepOutside;
00135 
00136         double depth;
00137         cf_type dir;
00138 
00139 private:
00140         DISALLOW_COPY_AND_ASSIGN(HapticBox);
00141 
00142 public:
00143         EIGEN_MAKE_ALIGNED_OPERATOR_NEW
00144 };
00145 
00146 
00147 }
00148 }
00149 
00150 #endif /* BARRETT_SYSTEMS_HAPTIC_BOX_H_ */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Defines