Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008 #include <tk_mkinterface/MKSafeMod.hpp>
00009
00010 #define THREAD_SLEEP_TIME_US 10000 // 10ms
00011
00012 namespace TELEKYB_NAMESPACE {
00013
00014 MKSafeModOptions::MKSafeModOptions()
00015 : OptionContainer("MKSafeMod")
00016 {
00017 tCmdTimeoutUs = addBoundsOption<int>("tCmdTimeoutUs",
00018 "Specifies the Commands Timeout (in us) for the Safe Module to become active.",
00019 400000, 10000, 500000, false, false);
00020 tEmergLandThrust = addBoundsOption<int>("tEmergLandThrust",
00021 "LL Emergency Landing Thrust Command To UAV",
00022 74, 60, 90, false, true);
00023
00024 tEmergLandDuration = addBoundsOption<double>("tEmergLandDuration",
00025 "Time spend in Emergency State",
00026 2.3, 1.0, 10.0, false, true);
00027 tEmergLandFreq = addBoundsOption<int>("tEmergLandFreq",
00028 "Frequency of the Landing Commands",
00029 120, 50, 240, false, true);
00030
00031
00032
00033 }
00034
00035 MKSafeMod::MKSafeMod(MKSafeModDeleagte* delegate_, MKInterfaceConnection* connection_)
00036 : connection(connection_), active(false), delegate(delegate_), mkSafeModThread(NULL), emergencyLandingRequest(false)
00037 {
00038
00039 }
00040
00041 MKSafeMod::~MKSafeMod()
00042 {
00043 if (mkSafeModThread) {
00044 stopThread();
00045 }
00046 }
00047
00048 void MKSafeMod::safeModFcn()
00049 {
00050 active = true;
00051 delegate->safeModDidBecomeActive();
00052
00053 MKCommandsPacket commands;
00054 commands.thrust = options.tEmergLandThrust->getValue();
00055
00056 Timer emergLandTimer;
00057 Time sleepTimer( 1.0 / (double)options.tEmergLandFreq->getValue() );
00058
00059 while(emergLandTimer.getElapsed().toDSec() < options.tEmergLandDuration->getValue()) {
00060 connection->sendCommand(commands);
00061 sleepTimer.sleep();
00062 }
00063
00064 active = false;
00065 delegate->safeModFinished();
00066 }
00067
00068 void MKSafeMod::threadFcn()
00069 {
00070 Time sleepTime(0,THREAD_SLEEP_TIME_US);
00071 while(!threadStopRequest) {
00072
00073
00074 bool emergency = false;
00075 if (emergencyLandingRequest) {
00076 ROS_ERROR("Emergency Landing Request received!");
00077 emergency = true;
00078 }
00079
00080 if (cmdTimer.getElapsed() > Time(0,options.tCmdTimeoutUs->getValue())) {
00081 ROS_ERROR("Emergency! command Timeout too big! Elapsed: %f", cmdTimer.getElapsed().toDSec());
00082 emergency = true;
00083 }
00084
00085 if (emergency) {
00086 ROS_ERROR("Emergency Situation found!");
00087 if (emergencyLandingRequest) {
00088 ROS_ERROR("EmergencyRequest: true");
00089 } else {
00090 ROS_ERROR("EmergencyRequest: false");
00091 }
00092 ROS_ERROR_STREAM("Timer: " << cmdTimer.getElapsed().toString());
00093
00094 emergencyLandingRequest = false;
00095 safeModFcn();
00096
00097 }
00098
00099
00100 sleepTime.sleep();
00101 }
00102 }
00103
00104 void MKSafeMod::startThread()
00105 {
00106 if (!mkSafeModThread) {
00107 threadStopRequest = false;
00108 mkSafeModThread = new boost::thread(&MKSafeMod::threadFcn, this);
00109 } else {
00110 ROS_WARN("Trying to start MKSafeModThread, but it's already active!");
00111 }
00112
00113 }
00114
00115 void MKSafeMod::stopThread()
00116 {
00117 if (mkSafeModThread) {
00118 threadStopRequest = true;
00119 mkSafeModThread->join();
00120 delete mkSafeModThread;
00121 mkSafeModThread = NULL;
00122 } else {
00123 ROS_WARN("Trying to stop MKSafeModThread, but it does not exist!");
00124 }
00125 }
00126
00127 void MKSafeMod::start()
00128 {
00129 startThread();
00130 }
00131
00132 void MKSafeMod::stop()
00133 {
00134 stopThread();
00135 }
00136
00137
00138 bool MKSafeMod::isActive() const
00139 {
00140 return active;
00141 }
00142
00143 bool MKSafeMod::isRunning() const
00144 {
00145 return (mkSafeModThread != NULL);
00146 }
00147
00148 void MKSafeMod::resetCmdTimer()
00149 {
00150 cmdTimer.reset();
00151 }
00152
00153 void MKSafeMod::setEmergency()
00154 {
00155 ROS_INFO("Received Emergency Landing Request!");
00156 emergencyLandingRequest = true;
00157 }
00158
00159
00160 }