Simbody  3.5
Event.h
Go to the documentation of this file.
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_
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines