Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

DriverMessaging.h

Go to the documentation of this file.
00001 //-*-c++-*-
00002 #ifndef INCLUDED_DriverMessaging_h_
00003 #define INCLUDED_DriverMessaging_h_
00004 
00005 #include "Shared/plistCollections.h"
00006 #include "Shared/plistSpecialty.h"
00007 #include <string>
00008 #include <set>
00009 #include <map>
00010 
00011 //! Functions and data structures for sending messages from "user land" (behavior in Main, or motion commands in Motion) to drivers in the hardware abstraction layer
00012 /*! TODO: not implemented for non-threaded IPC, assuming shared memory space... the 'Multiprocess' mode will probably be deprecated before this matters 
00013  */
00014 namespace DriverMessaging {
00015   
00016   class Message;
00017   
00018   //! Interface for drivers to receive messages, see addListener() and removeListener()
00019   /*! We're not using the normal EventRouter system because this will be using interprocess communication, and
00020    *  don't want to deal with interprocess subscriptions for a subset of events */
00021   class Listener {
00022   public:
00023     //! destructor
00024     virtual ~Listener() {}
00025     
00026     //! callback function, will be executed in thread of original postMessage() call
00027     virtual void processDriverMessage(const Message& d)=0;
00028   };
00029   
00030   //! allows drivers to subscribe to messages
00031   void addListener(Listener* l, const char* const t);
00032   
00033   //! allows drivers to unsubscribe from messages
00034   void removeListener(Listener* l, const char* const t);
00035   
00036   //! allows drivers to unsubscribe from all messages
00037   void removeListener(Listener* l);
00038   
00039   //! returns true if any drivers are subscribed to the specified message class
00040   bool hasListener(const char* const t);
00041   
00042   //! posts a message to all subscribing drivers
00043   /*! TODO not implemented for non-threaded IPC, assuming shared memory space... the 'Multiprocess' mode will probably be deprecated before this matters */
00044   void postMessage(const Message& d);
00045   
00046   
00047   
00048   //! Base class for all driver messages, this subclasses XMLLoadSave in case we want to serialize for messages from non-threaded (full multi-process) IPC, or offboard computation
00049   /*! TODO not implemented for non-threaded IPC, assuming shared memory space... the 'Multiprocess' mode will probably be deprecated before this matters */
00050   class Message : public virtual LoadSave {
00051   protected:
00052     //! Constructor to be used by subclasses (there is no public constructor, this is an abstract class)
00053     /*! The className argument is used to initialize #CLASS_NAME, the pointer address should be static, used for fast class comparisons */
00054     explicit Message(const char* const className) : LoadSave(), CLASS_NAME(className) {}
00055     
00056   public:
00057     //! Each class should supply a name so they can be identified more easily, this is assigned via the protected constructor
00058     /*! Do we need this?  Not sure why I added this vs. using RTTI and typeinfo/typeid stuff */
00059     const char* const CLASS_NAME;
00060     
00061     //! Copy constructor
00062     Message(const Message& m) : LoadSave(), CLASS_NAME(m.CLASS_NAME) {}
00063     
00064     //! Assignment operator
00065     Message& operator=(const Message& m) { return *this; }
00066     
00067     //! Destructor
00068     virtual ~Message()=0;
00069   };
00070   
00071   
00072   //! Encodes a set of load predictions for joints so driver can offset target positions accordingly
00073   class LoadPrediction : public Message, public virtual plist::Dictionary {
00074   public:
00075     //! constructor, assign load predictions via direct access to #loads
00076     LoadPrediction() : Message(NAME), loads() {
00077       addEntry("Loads",loads);
00078       setLoadSavePolicy(FIXED,SYNC);
00079     }
00080     
00081     //! holds load predictions, mapping outputs with predictions to those predictions (don't need to supply predictions for all outputs)
00082     plist::DictionaryOf<plist::Primitive<float> > loads;
00083     static const char* const NAME; //!< class identifier
00084   };
00085   
00086   
00087   //! Indicates priority of polling outputs/buttons/sensors, for those drivers which must actively poll for sensor data
00088   class SensorPriority : public Message, public virtual plist::Dictionary {
00089   public:
00090     //! constructor
00091     SensorPriority() : Message(NAME), outputs(), buttons(), sensors() {
00092       addEntry("Outputs",outputs);
00093       addEntry("Buttons",buttons);
00094       addEntry("Sensors",sensors);
00095       setLoadSavePolicy(FIXED,SYNC);
00096     }
00097     plist::DictionaryOf<plist::Primitive<float> > outputs; //!< priority of output feedbacks
00098     plist::DictionaryOf<plist::Primitive<float> > buttons; //!< priority of button status
00099     plist::DictionaryOf<plist::Primitive<float> > sensors; //!< priority of other sensors
00100     static const char* const NAME; //!< class identifier
00101   };
00102   
00103   class ContactPoint : public virtual plist::Dictionary {
00104   public:
00105     ContactPoint() : plist::Dictionary(), frame(), point() { init(); }
00106     template<typename T> ContactPoint(unsigned int offset, const T& p) : plist::Dictionary(), frame(offset), point(p) { init(); }
00107     ContactPoint(unsigned int offset, float x, float y, float z) : plist::Dictionary(), frame(offset), point(x,y,z) { init(); }
00108     plist::OutputSelector frame;
00109     plist::Point point;
00110   protected:
00111     void init() {
00112       addEntry("Frame",frame);
00113       addEntry("Point",point);
00114       frame.setRange(0,-1U); // accept anything (i.e. reference frames are fine)
00115       setLoadSavePolicy(FIXED,SYNC);
00116     }     
00117   };
00118   
00119   //! For simulation purposes, notifies visualizer to hold the specified points fixed relative to the world, and move the base frame instead
00120   class FixedPoints : public Message, public virtual plist::ArrayOf<ContactPoint> {
00121   public:
00122     //! constructor, use addEntry()/setEntry() to manage points
00123     FixedPoints() : Message(NAME), flushOnMotionUpdate(true) { setLoadSavePolicy(SYNC,SYNC); }
00124     
00125     //! set the fixed point for a reference frame (convenience function to convert to a DriverMessaging::Point)
00126     template<typename T> void addEntry(unsigned int frame, const T& p) {
00127       addEntry(new ContactPoint(frame, p));
00128     }
00129     //! set the fixed point for a reference frame (convenience function to convert to a DriverMessaging::Point)
00130     void addEntry(unsigned int frame, float x, float y, float z) {
00131       addEntry(new ContactPoint(frame, x,y,z));
00132     }
00133     using plist::ArrayOf<ContactPoint>::addEntry;
00134     
00135     bool flushOnMotionUpdate; //!< if true (the default), the points are synced to the @e next motion update, instead of being applied immediately
00136     static const char* const NAME; //!< class identifier
00137   };
00138 };
00139 
00140 /*! @file
00141  * @brief 
00142  * @author Ethan Tira-Thompson (ejt) (Creator)
00143  */
00144 
00145 #endif

Tekkotsu v5.1CVS
Generated Mon May 9 04:58:37 2016 by Doxygen 1.6.3