Main Page | Class Hierarchy | Class List | Directories | File List | Class Members | File Members | Related Pages | Examples

ArServerModeRatioDrive.cpp

Go to the documentation of this file.
00001 /*
00002 MobileRobots Advanced Robotics Interface for Applications (ARIA)
00003 Copyright (C) 2004, 2005 ActivMedia Robotics LLC
00004 Copyright (C) 2006, 2007 MobileRobots Inc.
00005 
00006      This program is free software; you can redistribute it and/or modify
00007      it under the terms of the GNU General Public License as published by
00008      the Free Software Foundation; either version 2 of the License, or
00009      (at your option) any later version.
00010 
00011      This program is distributed in the hope that it will be useful,
00012      but WITHOUT ANY WARRANTY; without even the implied warranty of
00013      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014      GNU General Public License for more details.
00015 
00016      You should have received a copy of the GNU General Public License
00017      along with this program; if not, write to the Free Software
00018      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 
00020 If you wish to redistribute ARIA under different terms, contact 
00021 MobileRobots for information about a commercial version of ARIA at 
00022 robots@mobilerobots.com or 
00023 MobileRobots Inc, 19 Columbia Drive, Amherst, NH 03031; 800-639-9481
00024 */
00025 
00026 #include "Aria.h"
00027 #include "ArExport.h"
00028 #include "ArServerModeRatioDrive.h"
00029 #include "ArServerHandlerCommands.h"
00030 
00031 AREXPORT ArServerModeRatioDrive::ArServerModeRatioDrive(
00032         ArServerBase *server, ArRobot *robot, bool takeControlOnJoystick,
00033         bool useComputerJoystick, bool useRobotJoystick, 
00034         bool useServerCommands, const char *name) : 
00035   ArServerMode(robot, server, name),
00036   myRatioDriveGroup(robot),
00037   myJoyUserTaskCB(this, &ArServerModeRatioDrive::joyUserTask),
00038   myServerSetSafeDriveCB(this, 
00039                          &ArServerModeRatioDrive::serverSetSafeDrive),
00040   myServerGetSafeDriveCB(this, 
00041                          &ArServerModeRatioDrive::serverGetSafeDrive),
00042   myServerRatioDriveCB(this, &ArServerModeRatioDrive::serverRatioDrive),
00043   myRatioFireCB(this, &ArServerModeRatioDrive::ratioFireCallback),
00044   myServerSafeDrivingEnableCB(this, 
00045                              &ArServerModeRatioDrive::serverSafeDrivingEnable),
00046   myServerSafeDrivingDisableCB(this, 
00047                              &ArServerModeRatioDrive::serverSafeDrivingDisable)
00048 {
00049   myHandlerCommands = NULL;
00050   myDriveSafely = true;
00051   myTakeControlOnJoystick = takeControlOnJoystick;
00052   myUseComputerJoystick = useComputerJoystick;
00053   myUseRobotJoystick = useRobotJoystick;
00054   myUseServerCommands = useServerCommands;
00055   myUseLocationDependentDevices = true;
00056 
00057   // add the actions, put the ratio input on top, then have the
00058   // limiters since the ratio doesn't touch decel except lightly
00059   // whereas the limiter will touch it strongly
00060 
00061   myRatioAction = new ArActionRatioInput;
00062   myRatioDriveGroup.addAction(myRatioAction, 50);
00063 
00064   myLimiterForward = new ArActionDeceleratingLimiter(
00065           "DeceleratingLimiterForward", true);
00066   myRatioDriveGroup.addAction(myLimiterForward, 40);
00067 
00068   myLimiterBackward = new ArActionDeceleratingLimiter(
00069           "DeceleratingLimiterBackward", false);
00070   myRatioDriveGroup.addAction(myLimiterBackward, 39);
00071 
00072   myMovementParameters = new ArActionMovementParameters("TeleopMovementParameters", false);
00073   myRatioDriveGroup.addAction(myMovementParameters, 1);
00074 
00075   myRatioFireCB.setName("ArServerModeRatioDrive");
00076   myRatioAction->addFireCallback(30, &myRatioFireCB);
00077   
00078 
00079   
00080   if (myServer != NULL && myUseServerCommands)
00081   {
00082     addModeData("ratioDrive", "drives the robot as with a joystick",
00083                 &myServerRatioDriveCB,
00084                 "double: transRatio; double: rotRatio; double: throttleRatio ",
00085                 "none", "Movement", "RETURN_NONE");
00086     myServer->addData("setSafeDrive", 
00087                       "sets whether we drive the robot safely or not",
00088                       &myServerSetSafeDriveCB,
00089                       "byte: 1 == drive safely, 0 == drive unsafely",
00090                       "none", "UnsafeMovement", "RETURN_NONE");
00091     myServer->addData("getSafeDrive", 
00092                       "gets whether we drive the robot safely or not",
00093                       &myServerGetSafeDriveCB,
00094                       "none", 
00095                       "byte: 1 == driving safely, 0 == driving unsafely", 
00096                       "Movement", "RETURN_SINGLE");
00097   }
00098 
00099   if (myUseComputerJoystick)
00100   {
00101     myJoydrive = new ArRatioInputJoydrive(robot, myRatioAction);
00102     if ((myJoyHandler = Aria::getJoyHandler()) == NULL)
00103     {
00104       myJoyHandler = new ArJoyHandler;
00105       myJoyHandler->init();
00106       Aria::setJoyHandler(myJoyHandler);
00107     }
00108   }
00109   if (myUseRobotJoystick)
00110   {
00111     myRobotJoydrive = new ArRatioInputRobotJoydrive(robot, myRatioAction);
00112     if ((myRobotJoyHandler = Aria::getRobotJoyHandler()) == NULL)
00113     {
00114       myRobotJoyHandler = new ArRobotJoyHandler(robot);
00115       Aria::setRobotJoyHandler(myRobotJoyHandler);
00116     }
00117   }
00118   if (myUseRobotJoystick || myUseComputerJoystick)
00119   {
00120     std::string taskName = name;
00121     taskName += "::joyUserTask";
00122     myRobot->addUserTask(taskName.c_str(), 75, &myJoyUserTaskCB);
00123   }
00124 
00125   myPrinting = false;
00126 }
00127 
00128 AREXPORT ArServerModeRatioDrive::~ArServerModeRatioDrive()
00129 {
00130 
00131 }
00132 
00133 AREXPORT void ArServerModeRatioDrive::addToConfig(ArConfig *config, 
00134                                              const char *section)
00135 {
00136   myRatioAction->addToConfig(config, section);
00137   myLimiterForward->addToConfig(config, section, "Forward");
00138   myLimiterBackward->addToConfig(config, section, "Backward");
00139   myMovementParameters->addToConfig(config, section, "Teleop");
00140   
00141 }
00142 
00143 AREXPORT void ArServerModeRatioDrive::activate(void)
00144 {
00145   ratioDrive(0, 0, 100);
00146 }
00147 
00148 AREXPORT void ArServerModeRatioDrive::deactivate(void)
00149 {
00150   myRatioDriveGroup.deactivate();
00151   baseDeactivate();
00152 }
00153 
00154 AREXPORT void ArServerModeRatioDrive::setSafeDriving(bool safe, bool internal)
00155 {
00156   if (!internal)
00157     myRobot->lock();
00158   // if this is a change then print it
00159   if (safe != myDriveSafely)
00160   {
00161     if (safe)
00162     {
00163       ArLog::log(ArLog::Normal, "%s: Driving safely again", myName.c_str());
00164     }
00165     else
00166     {
00167       ArLog::log(ArLog::Normal, "%s: Driving UNSAFELY", myName.c_str());
00168     }
00169     myNewDriveSafely = true;
00170   }
00171   myDriveSafely = safe;
00172   if (isActive())
00173     ratioDrive(myRatioAction->getTransRatio(), myRatioAction->getRotRatio(),
00174                myRatioAction->getThrottleRatio());
00175   if (!internal)
00176     myRobot->unlock();
00177 }
00178 
00179 AREXPORT bool ArServerModeRatioDrive::getSafeDriving(void)
00180 {
00181   return myDriveSafely;
00182 }
00183 
00184 AREXPORT void ArServerModeRatioDrive::serverSafeDrivingEnable(void)
00185 {
00186   setSafeDriving(true);
00187 }
00188 
00189 AREXPORT void ArServerModeRatioDrive::serverSafeDrivingDisable(void)
00190 {
00191   setSafeDriving(false);
00192 }
00193 
00194 AREXPORT void ArServerModeRatioDrive::addControlCommands(ArServerHandlerCommands *handlerCommands)
00195 {
00196   if (!myUseServerCommands)
00197   {
00198     ArLog::log(ArLog::Normal, 
00199                "ArServerModeRatioDrive::addControlCommands: Tried to add control commands to a ratio drive not using the server");
00200     return;
00201   }
00202   myHandlerCommands = handlerCommands;
00203   myHandlerCommands->addCommand(
00204           "safeRatioDrivingEnable",
00205           "Enables safe driving with ratioDrive, which will attempt to prevent collisions (default)",
00206           &myServerSafeDrivingEnableCB, "UnsafeMovement");
00207   myHandlerCommands->addCommand(
00208           "safeRatioDrivingDisable",
00209           "Disables safe driving with ratioDrive, this is UNSAFE and will let you drive your robot into things or down stairs, use at your own risk",
00210           &myServerSafeDrivingDisableCB, "UnsafeMovement");
00211 }
00212 
00213 AREXPORT void ArServerModeRatioDrive::ratioDrive(double transRatio, 
00214                                                  double rotRatio,
00215                                                  double throttleRatio)
00216 {
00217   bool wasActive;
00218   wasActive = isActive();
00219   if (!wasActive && !baseActivate())
00220     return;
00221   if (!wasActive || myNewDriveSafely)
00222   {
00223     myRobot->clearDirectMotion();
00224     if (myDriveSafely)
00225     {
00226       myRatioDriveGroup.activateExclusive();
00227       myMode = "Drive";
00228       ArLog::log(ArLog::Normal, "%s: Driving safely", myName.c_str());
00229     }
00230     else
00231     {
00232       myRobot->deactivateActions();
00233       myRatioAction->activate();
00234       myMode = "UNSAFE Drive";
00235       ArLog::log(ArLog::Normal, "%s: Driving unsafely", myName.c_str());
00236     }
00237   }
00238   myNewDriveSafely = false;
00239   myTransRatio = transRatio;
00240   myRotRatio = rotRatio;
00241   myThrottleRatio = throttleRatio;
00242   setActivityTimeToNow();
00243   if (myPrinting)
00244     printf("cmd %.0f %.0f %.0f\n", transRatio, rotRatio, throttleRatio);
00245   //myRatioAction.setRatios(transRatio, rotRatio, throttleRatio);
00246 }
00247 
00248 AREXPORT void ArServerModeRatioDrive::serverRatioDrive(ArServerClient *client, 
00249                                                        ArNetPacket *packet)
00250 {
00251   double transRatio;
00252   double rotRatio;
00253   double throttleRatio;
00254   transRatio = packet->bufToDouble();
00255   rotRatio = packet->bufToDouble();
00256   throttleRatio = packet->bufToDouble();
00257   if (!myDriveSafely && !client->hasGroupAccess("UnsafeMovement"))    
00258     serverSafeDrivingEnable();
00259   myRobot->lock();
00260   ratioDrive(transRatio, rotRatio, throttleRatio);
00261   myRobot->unlock();
00262 }
00263 
00264 AREXPORT void ArServerModeRatioDrive::serverSetSafeDrive(
00265         ArServerClient *client, ArNetPacket *packet)
00266 {
00267   if (packet->bufToUByte() == 0)
00268     setSafeDriving(false);
00269   else
00270     setSafeDriving(true);
00271 }
00272 
00273 AREXPORT void ArServerModeRatioDrive::serverGetSafeDrive(
00274         ArServerClient *client, ArNetPacket *packet)
00275 {
00276   ArNetPacket sendPacket;
00277   if (getSafeDriving())
00278     sendPacket.uByteToBuf(1);
00279   else
00280     sendPacket.uByteToBuf(0);
00281   
00282   client->sendPacketTcp(&sendPacket);
00283 }
00284 
00285 
00286 AREXPORT void ArServerModeRatioDrive::joyUserTask(void)
00287 {
00288   
00289   // if we're not active but we should be
00290   if (myTakeControlOnJoystick && !isActive() && 
00291       ((myUseComputerJoystick && myJoyHandler->haveJoystick() && 
00292         myJoyHandler->getButton(1)) || 
00293        (myUseRobotJoystick && myRobotJoyHandler->gotData() && 
00294         myRobotJoyHandler->getButton1())))
00295   {
00296     if (ArServerMode::getActiveMode() != NULL)
00297       ArLog::log(ArLog::Normal, 
00298                  "%s: Activating instead of %s because of local joystick", 
00299                  ArServerMode::getActiveMode()->getName(),
00300                  myName.c_str());
00301     else
00302       ArLog::log(ArLog::Normal, 
00303                  "%s: Activating because of local joystick",
00304                  myName.c_str());
00305     activate();
00306   }
00307 }
00308 
00309 AREXPORT void ArServerModeRatioDrive::userTask(void)
00310 {
00311   // Sets the robot so that we always thing we're trying to move in
00312   // this mode
00313   myRobot->forceTryingToMove();
00314   
00315   // if the joystick is pushed then set that we're active, server
00316   // commands'll go into ratioDrive and set it there too
00317   if ((myUseComputerJoystick && myJoyHandler->haveJoystick() && 
00318        myJoyHandler->getButton(1)) ||
00319       (myUseRobotJoystick && myRobotJoyHandler->gotData() && 
00320        myRobotJoyHandler->getButton1()))
00321   {
00322     setActivityTimeToNow();
00323   }
00324 
00325 
00326   if (!myStatusSetThisCycle)
00327   {
00328     if (myRobot->isLeftMotorStalled() || myRobot->isRightMotorStalled())
00329       myStatus = "Stalled";
00330     // this works because if the motors stalled above caught it, if
00331     // not and more values it means a stall
00332     else if (myRobot->getStallValue())
00333       myStatus = "Bumped";
00334     else if (ArMath::fabs(myRobot->getVel()) < 2 && 
00335              ArMath::fabs(myRobot->getRotVel()) < 2)
00336       myStatus = "Stopped";
00337     else
00338       myStatus = "Driving";
00339   }
00340 
00341   myStatusSetThisCycle = false;
00342 }
00343 
00344 AREXPORT void ArServerModeRatioDrive::ratioFireCallback(void)
00345 {
00346   if (myPrinting)
00347     printf("Doing %.0f %.0f %.0f\n", myTransRatio, myRotRatio, 
00348            myThrottleRatio);
00349   myRatioAction->setRatios(myTransRatio, myRotRatio, myThrottleRatio);
00350 }
00351 
00352 AREXPORT void ArServerModeRatioDrive::setUseLocationDependentDevices(
00353         bool useLocationDependentDevices, bool internal)
00354 {
00355   if (!internal)
00356     myRobot->lock();
00357   // if this is a change then print it
00358   if (useLocationDependentDevices != myUseLocationDependentDevices)
00359   {
00360     if (useLocationDependentDevices)
00361     {
00362       ArLog::log(ArLog::Normal, "%s: Using location dependent range devices",
00363                  myName.c_str());
00364     }
00365     else
00366     {
00367       ArLog::log(ArLog::Normal, 
00368                  "%s: Not using location dependent range devices",
00369                  myName.c_str());
00370     }
00371     myUseLocationDependentDevices = useLocationDependentDevices;
00372     myLimiterForward->setUseLocationDependentDevices(
00373             myUseLocationDependentDevices);
00374     myLimiterBackward->setUseLocationDependentDevices(
00375             myUseLocationDependentDevices);
00376   }
00377   if (!internal)
00378     myRobot->unlock();
00379 }
00380 
00381 AREXPORT bool ArServerModeRatioDrive::getUseLocationDependentDevices(void)
00382 {
00383   return myUseLocationDependentDevices;
00384 }
00385 
00386 
00387 
00388 

Generated on Tue Feb 20 10:51:50 2007 for ArNetworking by  doxygen 1.4.0