00001
00002
00003 #include "DualCoding/VRmixin.h"
00004 using namespace DualCoding;
00005
00006
00007 #include "Kodu/Primitives/KoduActionMotion.h"
00008 #include "Kodu/Primitives/KoduConditionBump.h"
00009 #include "Kodu/Primitives/PerceptionSearch.h"
00010
00011 namespace Kodu {
00012
00013
00014
00015 MotionCommand::MotionCommand()
00016 : targetObject(),
00017 dx(0),
00018 da(0),
00019 forwardSpeed(0),
00020 turnSpeed(0),
00021 cmdDriven(false)
00022 { }
00023
00024 MotionCommand::MotionCommand(const ShapeRoot& kTarget, float fwdSpeed, float trnSpeed)
00025 : targetObject(kTarget),
00026 dx(0.0f),
00027 da(0.0f),
00028 forwardSpeed(fwdSpeed),
00029 turnSpeed(trnSpeed),
00030 cmdDriven(false)
00031 { }
00032
00033 MotionCommand::MotionCommand(float fwdDist, float trnAngle, float fwdSpeed, float trnSpeed)
00034 : targetObject(ShapeRoot()),
00035 dx(fwdDist),
00036 da(trnAngle),
00037 forwardSpeed(fwdSpeed),
00038 turnSpeed(trnSpeed),
00039 cmdDriven(false)
00040 { }
00041
00042
00043 MotionCommand::MotionCommand(const DualCoding::ShapeRoot& kTarget,
00044 float fwdDist, float trnAngle, float fwdSpeed, float trnSpeed)
00045 : targetObject(kTarget),
00046 dx(fwdDist),
00047 da(trnAngle),
00048 forwardSpeed(fwdSpeed),
00049 turnSpeed(trnSpeed),
00050 cmdDriven(false)
00051 { }
00052
00053 MotionCommand::MotionCommand(const MotionCommand& kCommand)
00054 : targetObject(kCommand.targetObject),
00055 dx(kCommand.dx),
00056 da(kCommand.da),
00057 forwardSpeed(kCommand.forwardSpeed),
00058 turnSpeed(kCommand.turnSpeed),
00059 cmdDriven(kCommand.cmdDriven)
00060 { }
00061
00062 MotionCommand::MotionCommand(float fwdDist, float trnAngle, float fwdSpeed, float trnSpeed, bool driven)
00063 : targetObject(ShapeRoot()),
00064 dx(fwdDist),
00065 da(trnAngle),
00066 forwardSpeed(fwdSpeed),
00067 turnSpeed(trnSpeed),
00068 cmdDriven(driven)
00069 { }
00070
00071
00072 MotionCommand::~MotionCommand() { }
00073
00074 MotionCommand& MotionCommand::operator=(const MotionCommand& kCommand) {
00075 if (this != &kCommand) {
00076 targetObject = kCommand.targetObject;
00077 dx = kCommand.dx;
00078 da = kCommand.da;
00079 forwardSpeed = kCommand.forwardSpeed;
00080 turnSpeed = kCommand.turnSpeed;
00081 cmdDriven = kCommand.cmdDriven;
00082 }
00083 return *this;
00084 }
00085
00086 bool MotionCommand::operator==(const MotionCommand& kCommand) {
00087 return cmdDriven == kCommand.cmdDriven &&
00088 targetObject.getId() == kCommand.targetObject.getId() &&
00089 dx == kCommand.dx && da == kCommand.da;
00090 }
00091
00092 bool MotionCommand::operator!=(const MotionCommand& kCommand) { return (!(*this == kCommand)); }
00093
00094 float MotionCommand::getForwardSpeed() const { return forwardSpeed; }
00095
00096 float MotionCommand::getTurnSpeed() const { return turnSpeed; }
00097
00098 float MotionCommand::getDistanceToTravel() const { return dx; }
00099
00100 float MotionCommand::getTurningAngle() const { return da; }
00101
00102 bool MotionCommand::isValid() const {
00103 return (cmdDriven || targetObject.isValid() || dx != 0 || da != 0);
00104 }
00105
00106 bool MotionCommand::targetObjectIsValid() const { return targetObject.isValid(); }
00107
00108 bool MotionCommand::isDriven () const { return cmdDriven; }
00109
00110 const ShapeRoot& MotionCommand::getTargetObject() const { return targetObject; }
00111
00112 std::ostream& operator<<(std::ostream &os, const MotionCommand &cmd) {
00113 os << "MotionCommand[";
00114 if ( cmd.cmdDriven )
00115 os << "drive";
00116 else if ( cmd.targetObject.isValid() )
00117 os << "gotoShape " << cmd.targetObject.getId();
00118 else if ( cmd.dx != 0 || cmd.da != 0 )
00119 os << "dx= " << cmd.dx << ",da=" << cmd.da;
00120 os << "]";
00121 return os;
00122 }
00123
00124
00125
00126
00127 KoduActionMotion::KoduActionMotion(MotionType_t type, MotionRate_t rate, unsigned int motionMagCount)
00128 : KoduAction("KoduActionMotion", KoduAction::AT_MOTION, false, false),
00129 motionType(type),
00130 angleGen(0,0),
00131 distGen(0,0),
00132 directionToFace()
00133 {
00134
00135 if (type < MT_EMPTY_MOTION_TYPE) {
00136
00137 if (type == MT_MOVE_WANDER) {
00138 angleGen.setNumericValues(0, M_PI * 2.0f);
00139 distGen.setNumericValues(500, 300);
00140 }
00141 else if (type == MT_MOVE_FORWARD) {
00142 distGen.setNumericValues(500, 0);
00143 }
00144 }
00145 else if (type == MT_TURN_LEFT)
00146 angleGen.setNumericValues(-M_PI, 0);
00147 else if (type == MT_TURN_RIGHT)
00148 angleGen.setNumericValues(M_PI, 0);
00149 }
00150
00151 KoduActionMotion::KoduActionMotion(Direction_t direction, MotionRate_t rate,
00152 unsigned int motionMagCount)
00153 : KoduAction("KoduActionMotion", KoduAction::AT_MOTION, false, false),
00154 motionType(MT_TURN_DIRECTION),
00155 angleGen(0,0),
00156 distGen(0,0),
00157 directionToFace(direction)
00158 { }
00159
00160 KoduActionMotion::KoduActionMotion(const KoduActionMotion& kAction)
00161 : KoduAction(kAction),
00162 motionType(kAction.motionType),
00163 angleGen(kAction.angleGen),
00164 distGen(kAction.distGen),
00165 directionToFace(kAction.directionToFace)
00166 { }
00167
00168
00169 KoduActionMotion::~KoduActionMotion() {
00170
00171 }
00172
00173
00174 KoduActionMotion& KoduActionMotion::operator=(const KoduActionMotion& kAction) {
00175 if (this != &kAction) {
00176 KoduAction::operator=(kAction);
00177 motionType = kAction.motionType;
00178 angleGen = kAction.angleGen;
00179 distGen = kAction.distGen;
00180 directionToFace = kAction.directionToFace;
00181 }
00182 return *this;
00183 }
00184
00185 const MotionCommand KoduActionMotion::getMotionCommand() {
00186 MotionCommand motionCmd;
00187 switch (motionType) {
00188
00189 case MT_MOVE_WANDER:
00190 {
00191 motionCmd.dx = distGen.getNumericValue();
00192 motionCmd.da = angleGen.getNumericValue();
00193 break;
00194 }
00195
00196
00197 case MT_MOVE_FORWARD:
00198 {
00199 motionCmd.dx = distGen.getNumericValue();
00200 break;
00201 }
00202
00203
00204 case MT_MOVE_TOWARDS:
00205 {
00206 if ( ObjectKeeper::isValid &&
00207 distanceInBetweenAgentAndObject(ObjectKeeper::tempObject) > KoduConditionBump::kMaxDistanceAwayToSenseBump ) {
00208
00209
00210
00211 motionCmd.targetObject = ObjectKeeper::tempObject;
00212 }
00213 break;
00214 }
00215
00216 case MT_MOVE_GAMEPAD:
00217 {
00218 motionCmd.cmdDriven = true;
00219 break;
00220 }
00221
00222 case MT_EMPTY_MOTION_TYPE:
00223 break;
00224
00225
00226 case MT_TURN_DIRECTION:
00227 {
00228 float requestedHeading = 0.0f;
00229
00230 if (directionToFace & DT_EAST) {
00231 requestedHeading = (1.5f * M_PI);
00232 } else if (directionToFace & DT_WEST) {
00233 requestedHeading = (0.5f * M_PI);
00234 }
00235
00236 if (directionToFace & DT_NORTH) {
00237 requestedHeading = (2.0f * M_PI);
00238 } else if (directionToFace & DT_SOUTH) {
00239 requestedHeading = (1.0f * M_PI);
00240 }
00241
00242
00243 float currOrient = VRmixin::theAgent->getOrientation();
00244 float minTurnAngle = requestedHeading - currOrient;
00245
00246 if (std::fabs(minTurnAngle) > M_PI) {
00247 float angleDiff = std::fabs(minTurnAngle) - M_PI;
00248 minTurnAngle = (minTurnAngle > 0.0f ? (-1.0f * angleDiff) : angleDiff);
00249 }
00250
00251
00252 static const float kFiveDegrees = 5.0f * M_PI / 180.0f;
00253
00254 if (std::fabs(minTurnAngle) < kFiveDegrees)
00255
00256 motionCmd.da = 0;
00257 else
00258 motionCmd.da = minTurnAngle;
00259 break;
00260 }
00261
00262
00263 case MT_TURN_LEFT:
00264 {
00265 motionCmd.da = angleGen.getNumericValue();
00266 break;
00267 }
00268
00269
00270 case MT_TURN_RIGHT:
00271 {
00272 motionCmd.da = angleGen.getNumericValue();
00273 break;
00274 }
00275 }
00276 return motionCmd;
00277 }
00278
00279
00280 KoduActionMotion::MotionType_t KoduActionMotion::getMotionType() const {
00281 return motionType;
00282 }
00283
00284 bool KoduActionMotion::motionTypeIsMove() const {
00285 return (motionType < MT_EMPTY_MOTION_TYPE);
00286 }
00287
00288 bool KoduActionMotion::motionTypeIsTurn() const {
00289 return (motionType > MT_EMPTY_MOTION_TYPE);
00290 }
00291
00292 void KoduActionMotion::reinitialize() {
00293 KoduAction::reinitialize();
00294 }
00295 }