Simbody
3.5
|
00001 #ifndef SimTK_SimTKCOMMON_EVENT_H_ 00002 #define SimTK_SimTKCOMMON_EVENT_H_ 00003 00004 /* -------------------------------------------------------------------------- * 00005 * Simbody(tm): SimTKcommon * 00006 * -------------------------------------------------------------------------- * 00007 * This is part of the SimTK biosimulation toolkit originating from * 00008 * Simbios, the NIH National Center for Physics-Based Simulation of * 00009 * Biological Structures at Stanford, funded under the NIH Roadmap for * 00010 * Medical Research, grant U54 GM072970. See https://simtk.org/home/simbody. * 00011 * * 00012 * Portions copyright (c) 2008-12 Stanford University and the Authors. * 00013 * Authors: Michael Sherman * 00014 * Contributors: * 00015 * * 00016 * Licensed under the Apache License, Version 2.0 (the "License"); you may * 00017 * not use this file except in compliance with the License. You may obtain a * 00018 * copy of the License at http://www.apache.org/licenses/LICENSE-2.0. * 00019 * * 00020 * Unless required by applicable law or agreed to in writing, software * 00021 * distributed under the License is distributed on an "AS IS" BASIS, * 00022 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * 00023 * See the License for the specific language governing permissions and * 00024 * limitations under the License. * 00025 * -------------------------------------------------------------------------- */ 00026 00032 #include "SimTKcommon/basics.h" 00033 00034 namespace SimTK { 00035 00039 SimTK_DEFINE_UNIQUE_INDEX_TYPE(EventId); 00040 00047 SimTK_DEFINE_UNIQUE_INDEX_TYPE(SystemEventTriggerIndex); 00048 00057 SimTK_DEFINE_UNIQUE_INDEX_TYPE(SystemEventTriggerByStageIndex); 00058 00062 SimTK_DEFINE_UNIQUE_INDEX_TYPE(EventTriggerByStageIndex); 00063 00076 class Event { 00077 public: 00078 00123 class Cause { 00124 public: 00125 enum Num { 00126 Initialization = 1, 00127 Triggered = 2, 00128 Scheduled = 3, 00129 TimeAdvanced = 4, 00130 Signaled = 5, 00131 Termination = 6, 00132 Invalid = -1 00133 }; 00134 00135 Cause() : value(Invalid) {} 00136 Cause(Num n) : value(n) {} // implicit conversion 00137 operator Num() const {return value;} // implicit conversion 00138 Cause& operator=(Num n) {value=n; return *this;} 00139 00140 bool isValid() const {return Initialization<=value && value<=Termination;} 00141 00142 private: 00143 Num value; 00144 }; 00145 00148 SimTK_SimTKCOMMON_EXPORT static const char* getCauseName(Cause); 00149 00150 00155 enum Trigger { 00156 NoEventTrigger =0x0000, // must be 0 00157 00158 PositiveToNegative =0x0001, // 1 00159 NegativeToPositive =0x0002, // 2 00160 00161 Falling =(PositiveToNegative), // 1 00162 Rising =(NegativeToPositive), // 2 00163 AnySignChange =(PositiveToNegative|NegativeToPositive) // 3 00164 }; 00165 00168 SimTK_SimTKCOMMON_EXPORT static std::string eventTriggerString(Trigger); 00169 00170 00174 static Trigger classifyTransition(int before, int after) { 00175 if (before==after) 00176 return NoEventTrigger; 00177 if (before==0) 00178 return NoEventTrigger; // Do not report transitions away from zero. 00179 if (before==1) 00180 return PositiveToNegative; 00181 // before==-1 00182 return NegativeToPositive; 00183 } 00184 00188 static Trigger maskTransition(Trigger transition, Trigger mask) { 00189 // we're depending on NoEventTrigger==0 00190 return Trigger(transition & mask); 00191 } 00192 00193 private: 00194 }; 00195 00196 00206 class SimTK_SimTKCOMMON_EXPORT EventTriggerInfo { 00207 public: 00208 EventTriggerInfo(); 00209 explicit EventTriggerInfo(EventId eventId); 00210 ~EventTriggerInfo(); 00211 EventTriggerInfo(const EventTriggerInfo&); 00212 EventTriggerInfo& operator=(const EventTriggerInfo&); 00213 00214 EventId getEventId() const; // returns -1 if not set 00215 bool shouldTriggerOnRisingSignTransition() const; // default=true 00216 bool shouldTriggerOnFallingSignTransition() const; // default=true 00217 Real getRequiredLocalizationTimeWindow() const; // default=0.1 00218 00219 // These return the modified 'this', like assignment operators. 00220 EventTriggerInfo& setEventId(EventId); 00221 EventTriggerInfo& setTriggerOnRisingSignTransition(bool); 00222 EventTriggerInfo& setTriggerOnFallingSignTransition(bool); 00223 EventTriggerInfo& setRequiredLocalizationTimeWindow(Real); 00224 00225 Event::Trigger calcTransitionMask() const { 00226 unsigned mask = 0; 00227 if (shouldTriggerOnRisingSignTransition()) { 00228 mask |= Event::NegativeToPositive; 00229 } 00230 if (shouldTriggerOnFallingSignTransition()) { 00231 mask |= Event::PositiveToNegative; 00232 } 00233 return Event::Trigger(mask); 00234 } 00235 00236 Event::Trigger calcTransitionToReport 00237 (Event::Trigger transitionSeen) const 00238 { 00239 // report -1 to 1 or 1 to -1 as appropriate 00240 if (transitionSeen & Event::Rising) 00241 return Event::NegativeToPositive; 00242 if (transitionSeen & Event::Falling) 00243 return Event::PositiveToNegative; 00244 assert(!"impossible event transition situation"); 00245 return Event::NoEventTrigger; 00246 } 00247 00248 private: 00249 class EventTriggerInfoRep; 00250 00251 // opaque implementation for binary compatibility 00252 EventTriggerInfoRep* rep; 00253 00254 const EventTriggerInfoRep& getRep() const {assert(rep); return *rep;} 00255 EventTriggerInfoRep& updRep() {assert(rep); return *rep;} 00256 }; 00257 00258 00259 00260 00261 //============================================================================== 00262 // HANDLE EVENTS OPTIONS and HANDLE EVENTS RESULTS 00263 //============================================================================== 00266 class HandleEventsOptions { 00267 public: 00268 enum Option { 00270 None = 0x0000, 00274 DontThrow = 0x0001, 00277 UseInfinityNorm = 0x0002 00278 }; 00279 00280 00281 HandleEventsOptions() {clear();} 00282 explicit HandleEventsOptions(Real accuracy) 00283 { clear(); setAccuracy(accuracy); } 00284 explicit HandleEventsOptions(Option opt) 00285 { clear(); setOption(opt); } 00286 00290 HandleEventsOptions& clear() 00291 { optionSet=0; setAccuracyDefaults(); return *this; } 00292 00296 HandleEventsOptions& setAccuracy(Real accuracy) { 00297 assert(accuracy > 0); 00298 requiredAccuracy = accuracy; 00299 return *this; 00300 } 00301 00304 HandleEventsOptions& clearOption(Option opt) 00305 { optionSet &= ~(unsigned)opt; return *this; } 00308 HandleEventsOptions& setOption (Option opt) 00309 { optionSet |= (unsigned)opt; return *this; } 00310 00312 Real getAccuracy() const {return requiredAccuracy;} 00313 00314 bool isOptionSet(Option opt) const {return (optionSet&(unsigned)opt) != 0;} 00315 00316 static Real getDefaultAccuracy() {return Real(1e-4);} 00317 00318 // Set operators: not, or, and, set difference 00319 HandleEventsOptions& operator|=(const HandleEventsOptions& opts) 00320 { optionSet |= opts.optionSet; return *this; } 00321 HandleEventsOptions& operator&=(const HandleEventsOptions& opts) 00322 { optionSet &= opts.optionSet; return *this; } 00323 HandleEventsOptions& operator-=(const HandleEventsOptions& opts) 00324 { optionSet &= ~opts.optionSet; return *this; } 00325 00326 HandleEventsOptions& operator|=(Option opt) {setOption(opt); return *this;} 00327 HandleEventsOptions& operator-=(Option opt) {clearOption(opt); return *this;} 00328 00329 private: 00330 Real requiredAccuracy; 00331 unsigned optionSet; 00332 00333 void setAccuracyDefaults() { 00334 requiredAccuracy = getDefaultAccuracy(); 00335 } 00336 }; 00337 00342 class HandleEventsResults { 00343 public: 00344 HandleEventsResults() : m_lowestModifiedStage(Stage::Infinity) {clear();} 00345 00346 enum Status { 00348 Invalid = -1, 00351 Succeeded = 0, 00355 ShouldTerminate = 1, 00359 Failed = 2 00360 }; 00361 00364 HandleEventsResults& clear() { 00365 m_exitStatus = Invalid; 00366 m_anyChangeMade = false; 00367 m_lowestModifiedStage = Stage::Infinity; // i.e., nothing modified 00368 m_message.clear(); 00369 return *this; 00370 } 00371 bool isValid() const {return m_exitStatus != Invalid;} 00372 Status getExitStatus() const {return m_exitStatus;} 00373 00374 bool getAnyChangeMade() const 00375 { assert(isValid()); return m_anyChangeMade; } 00376 Stage getLowestModifiedStage() const 00377 { assert(isValid()); return m_lowestModifiedStage; } 00378 const String& getMessage() const 00379 { assert(isValid()); return m_message; } 00380 00381 HandleEventsResults& setExitStatus(Status status) 00382 { m_exitStatus=status; return *this; } 00383 HandleEventsResults& setAnyChangeMade(bool changeMade) 00384 { m_anyChangeMade=changeMade; return *this; } 00385 HandleEventsResults& setLowestModifiedStage(Stage stage) 00386 { m_lowestModifiedStage=stage; return *this; } 00387 HandleEventsResults& setMessage(const String& message) 00388 { m_message=message; return *this; } 00389 private: 00390 Status m_exitStatus; 00391 bool m_anyChangeMade; 00392 Stage m_lowestModifiedStage; 00393 String m_message; 00394 }; 00395 00396 } // namespace SimTK 00397 00398 #endif // SimTK_SimTKCOMMON_EVENT_H_