Experiment.cpp
Go to the documentation of this file.
00001 /*
00002  * Experiment.cpp
00003  *
00004  *  Created on: Nov 15, 2011
00005  *      Author: mriedel
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                 // fail
00031                 ros::shutdown();
00032                 return;
00033         }
00034 
00035         //options.tUseMKInterface->setValue(true);
00036         if (options.tUseMKInterface->getValue()) {
00037                 ROS_INFO("Creating MKInterface!");
00038                 // use MKInterface
00039                 mkInterface = telekyb_interface::MKInterface::getMKInterface(options.robotID->getValue());
00040                 //mkInterface = telekyb_interface::MKInterface::getMKInterface(1); // BEWARE TEMPORARY!!!
00041                 if (!mkInterface) {
00042                         // fail
00043                         ros::shutdown();
00044                         return;
00045                 }
00046         }
00047 
00048         bController = system->getBehaviorController();
00049         oController = system->getOptionController();
00050 
00051         //activeBehavior = bController->getActiveBehaviorReference();
00052 
00053         bController->setActiveBehaviorListener(this);
00054         activeBehaviorPtr = bController->getActiveBehaviorPointer();
00055 
00056         // UDP to Virtools
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         // load Behaviors
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         // sanity check
00081         if (ground.isNull() || hover.isNull() || normalBreak.isNull() || takeOff.isNull() || land.isNull()) {
00082                 ROS_FATAL("Unable to get SystemBehavior!!!");
00083                 //ROS_BREAK();
00084                 ros::shutdown();
00085         }
00086 
00087         // setup takeoff
00088         takeOff.getOptionContainer().getOption("tTakeOffDestination").set(Position3D(0.0,0.0,-1.0));
00089         takeOff.getOptionContainer().getOption("tTakeOffVertically").set(true);
00090         // done
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); // actually is default!
00096         // done
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                 //ROS_BREAK();
00104                 ros::shutdown();
00105         }
00106 
00107         // setup joystick
00108         handJoystick.getOptionContainer().getOption("tHandJoystickTopic").set(options.tHandJoystickTopic->getValue());
00109         handJoystick.getOptionContainer().getOption("tHandJoystickScale").set(1.0); // 1m/s
00110         handJoystick.setNextBehavior(land);
00111         handJoystick.setParameterInitialized(true);
00112 
00113         // takeoff next Behavior
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                 //ROS_BREAK();
00122                 ros::shutdown();
00123         }
00124 
00125         // Configure Flyto Behaviors
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         // done
00134         flyToTakeOff.setParameterInitialized(true);
00135 
00136         // This get's set dynamically
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); // 40cm
00140         flyTo.getOptionContainer().getOption("tFlyToInnerDestinationRadius").set(0.03); // 5cm
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); // actually is default!
00149 
00150         // done
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         // lastly start Controller
00161         joySub = mainNodeHandle.subscribe(options.tJoystickTopic->getValue()
00162                         , 10, &Experiment::joystickCB, this);
00163 
00164         // HandJoy
00165         handJoySub = mainNodeHandle.subscribe(options.tHandJoystickTopic->getValue()
00166                         , 10, &Experiment::handJoystickCB, this);
00167 
00168         // For Testing
00169         srand((unsigned)time(NULL));
00170 }
00171 
00172 
00173 
00174 
00175 void Experiment::joystickCB(const sensor_msgs::Joy::ConstPtr& msg)
00176 {
00177         // use button 2
00178         if (msg->buttons.size() < 10) {
00179                 ROS_ERROR("Jostick does not publish enough buttons.");
00180                 return;
00181         }
00182 
00183         // Emergency
00184         if (msg->buttons[6]) {
00185                 ROS_WARN("Emergency Button pressed!");
00186                 mkInterface->setEmergency();
00187         }
00188 
00189         // Button 1! toggle Motors for mkInterface Only in Ground
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                         // stop
00200                         motorState.value = MotorState::Off;
00201                         mkInterface->setMKValue(motorState);
00202                 } else if (motorState.value == MotorState::Off) {
00203                         // start
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                         // takeoff
00218                         bController->switchBehavior(takeOff);
00219                 } else {
00220                         // flying -> land
00221                         bController->switchBehavior(land);
00222                 }
00223         }
00224 
00225         // Test Error
00226         if (msg->buttons[3]) {
00227                 // ROS_INFO("Received Joystick CB");
00228                 //bController->switchBehavior(handJoystick);
00229                 changeState("#error#There was an error.#", State::Error);
00230         }
00231 
00232         if (msg->buttons[4]) {
00233                 ROS_INFO("Received Joystick CB");
00234                 //ROS_INFO("Size: %d, Value: %d", msg->buttons.size(), msg->buttons.at(0));
00235                 ROS_INFO("CurrentState: %s", currState.str());
00236                 std::string command;
00237                 // Start Experiment
00238                 if (currState == State::Init) {
00239                         changeState("#startExp#", State::Init);
00240                 }
00241         }
00242 
00243         // right back. Testing FlyTo
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                 //flyToY = fmax(flyToY, -1.0);
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                 // Set Destination
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                 // Note:: TakeOff is GroundState
00264                 if (*activeBehaviorPtr == ground) {
00265                         bController->switchBehavior(flyToTakeOff);
00266                 } else {
00267                         bController->switchBehavior(flyTo);
00268                 }
00269         }
00270 
00271         // Same Button as Hand Neutral
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         // what to do
00283 
00284 }
00285 
00286 void Experiment::readSpin()
00287 {
00288         // know that it's less then 255.
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                         // parse #
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                         // State Machine
00309                         if (currState == State::Init && command == "readyV") {
00310                                 ROS_INFO("State: init->config");
00311                                 // Get Coodinates and flyto
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                                 // remove translation and check
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                                 // Set Destination
00337                                 flyTo.getOptionContainer().getOption("tFlyToDestination").set(flyToDestination);
00338                                 flyToLand.getOptionContainer().getOption("tLandDestination").set(flyToLandDestination);
00339 
00340                                 bController->switchBehavior(flyToTakeOff);
00341 
00342                                 // Quick Config State
00343                                 currState = State::Config;
00344 
00345                         } else if (command == "flyto") {
00350                                 // Get Destination
00351                                 double flyToX = 0.0;
00352                                 double flyToY = 0.0;
00353                                 if (segments.size() > 5) {
00354                                         // Beware coordinate switch
00355                                         flyToX = boost::lexical_cast<double>(segments.at(2));
00356                                         flyToY = -1.0 * boost::lexical_cast<double>(segments.at(4));
00357 
00358 
00359                                         // remove translation and check
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                                 // Set Destination
00378                                 flyTo.getOptionContainer().getOption("tFlyToDestination").set(flyToDestination);
00379                                 flyToLand.getOptionContainer().getOption("tLandDestination").set(flyToLandDestination);
00380 
00381                                 // Note:: TakeOff is GroundState
00382                                 if (currState == State::Ready || currState == State::TakeOff) {
00383                                         // Standard Case With TakeOff
00384                                         bController->switchBehavior(flyToTakeOff);
00385                                         currState = State::Flyto;
00386                                 } else if (currState == State::Flyto // this does not include the Touchdown Phase of Flyto.
00387                                                 || currState == State::User) {
00388                                         // Disrubtive Case WITHOUT TakeOff
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; // TakeOff is Ground State
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                                         // stop
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         // Liftoff // z maximum
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                 // Landing in Flyto
00444                 //currState = State::Land; // Ground follows automatically.
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         // only send if you have command
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines


tk_vrqc2011
Author(s): Martin Riedel
autogenerated on Wed Apr 24 2013 11:26:17