Simbody  3.4 (development)
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 
00205 class SimTK_SimTKCOMMON_EXPORT EventTriggerInfo {
00206 public:
00207     EventTriggerInfo();
00208     explicit EventTriggerInfo(EventId eventId);
00209     ~EventTriggerInfo();
00210     EventTriggerInfo(const EventTriggerInfo&);
00211     EventTriggerInfo& operator=(const EventTriggerInfo&);
00212 
00213     EventId getEventId() const; // returns -1 if not set
00214     bool shouldTriggerOnRisingSignTransition()  const; // default=true
00215     bool shouldTriggerOnFallingSignTransition() const; // default=true
00216     Real getRequiredLocalizationTimeWindow()    const; // default=0.1
00217 
00218     // These return the modified 'this', like assignment operators.
00219     EventTriggerInfo& setEventId(EventId);
00220     EventTriggerInfo& setTriggerOnRisingSignTransition(bool);
00221     EventTriggerInfo& setTriggerOnFallingSignTransition(bool);
00222     EventTriggerInfo& setRequiredLocalizationTimeWindow(Real);
00223 
00224     Event::Trigger calcTransitionMask() const {
00225         unsigned mask = 0;
00226         if (shouldTriggerOnRisingSignTransition()) {
00227             mask |= Event::NegativeToPositive;
00228         }
00229         if (shouldTriggerOnFallingSignTransition()) {
00230             mask |= Event::PositiveToNegative;
00231         }
00232         return Event::Trigger(mask);
00233     }
00234 
00235     Event::Trigger calcTransitionToReport
00236        (Event::Trigger transitionSeen) const
00237     {
00238         // report -1 to 1 or 1 to -1 as appropriate
00239         if (transitionSeen & Event::Rising)
00240             return Event::NegativeToPositive;
00241         if (transitionSeen & Event::Falling)
00242             return Event::PositiveToNegative;
00243         assert(!"impossible event transition situation");
00244         return Event::NoEventTrigger;
00245     }
00246 
00247 private:
00248     class EventTriggerInfoRep;
00249 
00250     // opaque implementation for binary compatibility
00251     EventTriggerInfoRep* rep;
00252 
00253     const EventTriggerInfoRep& getRep() const {assert(rep); return *rep;}
00254     EventTriggerInfoRep&       updRep()       {assert(rep); return *rep;}
00255 };
00256 
00257 
00258 
00259 
00260 //==============================================================================
00261 //              HANDLE EVENTS OPTIONS and HANDLE EVENTS RESULTS
00262 //==============================================================================
00265 class HandleEventsOptions {
00266 public:
00267     enum Option {
00269         None            = 0x0000,
00273         DontThrow       = 0x0001,
00276         UseInfinityNorm = 0x0002
00277     };
00278 
00279 
00280     HandleEventsOptions() {clear();}
00281     explicit HandleEventsOptions(Real accuracy) 
00282     {   clear(); setAccuracy(accuracy); }
00283     explicit HandleEventsOptions(Option opt)
00284     {   clear(); setOption(opt); }
00285 
00289     HandleEventsOptions& clear() 
00290     {   optionSet=0; setAccuracyDefaults(); return *this; }
00291 
00295     HandleEventsOptions& setAccuracy(Real accuracy) {
00296         assert(accuracy > 0);
00297         requiredAccuracy = accuracy;
00298         return *this;
00299     }
00300 
00303     HandleEventsOptions& clearOption(Option opt) 
00304     {   optionSet &= ~(unsigned)opt; return *this; }
00307     HandleEventsOptions& setOption  (Option opt) 
00308     {   optionSet |= (unsigned)opt; return *this; }
00309 
00311     Real getAccuracy()       const {return requiredAccuracy;}
00312 
00313     bool isOptionSet(Option opt) const {return (optionSet&(unsigned)opt) != 0;}
00314 
00315     static Real getDefaultAccuracy() {return Real(1e-4);}
00316 
00317     // Set operators: not, or, and, set difference
00318     HandleEventsOptions& operator|=(const HandleEventsOptions& opts) 
00319     {   optionSet |= opts.optionSet; return *this; }
00320     HandleEventsOptions& operator&=(const HandleEventsOptions& opts) 
00321     {   optionSet &= opts.optionSet; return *this; }
00322     HandleEventsOptions& operator-=(const HandleEventsOptions& opts) 
00323     {   optionSet &= ~opts.optionSet; return *this; }
00324 
00325     HandleEventsOptions& operator|=(Option opt) {setOption(opt); return *this;}
00326     HandleEventsOptions& operator-=(Option opt) {clearOption(opt); return *this;}
00327 
00328 private:
00329     Real     requiredAccuracy;
00330     unsigned optionSet;
00331 
00332     void setAccuracyDefaults() {
00333         requiredAccuracy = getDefaultAccuracy();
00334     }
00335 };
00336 
00341 class HandleEventsResults {
00342 public:
00343     HandleEventsResults() : m_lowestModifiedStage(Stage::Infinity) {clear();}
00344 
00345     enum Status {
00347         Invalid                 = -1,
00350         Succeeded               = 0,
00354         ShouldTerminate         = 1,
00358         Failed                  = 2    
00359     };
00360 
00363     HandleEventsResults& clear() {
00364         m_exitStatus = Invalid;
00365         m_anyChangeMade = false;
00366         m_lowestModifiedStage = Stage::Infinity; // i.e., nothing modified
00367         m_message.clear();
00368         return *this;
00369     }
00370     bool    isValid()           const {return m_exitStatus != Invalid;}
00371     Status  getExitStatus()     const {return m_exitStatus;}
00372 
00373     bool getAnyChangeMade()     const 
00374     {   assert(isValid()); return m_anyChangeMade; }
00375     Stage getLowestModifiedStage() const 
00376     {   assert(isValid()); return m_lowestModifiedStage; }
00377     const String& getMessage() const
00378     {   assert(isValid()); return m_message; }
00379 
00380     HandleEventsResults& setExitStatus(Status status) 
00381     {   m_exitStatus=status; return *this; }
00382     HandleEventsResults& setAnyChangeMade(bool changeMade) 
00383     {   m_anyChangeMade=changeMade; return *this; }
00384     HandleEventsResults& setLowestModifiedStage(Stage stage) 
00385     {   m_lowestModifiedStage=stage; return *this; }
00386     HandleEventsResults& setMessage(const String& message) 
00387     {   m_message=message; return *this; }
00388 private:
00389     Status  m_exitStatus;
00390     bool    m_anyChangeMade;
00391     Stage   m_lowestModifiedStage;
00392     String  m_message;
00393 };
00394 
00395 } // namespace SimTK
00396 
00397 #endif // SimTK_SimTKCOMMON_EVENT_H_
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines