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 }