/// @file mind.hh /// @author Joshua Petitt /// @author Stefan Schmitt /// @version 1.0 /// @date 2003-07 /// /// Declares Id, Ego and SuperEgo base classes and Mind, a container for global /// data and functions and communication backbone for Id, Ego, SuperEgo. #ifndef MIND_HH #define MIND_HH #include "base/base.hh" #include "base/templates.hh" #include "behavior/behavior.hh" #include "semantic/dictionary.hh" ///@bug Workaround if using mc-5.2 #ifndef MAX_IRQ # define MAX_IRQ 16 #endif namespace EyeMind { /// Saves much typing in Mind declaration, use it in derived Minds. #define REGISTER_WITH_MIND(type, pointer) \ private: static class type* pointer; \ public: static void Register(type& r){ NullCheck(pointer, #type); pointer = &r; } \ static type* Active##type(){ return pointer; } #ifndef REACT #include "state/state.hh" /// Depth of state stack static const unsigned STATE_STACK_SIZE=1; /// A simple stack implementation based on fixed size array class MindStack { private: typedef Array StateStack; StateStack stack; public: MindStack() { } ~MindStack() { } int Push(State* s) { if(stack.Append(s)!=NULL) return -1; } State* Pop() { if(stack.Pos()>0) { return *stack--; } } }; #endif /// Container class for global data and functions; purely static, not /// instantiable. class Mind { private: NO_COPYING(Mind); ///< Prevent copying. protected: /// Default constructor; initializes data members. Mind(); /// If variable p is not NULL, panic. static void NullCheck(void* p, const char* who); public: REGISTER_WITH_MIND(Id, id); REGISTER_WITH_MIND(Ego, ego); REGISTER_WITH_MIND(SuperEgo, superego); REGISTER_WITH_MIND(VWMove, vwmove); REGISTER_WITH_MIND(VWDrive, vwdrive); REGISTER_WITH_MIND(FeelPsds, feelpsds); REGISTER_WITH_MIND(Odometry, odometry); REGISTER_WITH_MIND(Dictionary, dictionary); #ifndef REACT REGISTER_WITH_MIND(MindStack, stack); #endif }; /// Number of inputs/outputs in Id class lists. static const unsigned INTERFACE_LIST_SIZE=16; /// Number Behaviors in Id class lists. static const unsigned BEHAVIOR_LIST_SIZE=16; /// The "nerve system" of the agent. class Id { friend Updatable& operator<<(Id& id, Updatable& i); friend Updatable& operator>>(Id& id, Updatable& o); friend Behavior& operator>>(Id& id, Behavior& b); private: bool active; ///< Active flag. /// Contains handles for attached IRQ functions. static TimerHandle timer_handles[MAX_IRQ]; /// Counts attached IRQ functions. static unsigned timer_count; /// Attaches a function to the TPU. void AttachToTimer(void (*function)(), float timebase); protected: /// Array of Updatables. typedef Array Updatables; /// Array of Behaviors. typedef Array Behaviors; Updatables inputs; ///< All inputs of the id. Updatables outputs; ///< All outputs of the id. /// All root behaviors. Behaviors behaviors; public: /// Default constructor; registers with Mind. Id(); /// Virtual destructor; unregisters all IRQ functions. virtual ~Id(); /// Make the id "clear for action"; must set Active(true). /// The behavior tree should be build in this function. virtual void Ready() = 0; /// @name Attribute manipulation functions //@{ bool Active(){ return active; } ///< Set active flag; void Active(bool b){ active = b; } ///< Returns active flag; //@} /// Excite all Behaviors in behaviors list by signal. void ExciteBehaviors(int signal = ROOT_DEFAULT_EXCITE); }; /// Attach an Updatable as Input to the Id. i.Update() will be called with its /// Timebase value. Handles multiple attachment of the same object by not /// attaching it a second time. Updatable& operator<<(Id& id, Updatable& i); /// Attach an Updatable as Output to the Id. o.Update() will be called with its /// Timebase value. Handles multiple attachment of the same object by not /// attaching it a second time. Updatable& operator>>(Id& id, Updatable& o); /// Attach an Behavior to the Id. b.Excite() will be called with its /// Timebase value. Handles multiple attachment of the same object by not /// attaching it a second time. Behavior& operator>>(Id& id, Behavior& b); #ifndef REACT /// Middle layer arbitration between Id and SuperEgo. /// The Ego class contains a FIFO queue of states to achieve. /// The queue of states is dictated primarily by the SuperEgo, /// but the Ego can also modify the state list. class Ego { private: bool active; ///< Active flag. protected: States task; ///< Desired states. States past; ///< Past states. States states; ///< Current states. public: ///< Default constructor, registers with Mind. Ego(); ///< Virtual destructor. virtual ~Ego(){} /// Make the ego "clear for action"; must set Active(true). virtual void Ready() = 0; /// Main processing function. virtual void Think(); /// @name Attribute manipulation functions //@{ bool Active(){ return active; } ///< Set active flag; void Active(bool b){ active = b; } ///< Returns active flag; States& CurrentStates(){ return states; } ///< Returns current states. /// @bug This actually does nothing. void AddState(State *state){} //@} }; /// Container for high-level planning type algorithms. The SuperEgo has one /// pure virtual function, Plan(). This function should create state lists /// for the Ego to accomplish a task. class SuperEgo { private: bool active; ///< Active flag. protected: StateMemoryMap statemap; ///< Map of available states. public: ///< Default constructor, registers with Mind. SuperEgo(); ///< Virtual destructor. virtual ~SuperEgo(){} /// Make the super-ego "clear for action"; must set Active(true). virtual void Ready() = 0; /// Main processing function. virtual void Plan(); /// @name Attribute manipulation functions //@{ bool Active(){ return active; } ///< Set active flag; void Active(bool b){ active = b; } ///< Returns active flag; //@} }; #endif //REACT }; // namespace EyeMind #endif //MIND_HH