00001
00002
00003
00004
00005
00006
00007
00008 #include "Experiment.hpp"
00009
00010 #include <telekyb_base/ROS.hpp>
00011 #include <telekyb_base/Time.hpp>
00012
00013 #include <telekyb_base/Spaces.hpp>
00014
00015 #include <boost/algorithm/string.hpp>
00016
00017 #define FLYTO_Z -0.75
00018
00019 namespace telekyb {
00020
00021 Experiment::Experiment()
00022 : currState(State::Init),
00023 mainNodeHandle( ROSModule::Instance().getMainNodeHandle() ),
00024 system(NULL),
00025 mkInterface(NULL),
00026 neutralPosSet(false)
00027 {
00028 system = telekyb_interface::TeleKybSystem::getTeleKybSystem(options.robotID->getValue());
00029 if (!system) {
00030
00031 ros::shutdown();
00032 return;
00033 }
00034
00035
00036 if (options.tUseMKInterface->getValue()) {
00037 ROS_INFO("Creating MKInterface!");
00038
00039 mkInterface = telekyb_interface::MKInterface::getMKInterface(options.robotID->getValue());
00040
00041 if (!mkInterface) {
00042
00043 ros::shutdown();
00044 return;
00045 }
00046 }
00047
00048 bController = system->getBehaviorController();
00049 oController = system->getOptionController();
00050
00051
00052
00053 bController->setActiveBehaviorListener(this);
00054 activeBehaviorPtr = bController->getActiveBehaviorPointer();
00055
00056
00057 udp.initSender(options.tClientHostname->getValue().c_str(), options.tClientPort->getValue());
00058 udp.initReceiver(options.tClientPort->getValue());
00059
00060 setupExperiment();
00061 }
00062
00063 Experiment::~Experiment()
00064 {
00065 if (mkInterface) { delete mkInterface; }
00066
00067 delete system;
00068 }
00069
00070 void Experiment::setupExperiment()
00071 {
00072
00073 ground = bController->getSystemBehavior("tk_behavior/Ground");
00074 hover = bController->getSystemBehavior("tk_behavior/Hover");
00075 normalBreak = bController->getSystemBehavior("tk_behavior/NormalBrake");
00076 takeOff = bController->getSystemBehavior("tk_behavior/TakeOff");
00077 land = bController->getSystemBehavior("tk_behavior/Land");
00078
00079
00080
00081 if (ground.isNull() || hover.isNull() || normalBreak.isNull() || takeOff.isNull() || land.isNull()) {
00082 ROS_FATAL("Unable to get SystemBehavior!!!");
00083
00084 ros::shutdown();
00085 }
00086
00087
00088 takeOff.getOptionContainer().getOption("tTakeOffDestination").set(Position3D(0.0,0.0,-1.0));
00089 takeOff.getOptionContainer().getOption("tTakeOffVertically").set(true);
00090
00091 takeOff.setParameterInitialized(true);
00092
00093 land.getOptionContainer().getOption("tLandDestination").set(Position3D(0.0,0.0,0.0));
00094 land.getOptionContainer().getOption("tLandDestinationHeight").set(-0.15);
00095 land.getOptionContainer().getOption("tLandVertically").set(true);
00096
00097 land.setParameterInitialized(true);
00098
00099 handJoystick = bController->loadBehavior("tk_vrqc2011/HandJoystick");
00100
00101 if ( handJoystick.isNull() ) {
00102 ROS_FATAL("Unable to load HandJoystick!!!");
00103
00104 ros::shutdown();
00105 }
00106
00107
00108 handJoystick.getOptionContainer().getOption("tHandJoystickTopic").set(options.tHandJoystickTopic->getValue());
00109 handJoystick.getOptionContainer().getOption("tHandJoystickScale").set(1.0);
00110 handJoystick.setNextBehavior(land);
00111 handJoystick.setParameterInitialized(true);
00112
00113
00114 takeOff.setNextBehavior(handJoystick);
00115
00116 flyToTakeOff = bController->loadBehavior("tk_behavior/TakeOff");
00117 flyTo = bController->loadBehavior("tk_be_common/DynamicFlyTo");
00118 flyToLand = bController->loadBehavior("tk_behavior/Land");
00119 if (flyToTakeOff.isNull() || flyTo.isNull() || flyToLand.isNull()) {
00120 ROS_FATAL("Unable to get FlyTo Behaviors!!!");
00121
00122 ros::shutdown();
00123 }
00124
00125
00126 flyToTakeOff.getOptionContainer().getOption("tTakeOffDestination").set(Position3D(0.0,0.0,FLYTO_Z));
00127 flyToTakeOff.getOptionContainer().getOption("tTakeOffVertically").set(true);
00128 flyToTakeOff.getOptionContainer().getOption("tTakeOffVelocity").set(0.4);
00129 flyToTakeOff.getOptionContainer().getOption("tTakeOffDestinationRadius").set(0.3);
00130
00131 flyToTakeOff.setNextBehavior(flyTo);
00132
00133
00134 flyToTakeOff.setParameterInitialized(true);
00135
00136
00137 flyTo.getOptionContainer().getOption("tFlyToDestination").set(Position3D(0.0,0.0,FLYTO_Z));
00138 flyTo.getOptionContainer().getOption("tFlyToVelocity").set(1.2);
00139 flyTo.getOptionContainer().getOption("tFlyToOuterDestinationRadius").set(0.40);
00140 flyTo.getOptionContainer().getOption("tFlyToInnerDestinationRadius").set(0.03);
00141
00142 flyTo.setNextBehavior(flyToLand);
00143 flyTo.setParameterInitialized(true);
00144
00145 flyToLand.getOptionContainer().getOption("tLandDestination").set(Position3D(0.0,0.0,0.0));
00146 flyToLand.getOptionContainer().getOption("tLandDestinationHeight").set(-0.15);
00147 flyToLand.getOptionContainer().getOption("tLandVelocity").set(0.4);
00148 flyToLand.getOptionContainer().getOption("tLandVertically").set(false);
00149
00150
00151 flyToLand.setNextBehavior(ground);
00152 flyToLand.setParameterInitialized(true);
00153
00154
00155 if (*activeBehaviorPtr != ground) {
00156 ROS_ERROR("UAV not in Ground Behavior during Startup");
00157 ros::shutdown();
00158 }
00159
00160
00161 joySub = mainNodeHandle.subscribe(options.tJoystickTopic->getValue()
00162 , 10, &Experiment::joystickCB, this);
00163
00164
00165 handJoySub = mainNodeHandle.subscribe(options.tHandJoystickTopic->getValue()
00166 , 10, &Experiment::handJoystickCB, this);
00167
00168
00169 srand((unsigned)time(NULL));
00170 }
00171
00172
00173
00174
00175 void Experiment::joystickCB(const sensor_msgs::Joy::ConstPtr& msg)
00176 {
00177
00178 if (msg->buttons.size() < 10) {
00179 ROS_ERROR("Jostick does not publish enough buttons.");
00180 return;
00181 }
00182
00183
00184 if (msg->buttons[6]) {
00185 ROS_WARN("Emergency Button pressed!");
00186 mkInterface->setEmergency();
00187 }
00188
00189
00190 if (mkInterface && *activeBehaviorPtr == ground && msg->buttons[0]) {
00191
00192 MKSingleValuePacket motorState(MKDataDefines::MOTOR_STATE,0);
00193 if (!mkInterface->updateMKValue(motorState)) {
00194 ROS_ERROR("Could not get Motorstate!");
00195 return;
00196 }
00197
00198 if (motorState.value == MotorState::On) {
00199
00200 motorState.value = MotorState::Off;
00201 mkInterface->setMKValue(motorState);
00202 } else if (motorState.value == MotorState::Off) {
00203
00204 motorState.value = MotorState::Init;
00205 mkInterface->setMKValue(motorState);
00206 } else if (motorState.value == MotorState::Init) {
00207 motorState.value = MotorState::On;
00208 mkInterface->setMKValue(motorState);
00209 }
00210
00211
00212 }
00213
00214 if (msg->buttons[2]) {
00215 ROS_ERROR("LiftOff/Land Button.");
00216 if (*activeBehaviorPtr == ground) {
00217
00218 bController->switchBehavior(takeOff);
00219 } else {
00220
00221 bController->switchBehavior(land);
00222 }
00223 }
00224
00225
00226 if (msg->buttons[3]) {
00227
00228
00229 changeState("#error#There was an error.#", State::Error);
00230 }
00231
00232 if (msg->buttons[4]) {
00233 ROS_INFO("Received Joystick CB");
00234
00235 ROS_INFO("CurrentState: %s", currState.str());
00236 std::string command;
00237
00238 if (currState == State::Init) {
00239 changeState("#startExp#", State::Init);
00240 }
00241 }
00242
00243
00244 if (msg->buttons[5]) {
00245 double flyToX = (((double)rand() / RAND_MAX) - 0.5) * 4.0;
00246 double flyToY = (((double)rand() / RAND_MAX) - 0.5) * 4.0;
00247
00248
00249
00250 if (flyToX > 2.0 || flyToY > 2.0) {
00251 ROS_ERROR("Cannot fly outside of 2.0/2.0");
00252 return;
00253 }
00254
00255 Position3D flyToDestination(flyToX, flyToY, FLYTO_Z);
00256 Position3D flyToLandDestination(flyToX, flyToY, 0.0);
00257
00258 flyTo.getOptionContainer().getOption("tFlyToDestination").set(flyToDestination);
00259 flyToLand.getOptionContainer().getOption("tLandDestination").set(flyToLandDestination);
00260
00261 ROS_INFO("Flying to %f,%f", flyToX, flyToY);
00262
00263
00264 if (*activeBehaviorPtr == ground) {
00265 bController->switchBehavior(flyToTakeOff);
00266 } else {
00267 bController->switchBehavior(flyTo);
00268 }
00269 }
00270
00271
00272 if (msg->buttons[9]) {
00273 neutralPosSet = true;
00274
00275 if (currState == State::Config) {
00276 changeState("#readyT#", State::Ready);
00277 }
00278
00279 }
00280
00281
00282
00283
00284 }
00285
00286 void Experiment::readSpin()
00287 {
00288
00289 char buffer[255];
00290 int recvBytes;
00291 while(ros::ok()) {
00292 udp.doSelect();
00293 if ((recvBytes = udp.recvRaw(buffer,sizeof(buffer))) > 0) {
00294 std::string msg(buffer, recvBytes);
00295 ROS_INFO_STREAM("Got Message: " << msg);
00296
00297 std::vector<std::string> segments;
00298 boost::split(segments, msg, boost::is_any_of("#"));
00299 ROS_INFO_STREAM("segments.size(): " << segments.size());
00300
00301
00302 std::string command = segments.at(1);
00303
00304 ROS_INFO_STREAM("Got command: " << command);
00305
00306
00307
00308
00309 if (currState == State::Init && command == "readyV") {
00310 ROS_INFO("State: init->config");
00311
00312
00313 double flyToX = 0.0;
00314 double flyToY = 0.0;
00315 if (segments.size() > 5) {
00316 flyToX = boost::lexical_cast<double>(segments.at(2));
00317 flyToY = -1.0 * boost::lexical_cast<double>(segments.at(4));
00318 } else {
00319 ROS_ERROR("Did not receive enough segments! Flying to 0/0/0");
00320 return;
00321 }
00322
00323
00324 if (abs(flyToX - options.tXYOffsetTranslation->getValue()(0)) > options.tMaxSquareAreaSize->getValue()) {
00325 changeState("#error#X Value out of bounds!#", State::Error);
00326 return;
00327 }
00328
00329 if (abs(flyToY - options.tXYOffsetTranslation->getValue()(1)) > options.tMaxSquareAreaSize->getValue()) {
00330 changeState("#error#Y Value out of bounds!#", State::Error);
00331 return;
00332 }
00333
00334 Position3D flyToDestination(flyToX, flyToY, FLYTO_Z);
00335 Position3D flyToLandDestination(flyToX, flyToY, 0.0);
00336
00337 flyTo.getOptionContainer().getOption("tFlyToDestination").set(flyToDestination);
00338 flyToLand.getOptionContainer().getOption("tLandDestination").set(flyToLandDestination);
00339
00340 bController->switchBehavior(flyToTakeOff);
00341
00342
00343 currState = State::Config;
00344
00345 } else if (command == "flyto") {
00350
00351 double flyToX = 0.0;
00352 double flyToY = 0.0;
00353 if (segments.size() > 5) {
00354
00355 flyToX = boost::lexical_cast<double>(segments.at(2));
00356 flyToY = -1.0 * boost::lexical_cast<double>(segments.at(4));
00357
00358
00359
00360 if (abs(flyToX - options.tXYOffsetTranslation->getValue()(0)) > options.tMaxSquareAreaSize->getValue()) {
00361 changeState("#error#X Value out of bounds!#", State::Error);
00362 return;
00363 }
00364
00365 if (abs(flyToY - options.tXYOffsetTranslation->getValue()(1)) > options.tMaxSquareAreaSize->getValue()) {
00366 changeState("#error#Y Value out of bounds!#", State::Error);
00367 return;
00368 }
00369
00370 } else {
00371 ROS_ERROR("Did not receive enough segments! Flying to 0/0/0");
00372 return;
00373 }
00374
00375 Position3D flyToDestination(flyToX, flyToY, FLYTO_Z);
00376 Position3D flyToLandDestination(flyToX, flyToY, 0.0);
00377
00378 flyTo.getOptionContainer().getOption("tFlyToDestination").set(flyToDestination);
00379 flyToLand.getOptionContainer().getOption("tLandDestination").set(flyToLandDestination);
00380
00381
00382 if (currState == State::Ready || currState == State::TakeOff) {
00383
00384 bController->switchBehavior(flyToTakeOff);
00385 currState = State::Flyto;
00386 } else if (currState == State::Flyto
00387 || currState == State::User) {
00388
00389 bController->switchBehavior(flyTo);
00390 currState = State::Flyto;
00391 } else {
00392 ROS_ERROR("Received FlyTo in invalid State: %s", currState.str());
00393 }
00394
00395 } else if (currState == State::Ready && command == "target") {
00396 ROS_INFO("Received Target. Ready for Takeoff.");
00397 currState = State::TakeOff;
00398 } else if (currState == State::Ready && command == "finished") {
00399 ROS_INFO("Experiment finished! Turning off Motors.");
00400
00401 MKSingleValuePacket motorState(MKDataDefines::MOTOR_STATE,0);
00402 if (!mkInterface->updateMKValue(motorState)) {
00403 ROS_ERROR("Could not get Motorstate!");
00404 return;
00405 }
00406
00407 if (motorState.value == MotorState::On || motorState.value == MotorState::Init) {
00408
00409 motorState.value = MotorState::Off;
00410 mkInterface->setMKValue(motorState);
00411 }
00412
00413 } else {
00414 ROS_ERROR("Received Command in Invalid State. Command: %s, State: %s", command.c_str(), currState.str());
00415 }
00416
00417 }
00418
00419 usleep(10);
00420 }
00421 }
00422
00423 void Experiment::handJoystickCB(const sensor_msgs::Joy::ConstPtr& msg)
00424 {
00425
00426 if (currState == State::TakeOff && *activeBehaviorPtr == ground && msg->axes[2] <= -1.0) {
00427 bController->switchBehavior(takeOff);
00428
00429 changeState("#liftoff#", State::User);
00430 }
00431 }
00432
00433 void Experiment::activeBehaviorChanged(telekyb_interface::Behavior newActiveBehavior)
00434 {
00435 ROS_INFO("activeBehaviorChanged CALLLED!!!!");
00436 if (newActiveBehavior == ground) {
00437 if (currState == State::User) {
00438 changeState("#touchdown#", State::Ready);
00439 } else if (currState == State::Flyto) {
00440 changeState("#readyT#", State::Ready);
00441 }
00442 } else if (newActiveBehavior == flyToLand || newActiveBehavior == land) {
00443
00444
00445 }
00446
00447 }
00448
00449 void Experiment::changeState(const std::string& command, State newState)
00450 {
00451 ROS_INFO("Changing Experimental State: %s -> %s", currState.str(), newState.str());
00452
00453
00454 if (command.size() > 0) {
00455 udp.doSelect();
00456 udp.sendRaw(command.c_str(),command.size()+1);
00457 }
00458
00459 currState = newState;
00460 }
00461
00462 }