File: ArServerMode.h

package info (click to toggle)
libaria 2.8.0%2Brepack-1
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 13,628 kB
  • ctags: 16,574
  • sloc: cpp: 135,490; makefile: 925; python: 597; java: 570; ansic: 182
file content (252 lines) | stat: -rw-r--r-- 11,092 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
#ifndef ARSERVERMODE_H
#define ARSERVERMODE_H

#include "Aria.h"
#include "ArServerBase.h"

class ArServerModeIdle;
class ArServerClient;

/// A mode for controlling the robot (only one active)

/**
   This is a lot like ArMode but for net control instead...

   Only one mode can control the robot at once, this is made to be
   subclassed.  Each subclass needs to implement activate and
   deactivate, activate MUST call baseActivate and if baseActivate
   returns false then the mode is NOT active and shouldn't do
   anything.  Further each class should set myMode and myStatus to the
   mode its in and the things its doing... You can lock your mode in
   with lockMode and unlock it with unlockMode but you should redefine
   the inherited requestUnlock and unlock yourself and deactivate
   gracefully.  

   If you want to implement a server mode as a default mode then you also
   need to implement checkDefault which will be called when nothing
   else is active

   Note that there's a new mechanism in place where if you use
   addModeData instead of addData on the ArServerBase the command will
   be placed into a map of available modes with commands that can be
   gotten by the client.  The active mode and whether its locked and
   will unlock and such can now be gotten too... this is all so that
   different commands can be disabled in client GUIs when they aren't
   available.
**/
class ArServerMode
{
public:
  /// Constructor
  AREXPORT ArServerMode(ArRobot *robot, ArServerBase *server, const char *name);
  /// Destructor
  AREXPORT virtual ~ArServerMode();
  /// This function should return the action group this mode uses
  AREXPORT virtual ArActionGroup *getActionGroup(void) { return NULL; }
  /** The function called when the mode is activated. Subclasses must implement
    * this, but also call baseActivate().-
    */
  AREXPORT virtual void activate(void) = 0;
  /** The function called when the mode is deactivated. Subclasses must
   * implement this, and also call baseDeactivate().
   */
  AREXPORT virtual void deactivate(void) = 0;
  /// The function called if the mode is not activated because another mode superceded it.
  AREXPORT virtual void activationDenied(void) {}

  /// The ArMode's user task, don't need one, subclass must provide if needed
  AREXPORT virtual void userTask(void) {}
  /// This will be called if another mode wants the lock broken (can ignore)
  AREXPORT virtual void requestUnlock(void) { }
  /// This will be called if another mode has to break the lock
  AREXPORT virtual void forceUnlock(void);
  /// Locks this mode in until its unlocked (mode must be the active mode)
  AREXPORT void lockMode(bool willUnlockIfRequested = false);
  /// Unlocks the mode so other modes can activate
  AREXPORT void unlockMode(void);      
  /// Gets a string representing the mode we're in
  AREXPORT const char *getMode(void) const { return myMode.c_str(); }
  /// Gets a string representing the status of the mode we're in
  AREXPORT const char *getStatus(void) const { return myStatus.c_str(); }
  /// Gets a string representing the extended status of the mode we're
  /// in
  AREXPORT const char *getExtendedStatus(void) const { return myExtendedStatus.c_str(); }
  /// Gets the active mode string
  AREXPORT static const char *getActiveModeModeString(void);
  /// Gets the active status string
  AREXPORT static const char *getActiveModeStatusString(void);
  /// Gets the active extended status string
  AREXPORT static const char *getActiveModeExtendedStatusString(void);
  /// Gets the name of the mode we're in
  AREXPORT const char *getName(void) const { return myName.c_str(); }
  /// Gets if this mode is active or not
  AREXPORT bool isActive(void) const { return myIsActive; }
  /// Gets if the active mode is locked or not 
  AREXPORT static bool isLocked(void);
  /// Gets whether we'll unlock if requested or not
  AREXPORT static bool willUnlockIfRequested(void);
  /// Gets the active mode
  AREXPORT static ArServerMode *getActiveMode(void);
  /// Gets if we've set our activity time
  AREXPORT bool hasSetActivityTime(void) { return myHasSetActivityTime; }
  /// Gets the time of our last activity 
  AREXPORT ArTime getActivityTime(void);
  /// Sets that we're active right now
  AREXPORT void setActivityTimeToNow(void);
  /// Gets the seconds since the activity of our active mode
  AREXPORT static int getActiveModeActivityTimeSecSince(void);
  /// Gets if the active mode set the activity time this cycle or not 
  AREXPORT static bool getActiveModeSetActivityThisCycle(void);
  /// Sets this mode to default (so if a mode deactivates it activates this)
  AREXPORT void addAsDefaultMode(ArListPos::Pos pos = ArListPos::LAST);
  /// Sees if this wants to become the default mode
  /**
     This will be called when there would be no other modes, if this
     mode wants to take over it should activate itself, if it doesn't
     want to take over it shouldn't activate
   **/
  AREXPORT virtual void checkDefault(void) {}
  /// This should only be used by careful people and probably not then
  AREXPORT void setMode(const char *str) { myMode = str; }
  /// This should only be used by careful people and probably not then
  /**
     This changes the status of the mode and sets the
     myStatusSetThisCycle to true.  If the mode inheriting is setting
     the status in cycles then it should use this status instead and
     then clear the myStatusSetThisFlag to false.
   **/
  AREXPORT void setStatus(const char *str) 
    { myStatus = str; myStatusSetThisCycle = true; }
  /// Adds data to the list of this mode's commands
  
 
  /// Returns whether the mode should be automatically resumed after it was interrupted
  /**
   * This method primarily applies when the mode has been interrupted by a 
   * forced docking situation.  In that case, when the docking mode is complete,
   * it will resume the interrupted mode -- if this method returns true.  This
   * would primarily be applicable to very long, complex modes.
   *
   * The default return value is false.
  **/
  AREXPORT virtual bool isAutoResumeAfterInterrupt();
 

  AREXPORT bool addModeData(
	  const char *name, const char *description,
	  ArFunctor2<ArServerClient *, ArNetPacket *> *functor,
	  const char *argumentDescription, const char *returnDescription,
	  const char *commandGroup = NULL, const char *dataFlags = NULL);
  /// Gets the list of data for each mode
  AREXPORT static void getModeDataList(ArServerClient *client, 
				       ArNetPacket *packet);
  /// Gets the info about which mode is active and such
  AREXPORT static void getModeInfo(ArServerClient *client, 
				   ArNetPacket *packet);
  /// Handles the packet request for the mode busy state.
  AREXPORT static void getModeBusy(ArServerClient *client,
                                   ArNetPacket *packet);
  
  /// Adds a callback for when this class is activated
  void addActivateCallback(
	  ArFunctor *functor, int position = 50) 
    { myActivateCallbacks.addCallback(functor, position); }
  /// Removes a callback for when this class is activated
  void remActivateCallback(ArFunctor *functor)
    { myActivateCallbacks.remCallback(functor); }
  /// Adds a callback for when this class is deactivated
  void addDeactivateCallback(
	  ArFunctor *functor, int position = 50) 
    { myDeactivateCallbacks.addCallback(functor, position); }
  /// Removes a callback for when this class is deactivated
  void remDeactivateCallback(ArFunctor *functor)
    { myDeactivateCallbacks.remCallback(functor); }

  /// Adds a single shot callback for when this class is deactivated
  void addSingleShotDeactivateCallback(
	  ArFunctor *functor, int position = 50) 
    { mySingleShotDeactivateCallbacks.addCallback(functor, position); }
  /// Removes a single shot callback for when this class is deactivated
  void remSingleShotDeactivateCallback(ArFunctor *functor)
    { mySingleShotDeactivateCallbacks.remCallback(functor); }

  /// Call that gets our idle mode
  AREXPORT static ArServerModeIdle *getIdleMode(void);
protected:
  AREXPORT static void modeUserTask(void);
  AREXPORT static void buildModeInfoPacket(ArNetPacket *packet);
  AREXPORT static std::list<ArServerMode *> *getRequestedActivateModes(void);
  AREXPORT void checkBroadcastModeInfoPacket(void);
  /** Activates this mode if it can (returns true if it can, false otherwise).
      If we have an ArRobot instance (myRobot), then robot motion is stopped.
      Activity time is reset, and activate callbacks are called.
  */
  AREXPORT bool baseActivate(void);
  /** Deactivates this mode. Deactivation callbacks are called. The next mode to
      be activated is activated, if any. (E.g. the global default mode)
  */
  AREXPORT void baseDeactivate(void);

  ArCallbackList myActivateCallbacks;
  ArCallbackList myDeactivateCallbacks;
  ArCallbackList mySingleShotDeactivateCallbacks;

  bool myIsActive;
  ArRobot *myRobot;
  ArServerBase *myServer;
  std::string myName;
  // inheritors will want to play with these two strings as they are
  // what is shown to the user
  std::string myMode;
  std::string myStatus;
  bool myStatusSetThisCycle;
  std::string myExtendedStatus;

  // variables for activity time (so we can do things if idle) this
  // isn't static so that each mode can have its own
  // 'myHasSetActivityTime' so that if a mode doesn't use this scheme
  // it doesn't get tromped on
  bool myHasSetActivityTime;
  bool mySetActivityThisCycle;
  ArTime myActivityTime;
  ArMutex myActivityTimeMutex;
  
  AREXPORT static bool ourActiveModeLocked;
  AREXPORT static bool ourActiveModeWillUnlockIfRequested;
  AREXPORT static ArServerMode *ourActiveMode;
  AREXPORT static ArServerMode *ourNextActiveMode;
  AREXPORT static ArServerMode *ourLastActiveMode;
  AREXPORT static bool ourActiveModeSetActivityThisCycle;

  AREXPORT ArServerMode *getLastActiveMode();

  AREXPORT static bool ourIsBusy;
  AREXPORT static ArServerBase *ourServerBase;

  AREXPORT static std::list<ArServerMode *> ourModes;
  AREXPORT static std::list<ArServerMode *> ourDefaultModes;
  AREXPORT static std::list<ArServerMode *> ourRequestedActivateModes;
  AREXPORT static std::multimap<std::string, std::string> ourModeDataMap;
  AREXPORT static ArMutex ourModeDataMapMutex;
  
  AREXPORT static ArGlobalFunctor2<ArServerClient *, 
				   ArNetPacket *> ourGetModeDataListCB;
  AREXPORT static ArGlobalFunctor2<ArServerClient *, 
				   ArNetPacket *> ourGetModeInfoCB;
  AREXPORT static ArGlobalFunctor2<ArServerClient *, 
				   ArNetPacket *> ourGetModeBusyCB;

  AREXPORT static bool ourBroadcastActiveModeLocked;
  AREXPORT static ArServerMode *ourBroadcastActiveMode;
  AREXPORT static bool ourBroadcastActiveModeWillUnlockIfRequested;
  AREXPORT static ArGlobalFunctor ourUserTaskCB;    
  AREXPORT static bool ourUserTaskAdded;  
  // so we can easily just get the verbose out of this one
  ArLog::LogLevel myVerboseLogLevel;

  AREXPORT static ArServerModeIdle *ourIdleMode;
  AREXPORT static ArMutex ourIdleModeMutex;
  AREXPORT static bool ourIdleModeCreated;
};

#endif // ARSERVERMODE_H