00001 /************************************************************************* 00002 * * 00003 * Open Physics Abstraction Layer * 00004 * Copyright (C) 2004-2005 * 00005 * Alan Fischer alan.fischer@gmail.com * 00006 * Andres Reinot andres@reinot.com * 00007 * Tyler Streeter tylerstreeter@gmail.com * 00008 * All rights reserved. * 00009 * Web: opal.sourceforge.net * 00010 * * 00011 * This library is free software; you can redistribute it and/or * 00012 * modify it under the terms of EITHER: * 00013 * (1) The GNU Lesser General Public License as published by the Free * 00014 * Software Foundation; either version 2.1 of the License, or (at * 00015 * your option) any later version. The text of the GNU Lesser * 00016 * General Public License is included with this library in the * 00017 * file license-LGPL.txt. * 00018 * (2) The BSD-style license that is included with this library in * 00019 * the file license-BSD.txt. * 00020 * * 00021 * This library is distributed in the hope that it will be useful, * 00022 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00023 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * 00024 * license-LGPL.txt and license-BSD.txt for more details. * 00025 * * 00026 *************************************************************************/ 00027 00028 #include "ServoMotor.h" 00029 00030 namespace opal 00031 { 00032 ServoMotor::ServoMotor() 00033 : Motor() 00034 { 00035 // "mData" will be initialized in its own constructor. 00036 } 00037 00038 ServoMotor::~ServoMotor() 00039 { 00040 // We must set the Joint's desired vel and max force to 0 since 00041 // this Motor won't apply to it anymore. This is only necessary 00042 // if this Motor is enabled. 00043 if ( mData.enabled && mData.joint ) 00044 { 00045 mData.joint->internal_setDesiredVel( mData.jointAxisNum, 0 ); 00046 mData.joint->internal_setMaxTorque( mData.jointAxisNum, 0 ); 00047 } 00048 } 00049 00050 void ServoMotor::init( const ServoMotorData& data ) 00051 { 00052 if ( mInitCalled ) 00053 { 00054 // If the Servo is already in operation, we first need to 00055 // set the old Joint's desired vel and max force to 0. The 00056 // following function call will automatically handle this 00057 // when set to false. 00058 setEnabled( false ); 00059 } 00060 00061 assert( data.joint ); 00062 assert( data.jointAxisNum >= 0 && 00063 data.jointAxisNum < data.joint->getNumAxes() ); 00064 Motor::init(); 00065 assert( data.joint->isRotational( data.jointAxisNum ) ); 00066 mData = data; 00067 setEnabled( mData.enabled ); 00068 } 00069 00070 const ServoMotorData& ServoMotor::getData() const 00071 { 00072 return mData; 00073 } 00074 00075 MotorType ServoMotor::getType() const 00076 { 00077 return mData.getType(); 00078 } 00079 00080 void ServoMotor::setName( const std::string& name ) 00081 { 00082 mData.name = name; 00083 } 00084 00085 const std::string& ServoMotor::getName() const 00086 { 00087 return mData.name; 00088 } 00089 00090 bool ServoMotor::isEnabled() const 00091 { 00092 return mData.enabled; 00093 } 00094 00095 void ServoMotor::setEnabled( bool e ) 00096 { 00097 //if (!mInitCalled) 00098 //{ 00099 // return; 00100 //} 00101 00102 mData.enabled = e; 00103 00104 if ( mData.joint ) 00105 { 00106 if ( e ) 00107 { 00108 mData.joint->internal_setDesiredVel( mData.jointAxisNum, 00109 mData.desiredVel ); 00110 mData.joint->internal_setMaxTorque( mData.jointAxisNum, 00111 mData.maxTorque ); 00112 } 00113 else 00114 { 00115 mData.joint->internal_setDesiredVel( mData.jointAxisNum, 0 ); 00116 mData.joint->internal_setMaxTorque( mData.jointAxisNum, 0 ); 00117 } 00118 } 00119 } 00120 00121 void ServoMotor::internal_update() 00122 { 00123 if ( mData.enabled && mData.joint ) 00124 { 00125 // Make sure both Solids are awake at this point. 00126 mData.joint->wakeSolids(); 00127 00128 if ( DESIRED_ANGLE_MODE == mData.mode ) 00129 { 00130 // No longer support linear degrees of freedom. 00131 //if (true == mData.joint->isRotational(mData.jointAxisNum)) 00132 //{ 00133 real velocity = mData.desiredAngle - 00134 mData.joint->getAngle( mData.jointAxisNum ); 00135 if ( velocity > 180.0 ) 00136 velocity = -360 + velocity; 00137 if ( velocity < -180.0 ) 00138 velocity = 360 + velocity; 00139 mData.joint->internal_setDesiredVel( mData.jointAxisNum, 00140 mData.restoreSpeed * velocity ); 00141 //} 00142 //else 00143 //{ 00144 // // This axis must be a linear degree of freedom. 00145 // real velocity = mData.desiredPos - 00146 // mData.joint->getState(mData.jointAxisNum); 00147 // mData.joint->internal_setDesiredVel(mData.jointAxisNum, 00148 // mData.restoreSpeed * velocity); 00149 //} 00150 } 00151 else 00152 { 00153 // Nothing to do for desired velocity mode; the Joint's 00154 // desired velocity should already handle this. 00155 } 00156 } 00157 } 00158 00159 void ServoMotor::setDesiredAngle( real a ) 00160 { 00161 // this clamping is needed since there are sometimes float point errors 00162 real low = mData.joint->getLowLimit( mData.jointAxisNum ); 00163 if ( a < low ) 00164 { 00165 a = low; 00166 } 00167 00168 real high = mData.joint->getHighLimit( mData.jointAxisNum ); 00169 if ( a > high ) 00170 { 00171 a = high; 00172 } 00173 00174 mData.desiredAngle = a; 00175 } 00176 00177 void ServoMotor::setDesiredAngleNorm( real a ) 00178 { 00179 if ( a < 0 ) 00180 a = 0; 00181 if ( a > 1 ) 00182 a = 1; 00183 00184 real lowLimit = mData.joint->getLowLimit( mData.jointAxisNum ); 00185 real highLimit = mData.joint->getHighLimit( mData.jointAxisNum ); 00186 00187 // map the pos value onto the joint limits 00188 mData.desiredAngle = a * ( highLimit - lowLimit ) + lowLimit; 00189 00190 // Keep desired angle slightly away from the limit to avoid jitter. 00191 // @todo: fix this; this should just keep the thing away from the 00192 // limit when it's close, not all the time. 00193 mData.desiredAngle *= ( real ) 0.99; 00194 } 00195 00196 real ServoMotor::getDesiredAngle() const 00197 { 00198 return mData.desiredAngle; 00199 } 00200 00201 void ServoMotor::setDesiredVel( real vel ) 00202 { 00203 mData.desiredVel = vel; 00204 mData.joint->internal_setDesiredVel( mData.jointAxisNum, vel ); 00205 } 00206 00207 real ServoMotor::getDesiredVel() const 00208 { 00209 return mData.desiredVel; 00210 } 00211 00212 void ServoMotor::setMaxTorque( real max ) 00213 { 00214 mData.maxTorque = max; 00215 mData.joint->internal_setMaxTorque( mData.jointAxisNum, max ); 00216 } 00217 00218 real ServoMotor::getMaxTorque() const 00219 { 00220 return mData.maxTorque; 00221 } 00222 00223 void ServoMotor::setRestoreSpeed( real speed ) 00224 { 00225 mData.restoreSpeed = speed; 00226 } 00227 00228 real ServoMotor::getRestoreSpeed() const 00229 { 00230 return mData.restoreSpeed; 00231 } 00232 00233 bool ServoMotor::internal_dependsOnJoint( Joint* j ) 00234 { 00235 if ( j == mData.joint ) 00236 { 00237 return true; 00238 } 00239 else 00240 { 00241 return false; 00242 } 00243 } 00244 }