00001
00042 }
00043 \endcode
00044
00045
00046 If you add "catch" parenthesis in regular expression, "caught" vars are in argv.
00047
00048 In this case, the regular expression "^(.*) quitting$" will catch all message that will finish by " quitting". In argv[0] you can get the catched message juste before " quitting". argc return number of vars "catched". This is usefull only if your parameters number is not fixed. If you are not familiar with regular expressions, I recommend you to see some documentations before going further.
00049
00050 \subsection basics_micoleAgentThread MicoleAgentThread
00051 \sa MicoleAgentThread
00052 Some agents need their own thread because they work in parallel with the main program (coordinates sender agent for example). AgentsThreads are "threaded" version of Agents.
00053
00054 If you inherit MicoleAgentThread you can use two methods "start" and "run".
00055
00056 \code
00057 start();
00058 \endcode
00059
00060 This is a sample code of implementation of the run method in FF3DDeviceSenderAgent
00061
00062 \code
00063 void FF3DDeviceSenderAgent::run ()
00064 {
00065 Vec3f p = Vec3f(0,0,0);
00066 MicoleStringStream s;
00067 while(getState()==ACTIVE)
00068 {
00069 p = _FF3DCoord->get();
00070
00071 s<< "IN FF3D : pos=(" << p.x << ", "<< p.y << ", " << p.z<<");";
00072
00073 if (_buttonPress->eventPressed())
00074 s << " evt=PRESSED;";
00075
00076
00077 if (_buttonPress->eventReleased())
00078 s << " evt=RELEASED;";
00079
00080
00081 sendMessage(s.str());
00082 }
00083 ::Sleep(_delay);
00084 s.flush();
00085 }
00086 }
00087 \endcode
00088
00089 \section first_program Your first program
00090 \subsection first_program_logger LoggerAgent
00091
00092 The LoggerAgent catch all informations on the bus and write it in a log file. Learn how works the LoggerAgent is a good training course.
00093
00094 \subsection first_program_declaration Declaration
00095
00096 We decide to create "MyLoggerAgent" a quite simple Logger agent class"
00097
00098 MyLoggerAggent.h
00099 \code
00100 #ifndef MYLOGGERAGENT_H
00101 #define MYLOGGERAGENT_H
00102 #include "micolelib.h"
00103 #include "MicoleAgent.h"
00104 #include <iostream>
00105 #include <fstream>
00106 using namespace std;
00107
00111 class MyLoggerAgent: public MicoleAgent
00112 {
00113 public:
00114 MyLoggerAgent();
00115 virtual ~MyLoggerAgent();
00116 void handleAllMessage ( MicoleBus *app, int argc, const char **argv );
00117 private:
00118 ofstream _log; /**< output log file stream handler */
00119 FILE *_logFile;
00120 };
00121
00122 #endif
00123 \endcode
00124
00125 This is a classic class definition.
00126
00127 - Some include files
00128 - You inherit MicoleAgent
00129 - Default constructor, destructor
00130 - private variables for file handling
00131
00132 You can notice the handleAllMessage function prototypes. This is a "bindable" method by MicoleBus. Return type is always void and you have 3 parameters. MicoleBus (we will not take a look on this for the moment), argc (number of arguments in argv), argv: all strings catched by a regular expression. If you want to create new "bindable" method, you MUST follow this prototype.
00133 \subsection first_program_firstbind Your first bind
00134
00135 LoggerAggent bind "all information" on the bus with the regular expression "(.*)". Notice the catch parenthesis, all caracters will be put in first argument (argv[0]). All messages is logged in a log file.
00136
00137 \code
00138 #include "MyLoggerAgent.h"
00139
00140 MyLoggerAgent::MyLoggerAgent()
00141 : MicoleAgent("MyLoggerAgent", "Logger")
00142 {
00143 _log.open(s.str().c_str());
00144 bindMessage("(.*)", BUS_CALLBACK_OF(LoggerAgent, handleAllMessage));
00145 }
00146
00147 MyLoggerAgent::~LoggerAgent()
00148 {
00149 _log.close();
00150 }
00151
00152 void MyLoggerAgent::handleAllMessage ( MicoleBus *app, int argc, const char **argv )
00153 {
00154 _log << argv[0] << endl;
00155 }
00156 \endcode
00157
00158 This example is pretty short and usefull to debug Micole messages system.
00159
00160 This class already exist in Micole Architecture his name is "LoggerAgent" and I recommend you to use it to monitor your applications.
00161
00162 If you want to filter specific message, you can, for example, catch only input message with "^IN (.*)" regular expression. Prefixes choice is important if you want to filter specific messages.
00163 \section timetoplay Time to play with haptic devices
00164 \subsection timetoplay_init Intialization of you first haptic devices
00165
00166 To receive ForceFeedBack 3D Devices (device configured in reachin) you just need to instanciate
00167
00168 \code
00169 FF3DDeviceSenderAgent sa = FF3DDeviceSenderAgent(16);
00170 \endcode
00171
00172 And each 16ms you receive device coordinate on the bus. FF3DDeviceSenderAgent messages is like that
00173
00174 \code
00175 IN FF3D : pos=(-1.330810785e-003, -8.182675362e-002, -4.387708664e-002); evt=RELEASED;
00176 \endcode
00177
00178 \subsection timetoplay_helpers Use DeviceInputAgent Helpers
00179
00180 You don't need to "bind" FF3DDeviceSenderAgent messages if you inherit "FF3DDeviceInputAgent".
00181
00182 All *DeviceInputAgent are "helpers" and provide you an adapter to handle all "common" possibility of a device.
00183
00184 Each DeviceInputAgent has his own "method" to implement, following his own possibilites. FF3DDeviceInputAgent has virtuals methods onInput and onButtonPress and onButtonRelease. Methods names here are quite explicit.
00185
00186 More information in section Use haptic devices with MicoleLib
00187 \subsection timetoplay_deviceoutputagent Initialize a DeviceOuputAgent
00188
00189 To give some order to a device, you need to Instanciate a DeviceOutputAgent.
00190
00191 \code
00192 FF3DDeviceOutputAgent oa;
00193 \endcode
00194
00195 After that, you need to send specific messages that corresponding devices can understand.
00196
00197 \code
00198 MicoleStringStream ss;
00199 ss << "OUT FF3D : line=(("<<_grab.x<<", "<<_grab.y<<", "<<_grab.z<<"),("<<_position.x<<", "<<_position.y<<", "<<_position.z<<"));";
00200 sendMessage(ss.getString().c_str());
00201 \endcode
00202
00203 This is an example of a recognized message. If you want all possible messages you can see it at section : Use haptic devices with MicoleLib
00204 \subsection timetoplay_inputagentexample InputAgentExample
00205
00206 \code
00207 void InputAgentExample::onInput() {
00208 if (_recording) {
00209 _path.push_back(_position);
00210 }
00211
00212 if (_replay) {
00213
00214 Vec3f _diff = _magneticPoint - _position;
00215 if (_diff.length()<=0.025) {
00216
00217 if (_path.size() > 0) {
00218 _magneticPoint = _path.front();
00219 _path.pop_front();
00220
00221 MicoleStringStream s;
00222 s << "OUT FF3D GUIDE : point=("<<_magneticPoint.x<<", "<<_magneticPoint.y<<", "<<_magneticPoint.z<<");";
00223 FF3DDeviceInputAgent::sendMessage(s.str());
00224 } else { //no more point in path
00225 _replay = 0;
00226 FF3DDeviceInputAgent::sendMessage("OUT FF3D GUIDE : none;");
00227 FF3DDeviceInputAgent::sendMessage("OUT VTP : left=(0000000000000000);");
00228 FF3DDeviceInputAgent::sendMessage("OUT VTP : right=(0000000000000000);");
00229 }
00230 }
00231 }
00232
00233 }
00234 \endcode
00235
00236
00237 */