MKInterface.cpp
Go to the documentation of this file.
00001 /*
00002  * MKInterface.cpp
00003  *
00004  *  Created on: Nov 23, 2011
00005  *      Author: mriedel
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 // Battery Limits stay Hard-Coded
00017 #define BATTERY_LEVEL_EMPTY   131
00018 #define BATTERY_LEVEL_LOW     138
00019 #define BATTERY_LEVEL_CHARGED 180
00020 
00021 
00022 
00023 // TODO. Implement this nicely!!!
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         // Build conditions
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         // RobotID
00045         conditions.push_back(robotIDPacket);
00046         conditions.push_back(firmRevPacket);
00047 
00048         // try to establish connection
00049         connection = MKInterfaceConnection::findConnection(options.tSerialDeviceDirectory->getValue(),
00050                         options.tSerialDeviceNameRegex->getValue(), conditions);
00051 
00052 
00053 
00054         // Only build Interface AFTER Creating connection and only if it was found!
00055         if (connection) {
00056                 // safe Module
00057                 safeModule = new MKSafeMod(this, connection);
00058 
00059                 rosInterface = new MKROSInterface(*this, options.tUavId->getValue());
00060 
00061 
00062                 if (options.tInitialDriftEstim->getValue()) {
00063                         // perform DriftEstimation
00064                         performDriftEstim();
00065                 }
00066 
00067                 // TODO: Default Mirror is Off!
00068                 MKSingleValuePacket mirrorPacket(MKDataDefines::MIRROR_DATA_ACTIVE, MKDataDefines::MKINT_LOGICAL_OFF);
00069                 connection->setValue(mirrorPacket);
00070 
00071                 // Set Values!
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                 // Set Offsets if configured
00098                 // X
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 //                      else {
00105 //                              ROS_WARN("Successfully set OFFSET_RAW_ACC_X!");
00106 //                      }
00107                 }
00108 
00109                 // Y
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 //                      else {
00116 //                              ROS_WARN("Successfully set OFFSET_RAW_ACC_Y!");
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         //ROS_INFO("Test");
00138         safeModule->resetCmdTimer();
00139         // reset Timer
00140         // Pointer always valid (safemod before rosinterface!)
00141         if (!safeModule->isRunning()) {
00142                 ROS_WARN("Safemodule not running. Starting...");
00143                 safeModule->start();
00144         }
00145 
00146 
00147 
00148         // Message contains metric unit data.
00149         double zeroStickValue = options.tZeroStickValue->getValue();
00150         double mass = options.tUavMass->getValue();
00151         double gravity = options.tGravity->getValue();
00152         //double gravity = arma::norm(mEnvironment->getGravity(),2);
00153 
00154 //      ROS_INFO("Gravity: %f", gravity);
00155 //      ROS_INFO("Mass: %f Estimate: %f", mass, msg->mass);
00156 //
00157 //      ROS_INFO("Roll: %f, Pitch %f, Yaw %f, Thrust %f", msg->roll, msg->pitch, msg->yaw, msg->thrust);
00158 //      ROS_INFO("ZeroStickValue: %i", zeroStickValue);
00159 
00160 
00161 
00162         double cmdThrust =  std::min(255.0,std::max(-1.0 * thrust * zeroStickValue/mass/gravity,0.0)); // numbers under LL_CMD_NUM are reserved to protocol
00163 
00164         //ROS_INFO("thrust(1): %f", cmdThrust);
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         //ROS_INFO("thrust(2): %f", cmdThrust);
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         //ROS_INFO("Raw Commands: Roll: %f, Pitch: %f, Yaw: %f, Thrust: %f", cmdRoll, cmdPitch, cmdYawRate, cmdThrust);
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         // turn off motors
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                                 // Land
00228                                 ROS_ERROR("MKInterface %d: Battery Empty! LAND NOW! Trying to initiate land!", options.tUavId->getValue());
00229                                 landRequest = true;
00230                         } else {
00231                                 // Just warn
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Friends Defines


tk_mkinterface
Author(s): Martin Riedel
autogenerated on Wed Apr 24 2013 11:29:54