Go to the documentation of this file.00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 #include <tk_mkinterface/MKInterface.hpp>
00009 
00010 #include <tk_mkinterface/MKCalibrator.hpp>
00011 
00012 #define MIN_THRUST_CMD 28 // 8 + 20 (delta_trust in SaturateMotors())
00013 #define MAX_THRUST_CMD 210 // 230 - 20 (delta_trust in SaturateMotors())
00014 #define PITCH_ROLL_CMD_DEG_SCALE 4.0
00015 
00016 
00017 #define BATTERY_LEVEL_EMPTY   131
00018 #define BATTERY_LEVEL_LOW     138
00019 #define BATTERY_LEVEL_CHARGED 180
00020 
00021 
00022 
00023 
00024 #define INIT_ATTITUDE_PROP_GAIN 3.0
00025 #define INIT_ATTITUDE_DERIV_GAIN 4.0
00026 #define INIT_ATTITUDE_INTEG_GAIN 0.0
00027 
00028 #define INIT_YAW_RATE_GAIN 30.0
00029 #define INIT_YAW_ACC_GAIN 20.0
00030 
00031 #define INIT_ATTITUDE_GAIN_MULT 1.0
00032 
00033 namespace TELEKYB_NAMESPACE {
00034 
00035 MKInterface::MKInterface()
00036         : safeModule(NULL), connection(NULL), rosInterface(NULL)
00037 {
00038         
00039         std::vector<MKSingleValuePacket> conditions;
00040 
00041         MKSingleValuePacket robotIDPacket(MKDataDefines::ROBOT_ID, options.tUavId->getValue());
00042         MKSingleValuePacket firmRevPacket(MKDataDefines::FIRMWARE_REVISION, options.tUavFirmware->getValue());
00043 
00044         
00045         conditions.push_back(robotIDPacket);
00046         conditions.push_back(firmRevPacket);
00047 
00048         
00049         connection = MKInterfaceConnection::findConnection(options.tSerialDeviceDirectory->getValue(),
00050                         options.tSerialDeviceNameRegex->getValue(), conditions);
00051 
00052 
00053 
00054         
00055         if (connection) {
00056                 
00057                 safeModule = new MKSafeMod(this, connection);
00058 
00059                 rosInterface = new MKROSInterface(*this, options.tUavId->getValue());
00060 
00061 
00062                 if (options.tInitialDriftEstim->getValue()) {
00063                         
00064                         performDriftEstim();
00065                 }
00066 
00067                 
00068                 MKSingleValuePacket mirrorPacket(MKDataDefines::MIRROR_DATA_ACTIVE, MKDataDefines::MKINT_LOGICAL_OFF);
00069                 connection->setValue(mirrorPacket);
00070 
00071                 
00072                 if (!connection->setValue(MKSingleValuePacket(MKDataDefines::YAW_CTRL_TYPE, 1))) {
00073                         ROS_ERROR("Could not set YAW_CTRL_TYPE!");
00074                 }
00075 
00076                 if (!connection->setValue(MKSingleValuePacket(
00077                                 MKDataDefines::PROP_GAIN, (MKInt)(INIT_ATTITUDE_PROP_GAIN * INIT_ATTITUDE_GAIN_MULT)))) {
00078                         ROS_ERROR("Could not set PROP_GAIN!");
00079                 }
00080                 if (!connection->setValue(MKSingleValuePacket(
00081                                 MKDataDefines::DERIV_GAIN, (MKInt) (INIT_ATTITUDE_DERIV_GAIN * INIT_ATTITUDE_GAIN_MULT)))) {
00082                         ROS_ERROR("Could not set DERIV_GAIN!");
00083                 }
00084                 if (!connection->setValue(MKSingleValuePacket(
00085                                 MKDataDefines::INTEG_GAIN, (MKInt) (INIT_ATTITUDE_INTEG_GAIN * INIT_ATTITUDE_GAIN_MULT)))) {
00086                         ROS_ERROR("Could not set INTEG_GAIN!");
00087                 }
00088                 if (!connection->setValue(MKSingleValuePacket(
00089                                 MKDataDefines::YAW_RATE_GAIN, (MKInt) (INIT_YAW_RATE_GAIN * INIT_ATTITUDE_GAIN_MULT)))) {
00090                         ROS_ERROR("Could not set YAW_RATE_GAIN!");
00091                 }
00092                 if (!connection->setValue(MKSingleValuePacket(
00093                                 MKDataDefines::YAW_ACC_GAIN, (MKInt) (INIT_YAW_ACC_GAIN * INIT_ATTITUDE_GAIN_MULT)))) {
00094                         ROS_ERROR("Could not set YAW_ACC_GAIN!");
00095                 }
00096 
00097                 
00098                 
00099                 if (!options.tUavOffsetRawAccX->isOnInitialValue()) {
00100                         if (!connection->setValue(MKSingleValuePacket(
00101                                         MKDataDefines::OFFSET_RAW_ACC_X, (MKInt) (options.tUavOffsetRawAccX->getValue())))) {
00102                                 ROS_ERROR("Could not set OFFSET_RAW_ACC_X!");
00103                         }
00104 
00105 
00106 
00107                 }
00108 
00109                 
00110                 if (!options.tUavOffsetRawAccY->isOnInitialValue()) {
00111                         if (!connection->setValue(MKSingleValuePacket(
00112                                         MKDataDefines::OFFSET_RAW_ACC_Y, (MKInt) (options.tUavOffsetRawAccY->getValue())))) {
00113                                 ROS_ERROR("Could not set OFFSET_RAW_ACC_Y!");
00114                         }
00115 
00116 
00117 
00118                 }
00119 
00120                 rosInterface->activateCommandsCB();
00121         }
00122 }
00123 
00124 MKInterface::~MKInterface()
00125 {
00126         if (safeModule) { delete safeModule; }
00127         if (rosInterface) { delete rosInterface; }
00128 }
00129 
00130 bool MKInterface::hasConnection() const
00131 {
00132         return (connection != NULL);
00133 }
00134 
00135 void MKInterface::handleCommand(double estMass, double pitch, double roll, double yawrate, double thrust)
00136 {
00137         
00138         safeModule->resetCmdTimer();
00139         
00140         
00141         if (!safeModule->isRunning()) {
00142                 ROS_WARN("Safemodule not running. Starting...");
00143                 safeModule->start();
00144         }
00145 
00146 
00147 
00148         
00149         double zeroStickValue = options.tZeroStickValue->getValue();
00150         double mass = options.tUavMass->getValue();
00151         double gravity = options.tGravity->getValue();
00152         
00153 
00154 
00155 
00156 
00157 
00158 
00159 
00160 
00161 
00162         double cmdThrust =  std::min(255.0,std::max(-1.0 * thrust * zeroStickValue/mass/gravity,0.0)); 
00163 
00164         
00165 
00166         double hoveringCmd = estMass*zeroStickValue/mass;
00167         double semiDim =  std::min(fabs(MAX_THRUST_CMD - hoveringCmd),fabs(hoveringCmd - MIN_THRUST_CMD));
00168         cmdThrust = std::min(std::max(hoveringCmd - semiDim,cmdThrust),hoveringCmd + semiDim);
00169         
00170 
00171         double cmdPitch = std::min(127.0,std::max(-127.0,pitch*180/M_PI*PITCH_ROLL_CMD_DEG_SCALE));
00172         double cmdRoll = std::min(127.0,std::max(-127.0,roll*180/M_PI*PITCH_ROLL_CMD_DEG_SCALE));
00173         double cmdYawRate = std::min(127.0, std::max(-127.0,yawrate*180/M_PI));
00174 
00175 
00176         MKCommandsPacket commands;
00177         commands.pitch = (MKChar)cmdPitch;
00178         commands.roll = (MKChar)cmdRoll;
00179         commands.yawrate = (MKChar)cmdYawRate;
00180         commands.thrust = (MKChar)cmdThrust;
00181 
00182         
00183 
00184         connection->sendCommand(commands);
00185 }
00186 
00187 MKInterfaceConnection* MKInterface::getConnection() const
00188 {
00189         return connection;
00190 }
00191 
00192 bool MKInterface::performDriftEstim()
00193 {
00194         if (!connection) {
00195                 ROS_ERROR("Cannot Perform Drift Estimation without a valid connection.");
00196                 return false;
00197         }
00198 
00199         MKCalibrator calibrator(connection);
00200         return calibrator.doGyroDriftEstim();
00201 }
00202 
00203 void MKInterface::safeModDidBecomeActive()
00204 {
00205         rosInterface->deActiavteCommandsCB();
00206 }
00207 
00208 void MKInterface::safeModFinished()
00209 {
00210         
00211         connection->setValue(MKSingleValuePacket(MKDataDefines::MOTOR_STATE, MotorState::Off));
00212 
00213         rosInterface->activateCommandsCB();
00214 }
00215 
00216 bool MKInterface::checkBattery(MKInt& batteryValue, bool& landRequest)
00217 {
00218         bool updateOK = false;
00219         landRequest = false;
00220         MKValue* battery = connection->getMKDataRef().getValueByID(MKDataDefines::BATT_VOLT);
00221         if (connection->updateValue(MKDataDefines::BATT_VOLT)) {
00222                 updateOK = true;
00223                 batteryValue = battery->getValue();
00224 
00225                 if (batteryValue < BATTERY_LEVEL_LOW) {
00226                         if (batteryValue < BATTERY_LEVEL_EMPTY) {
00227                                 
00228                                 ROS_ERROR("MKInterface %d: Battery Empty! LAND NOW! Trying to initiate land!", options.tUavId->getValue());
00229                                 landRequest = true;
00230                         } else {
00231                                 
00232                                 ROS_WARN("MKInterface %d: Battery Level (%d) very low. Land soon!", options.tUavId->getValue(), batteryValue);
00233                         }
00234                 }
00235         }
00236 
00237         return updateOK;
00238 }
00239 
00240 void MKInterface::setEmergency()
00241 {
00242         safeModule->setEmergency();
00243 }
00244 
00245 const MKInterfaceOptions& MKInterface::getOptions() const
00246 {
00247         return options;
00248 }
00249 
00250 }