|
Urbi SDK Remote for C++
2.7.5
|
00001 /* 00002 * Copyright (C) 2010-2011, Gostai S.A.S. 00003 * 00004 * This software is provided "as is" without warranty of any kind, 00005 * either expressed or implied, including but not limited to the 00006 * implied warranties of fitness for a particular purpose. 00007 * 00008 * See the LICENSE file for more information. 00009 */ 00010 00011 #include <libport/asio.hh> 00012 00013 #include <urbi/uobject.hh> 00014 00015 using namespace urbi; 00016 00022 class subsumption: public UObject 00023 { 00024 public: 00025 subsumption(const std::string& n); 00027 int init(UVar& target); 00031 void createTimedOverride(const std::string& varName, int level, ufloat delay); 00033 void createOverride(const std::string& varName, int level); 00035 UVar level; 00036 private: 00037 class SUVar: public UVar 00038 { 00039 public: 00040 SUVar(const std::string& obj, const std::string& var, int level, 00041 ufloat delay = 0); 00042 friend class subsumption; 00043 private: 00044 int level_; 00045 ufloat timer_; 00046 }; 00047 int onLevelChange(UVar& v); 00048 int onWrite(UVar& v); 00049 int onRead(UVar& v); 00050 void resetLevel(int oldLevel, int writeCount); 00051 UVar* target_; 00052 int writeCount_; 00053 }; 00054 00055 00056 subsumption::subsumption(const std::string& n) 00057 : UObject(n) 00058 , target_(0) 00059 , writeCount_(0) 00060 { 00061 UBindFunction(subsumption, init); 00062 } 00063 00064 int 00065 subsumption::init(UVar& target) 00066 { 00067 std::string targetName = target.get_name(); 00068 UBindVar(subsumption, level); 00069 UBindFunction(subsumption, createOverride); 00070 UBindFunction(subsumption, createTimedOverride); 00071 UNotifyChange(level, &subsumption::onLevelChange); 00072 level = 0; 00073 target_ = new UVar(targetName); 00074 createOverride("val", 0); 00075 return 0; 00076 } 00077 00078 void 00079 subsumption::createOverride(const std::string& name, int level) 00080 { 00081 createTimedOverride(name, level, 0); 00082 } 00083 00084 void 00085 subsumption::createTimedOverride(const std::string& name, int level, 00086 ufloat timer) 00087 { 00088 SUVar* v = new SUVar(__name, name, level, timer); 00089 v->setOwned(); 00090 UNotifyChange(*v, &subsumption::onWrite); 00091 UNotifyAccess(*v, &subsumption::onRead); 00092 } 00093 00094 int 00095 subsumption::onLevelChange(UVar&) 00096 { 00097 writeCount_++; 00098 return 0; 00099 } 00100 00101 int 00102 subsumption::onRead(UVar& v) 00103 { 00104 v = target_->val(); 00105 return 0; 00106 } 00107 00108 int 00109 subsumption::onWrite(UVar& v) 00110 { 00111 SUVar& sv = static_cast<SUVar&>(v); 00112 if ((int)level <= sv.level_) 00113 { 00114 *target_ = sv.val(); 00115 if (sv.timer_) 00116 { 00117 int oldLevel = level; 00118 level = sv.level_; 00119 // Keep this line after the previous one. 00120 libport::asyncCall(boost::bind(&subsumption::resetLevel, this, 00121 oldLevel, writeCount_), 00122 useconds_t(sv.timer_ * 1000000.0)); 00123 } 00124 } 00125 return 0; 00126 } 00127 00128 subsumption::SUVar::SUVar(const std::string& obj, const std::string& var, 00129 int level, ufloat delay) 00130 : UVar(obj, var) 00131 , level_(level) 00132 , timer_(delay) 00133 { 00134 } 00135 00136 void 00137 subsumption::resetLevel(int newLevel, int wc) 00138 { 00139 ctx_->lock(); 00140 // Only reset if level was not written on since first trigger. 00141 if (writeCount_ == wc) 00142 level = newLevel; 00143 ctx_->unlock(); 00144 } 00145 00146 UStart(subsumption);