Tekkotsu Homepage | Demos | Overview | Downloads | Dev. Resources | Reference | Credits |
MotionHook.hGo to the documentation of this file.00001 //-*-c++-*- 00002 #ifndef INCLUDED_MotionHook_h_ 00003 #define INCLUDED_MotionHook_h_ 00004 00005 #include <cstring> 00006 #include "Shared/plist.h" 00007 #include "Shared/RobotInfo.h" 00008 #include <vector> 00009 00010 //! Interface for connections to remote hosts and hardware devices which should be polled with output values 00011 /*! 00012 * - Override motionCheck() if your hardware needs to have a value specified for every output 00013 * on every update, regardless of whether it changes. 00014 * - Override motionUpdated() if you only need to process the outputs which have changed. 00015 * 00016 * You can expect to be called every FrameTime*NumFrame milliseconds in terms of simulator time. 00017 * However, keep in mind this is relative to SharedGlobals::timeScale (Config.Speed) in terms of 00018 * wall-clock time, and is also subject to the simulator being paused, set to full-speed mode, or hitting 00019 * a breakpoint in the debugger. See enteringRealtime() and leavingRealtime() if you want updates 00020 * when the user switches simulation modes, although there's still no way to get notification if a 00021 * debugger breakpoint is hit. 00022 */ 00023 class MotionHook { 00024 public: 00025 //! used as input to updatePIDs() 00026 struct PIDUpdate { 00027 //! default constructor (unknown output, 0 pids) 00028 PIDUpdate() : idx(-1U) { pids[0]=0; pids[1]=0; pids[2]=0; } 00029 //! constructor, pass output index and pid array 00030 PIDUpdate(const std::pair<unsigned int, float[3]>& x) : idx(x.first) { memcpy(pids,x.second,sizeof(pids)); } 00031 unsigned int idx; //!< output index 00032 float pids[3]; //!< pid values 00033 }; 00034 00035 //! constructor 00036 MotionHook() : verbose(0), isFirstCheck(true) {} 00037 00038 //! no-op destructor 00039 virtual ~MotionHook() {} 00040 00041 //! Called when motion process is starting 00042 virtual void motionStarting() {} 00043 00044 //! Should return true if the MotionHook is successfully connected to physical hardware. 00045 /*! If relevant, this will only be called after motionStarting() has been called in order to 00046 * initialize a connection. 00047 * 00048 * This is used mainly to cancel out of the WaitForSensors if all MotionHooks return false. 00049 * If you are still in the process of connecting or unsure of status, be optimistic and return true. 00050 * This function will be polled at a coarse rate while blocked on sensors in case of timeouts 00051 * on the part of the MotionHook render it moot. */ 00052 virtual bool isConnected()=0; 00053 00054 //! Called each time the motion process has polled active motion commands 00055 /*! When in realtime mode, this should be called every FrameTime*NumFrames (defined in the RobotInfo) 00056 * milliseconds if running at full speed. See enteringRealtime() and leavingRealtime(). 00057 * 00058 * This default implementation checks to see which outputs have changed value since the last call and 00059 * passes the summary on to motionUpdated(). #lastOutputs will be updated with the new values @e after 00060 * the call to motionUpdated(). 00061 * 00062 * If you need to process all the outputs on every frame, you only need to override this function. 00063 * Your subclass doesn't need to call the MotionHook implementation unless you want to have 00064 * lastOutputs updated for you. 00065 * 00066 * If you only need to process the @e changed outputs for each frame, override motionUpdated() instead. 00067 * motionUpdated() is always called for each update, even if there aren't any changes, so you can still 00068 * use that if there are some outputs which need to be updated every cycle. */ 00069 virtual void motionCheck(const float outputs[][NumOutputs]) { 00070 std::vector<size_t> changedIndices; 00071 changedIndices.reserve(NumOutputs); 00072 for(size_t i=0; i<NumOutputs; ++i) { 00073 if(isFirstCheck) { 00074 changedIndices.push_back(i); 00075 } else { 00076 for(size_t j=0; j<NumFrames; ++j) { // if *any* of the frames have changed, update the output 00077 if(outputs[j][i]!=lastOutputs[i]) { // (not just checking last frame for each output) 00078 changedIndices.push_back(i); 00079 break; 00080 } 00081 } 00082 } 00083 } 00084 motionUpdated(changedIndices,outputs); 00085 for(size_t i=0; i<NumOutputs; ++i) 00086 lastOutputs[i] = outputs[NumFrames-1][i]; 00087 isFirstCheck=false; 00088 } 00089 00090 //! Called by motionCheck(), after comparing the new output values to #lastOutputs, and before lastOutputs is updated 00091 /*! Override this if you only need to send commands to the hardware for values that have changed. 00092 * This function is always called for each update, even though changedIndices might be empty. */ 00093 virtual void motionUpdated(const std::vector<size_t>& /*changedIndices*/, const float /*outputs*/[][NumOutputs]) {} 00094 00095 //! Called when PID values change 00096 virtual void updatePIDs(const std::vector<PIDUpdate>& pids) {} 00097 00098 //! Called when motion process is stopping 00099 virtual void motionStopping() { isFirstCheck=true; } 00100 00101 //! Called when the controller is going to be running in realtime mode, which is probably the normal mode you'd expect. 00102 /*! You might be in realtime mode, but a debugger breakpoint will still pause things, or thread scheduling could hiccup, so try to be robust.\n 00103 * The argument is a reference to SharedGlobals::timeScale, so the data source can subscribe to changes in 00104 * simulation speed if it can use that information. (We avoid direct dependency on the tekkotsu simulator 00105 * so this code can be reused for other tools too.) */ 00106 virtual void enteringRealtime(const plist::Primitive<double>& /*simTimeScale*/) {} 00107 00108 //! Called when leaving realtime mode, which means you have no idea when motionCheck() is going to be called in terms of wall-clock time. 00109 /*! Argument set to true if entering full speed mode, which @e may mean motionCheck will be 00110 * called at a high(er) frequency, or slower the computation is overwhelming the host hardware. 00111 * However, if false, almost certainly indicates updates will be sparse. 00112 * May be called multiple times if changing between full-speed mode and paused 00113 * 00114 * A non-realtime mode might be triggered if the user wants to pause the simulator/controller to step through something... 00115 * No guarantees though! The debugger might catch a breakpoint and stop things, and this won't be called! */ 00116 virtual void leavingRealtime(bool /*isFullSpeed*/) {} 00117 00118 //! Called by simulator thread to indicate level of verbosity for diagnostics and reporting errors 00119 virtual void setMotionHookVerbose(int v) { verbose=v; } 00120 00121 protected: 00122 //! stores current verbosity 00123 int verbose; 00124 //! set to false following the first motionCheck, reset to true by motionStopping 00125 bool isFirstCheck; 00126 //! stores the last frame of the outputs, updated by motionCheck() 00127 float lastOutputs[NumOutputs]; 00128 }; 00129 00130 /*! @file 00131 * @brief Describes MotionHook, an interface for connections to remote hosts and hardware devices which should be polled with output values 00132 * @author Ethan Tira-Thompson (ejt) (Creator) 00133 */ 00134 00135 #endif |
Tekkotsu Hardware Abstraction Layer 5.1CVS |
Generated Mon May 9 05:01:39 2016 by Doxygen 1.6.3 |