00001 /** 00002 * @file Motionfield.cpp 00003 * 00004 * Implementation of class Motionfield 00005 * 00006 * @author <a href="mailto:timlaue@informatik.uni-bremen.de">Tim Laue</a> 00007 */ 00008 00009 #include "Motionfield.h" 00010 #include "FieldObject.h" 00011 #include "PfieldDatatypes.h" 00012 #include "RandomMotionGenerator.h" 00013 #include "AStarSearch.h" 00014 #include "PotentialfieldComposition.h" 00015 #ifdef POTENTIALFIELDS_FOR_GT2004_ 00016 #include "Tools/Debugging/Debugging.h" 00017 #include "Tools/Debugging/DebugDrawings.h" 00018 #endif //POTENTIALFIELDS_FOR_GT2004_ 00019 00020 00021 Motionfield::Motionfield(const std::string& name) 00022 { 00023 this->name = name; 00024 randomMotionGenerator = 0; 00025 pathPlanner = 0; 00026 pathPlannerActive = false; 00027 alwaysUsePathPlanner = false; 00028 translationDisabled = false; 00029 rotationDisabled = false; 00030 lastMotionVector.x = 0.0; 00031 lastMotionVector.y = 0.0; 00032 } 00033 00034 00035 Motionfield::~Motionfield() 00036 { 00037 if(randomMotionGenerator) 00038 { 00039 delete randomMotionGenerator; 00040 } 00041 if(pathPlanner) 00042 { 00043 delete pathPlanner; 00044 } 00045 if(aStarParameterSet.stabilizationObject) 00046 { 00047 delete aStarParameterSet.stabilizationObject; 00048 } 00049 } 00050 00051 00052 void Motionfield::execute(const PfPose& pose, PotentialfieldResult& result) 00053 { 00054 result.actionPossible = true; 00055 result.subAction = ""; 00056 PfVec gradientVec; 00057 if(pathPlanner == 0) 00058 { 00059 gradientVec = getFieldVecAt(pose); 00060 } 00061 else if(alwaysUsePathPlanner) 00062 { 00063 gradientVec = getFieldVecFromAStarSearch(pose); 00064 } 00065 else if(pathPlannerActive) 00066 { 00067 gradientVec = getFieldVecFromAStarSearch(pose); 00068 pathPlannerActive = pathPlanningStillNeeded(pose); 00069 } 00070 else 00071 { 00072 gradientVec = getFieldVecAt(pose); 00073 pathPlannerActive = reachedLocalMinimum(gradientVec.length()); 00074 } 00075 correctMotionVector(gradientVec); 00076 lastMotionVector = gradientVec; 00077 gradientVec.rotate(-pose.rotation); 00078 if(translationDisabled) 00079 { 00080 result.motion.pos.x = 0.0; 00081 result.motion.pos.y = 0.0; 00082 } 00083 else 00084 { 00085 result.motion.pos = gradientVec; 00086 result.motion.pos.normalize(); 00087 } 00088 if(rotationDisabled || (gradientVec.length() == 0)) 00089 { 00090 result.motion.rotation = 0.0; 00091 } 00092 else 00093 { 00094 result.motion.rotation = gradientVec.getAngle(); 00095 } 00096 result.motion.speed = gradientVec.length(); 00097 if(criterion == CRITERION_CONST) 00098 { 00099 result.value = criterionParameter; 00100 } 00101 else if(criterion == CRITERION_GRADIENT) 00102 { 00103 result.value = -result.motion.speed; 00104 } 00105 } 00106 00107 00108 PfVec Motionfield::getFieldVecFromAStarSearch(const PfPose& pose) 00109 { 00110 PotentialfieldAStarNode start; 00111 PfPose goalPose(this->goal->getPose(pose)); 00112 PfPose startPose(pose); 00113 startPose.probabilityDistribution.clear(); 00114 startPose.hasProbabilityDistribution = false; 00115 start.setPose(pose); 00116 start.setFunctionValues(0,0); 00117 start.setValueAtPos(aStarParameterSet); 00118 aStarParameterSet.startPosition = start.getPose().pos; 00119 PotentialfieldAStarNode goal; 00120 goal.setPose(goalPose); 00121 if(aStarParameterSet.useStabilization && aStarParameterSet.numberOfCalls) 00122 { 00123 PfVec stabilizationPosition(-lastMotionVector.x,-lastMotionVector.y); 00124 stabilizationPosition.normalize(); 00125 stabilizationPosition *= aStarParameterSet.stabilizationDistance; 00126 stabilizationPosition += pose.pos; 00127 PfPose stabObjectPose; 00128 stabObjectPose.pos = stabilizationPosition; 00129 stabObjectPose.rotation = (pose.pos - stabilizationPosition).getAngle(); 00130 aStarParameterSet.stabilizationObject->setPose(stabObjectPose); 00131 } 00132 PotentialfieldAStarNode nextPosition = 00133 pathPlanner->search(start, goal, aStarParameterSet, plannedPathLengthToGoal); 00134 PfVec result(nextPosition.getPose().pos-pose.pos); 00135 result.normalize(); 00136 result *= aStarParameterSet.standardGradientLength; 00137 aStarParameterSet.numberOfCalls++; 00138 return result; 00139 } 00140 00141 00142 bool Motionfield::reachedLocalMinimum(double currentGradientLength) 00143 { 00144 return (currentGradientLength <= maxGradientLengthForLocalMinimum); 00145 } 00146 00147 00148 bool Motionfield::pathPlanningStillNeeded(const PfPose& pose) 00149 { 00150 PfPose currentPose(pose); 00151 PfPose goalPose(this->goal->getPose()); 00152 PfVec nextStep; 00153 double gradientTrajectoryLength(0.0); 00154 double stepLength(aStarParameterSet.minExpansionRadius); 00155 double maxLength(plannedPathLengthToGoal*2.0); 00156 while(gradientTrajectoryLength < maxLength) 00157 { 00158 if((currentPose.pos - goalPose.pos).length() < aStarParameterSet.distanceToGoal) 00159 { 00160 aStarParameterSet.numberOfCalls = 0; //reset call counter 00161 #ifdef POTENTIALFIELDS_FOR_GT2004_ 00162 DEBUG_DRAWING_FINISHED(behavior_aStarSearch); 00163 #endif //POTENTIALFIELDS_FOR_GT2004_ 00164 return false; 00165 } 00166 nextStep = getFieldVecAt(currentPose); 00167 nextStep.normalize(); 00168 nextStep *= stepLength; 00169 currentPose.addAbsVector(nextStep); 00170 gradientTrajectoryLength += stepLength; 00171 } 00172 return true; 00173 } 00174 00175 00176 void Motionfield::correctMotionVector(PfVec& motionVector) const 00177 { 00178 double secondsSinceLastResult(((double)(getSystemTime()-lastResult.timeStamp))/1000.0); 00179 if(maxAccel > 0.0) 00180 { 00181 double currentSpeed(motionVector.length()); 00182 double lastSpeed(lastMotionVector.length()); 00183 double speedDiff((currentSpeed - lastSpeed)/secondsSinceLastResult); 00184 if(speedDiff > maxAccel) 00185 { 00186 motionVector.normalize(); 00187 motionVector *= (lastSpeed + maxAccel*secondsSinceLastResult); 00188 } 00189 else if(speedDiff < -maxAccel) 00190 { 00191 motionVector.normalize(); 00192 motionVector *= (lastSpeed - maxAccel*secondsSinceLastResult); 00193 } 00194 } 00195 if(maxGradientDifference > 0.0) 00196 { 00197 double currentAngle(motionVector.getAngle()); 00198 double lastAngle(lastMotionVector.getAngle()); 00199 double diffAngle(currentAngle-lastAngle); 00200 PfPose dummyPose; dummyPose.rotation = diffAngle; dummyPose.normRotation(); 00201 diffAngle = dummyPose.rotation; 00202 double currentRotAccel(diffAngle / secondsSinceLastResult); 00203 if(currentRotAccel > maxGradientDifference) 00204 { 00205 motionVector.rotate(-diffAngle + maxGradientDifference*secondsSinceLastResult); 00206 } 00207 else if(currentRotAccel < -maxGradientDifference) 00208 { 00209 motionVector.rotate(-diffAngle - maxGradientDifference*secondsSinceLastResult); 00210 } 00211 } 00212 } 00213 00214 00215 00216 /* 00217 * $Log: Motionfield.cpp,v $ 00218 * Revision 1.1.1.1 2004/05/22 17:37:27 cvsadm 00219 * created new repository GT2004_WM 00220 * 00221 * Revision 1.1 2004/01/20 15:42:19 tim 00222 * Added potential fields implementation 00223 * 00224 * Revision 1.7 2003/06/13 14:27:58 tim 00225 * added random generator and tangential fields 00226 * 00227 * Revision 1.6 2003/06/09 20:00:04 tim 00228 * Changed potentialfield architecture 00229 * 00230 * Revision 1.5 2003/04/22 14:35:17 tim 00231 * Merged changes from GO 00232 * 00233 * Revision 1.5 2003/04/12 06:21:17 tim 00234 * Stand vor dem Spiel gegen Dortmund 00235 * 00236 * Revision 1.4 2003/04/02 14:39:11 tim 00237 * Changed Bremen Byters Behavior 00238 * 00239 * Revision 1.3 2003/03/30 15:32:09 tim 00240 * several minor changes 00241 * 00242 * Revision 1.2 2003/03/23 20:32:37 loetzsch 00243 * removed green compiler warning: no newline at end of file 00244 * 00245 * Revision 1.1 2003/03/23 17:51:27 tim 00246 * Added potentialfields 00247 * 00248 */