Replay: Difference between revisions
(New page: ==Introduction== Logfiles typically belong to a plugin, and often describe data from an interface (a sensor or its like). These files may further be directly - or after removing a few int...) |
|||
(10 intermediate revisions by the same user not shown) | |||
Line 19: | Line 19: | ||
1299310466.028311 0.07 0.08 3.1 | 1299310466.028311 0.07 0.08 3.1 | ||
1299310466.052313 0.05 0.04 3.1 | 1299310466.052313 0.05 0.04 3.1 | ||
# crc-check error in communication with sensor | |||
1299310466.088313 0.07 0.05 3.12 | 1299310466.088313 0.07 0.05 3.12 | ||
The | The the timestamp must be the first value in all replay files, as it is read by the replay system, this should then be followed by any value relevant for the interface for this time - all on the same line. | ||
Any line that starts with a text character - e.g. a '#' - will be ignored by the replay function. | |||
==Replay mode== | ==Replay mode== | ||
Line 30: | Line 32: | ||
The interface can then be stepped (one or more lines at a time) | The interface can then be stepped (one or more lines at a time) | ||
The | The plug-in will then insert the data (typically as if it came from the interface) | ||
All plug-in modules are connected, so that if one plug-in module is stepped one line. The replay time (the first element in any replay line) is advanced and all other plug-ins in replay mode are requested to advance to this time. | |||
The other plug-ins then advance until the next replay line has a timestamp that is ahead of this replay time. All the lines up to this time (zero or many) will be send to the plug-in - in a ''decodeReplayLine(..)'' call. | |||
Check the on-line help of plug-ins to see if they support replay. | |||
==How to use== | ==How to use== | ||
To make a plugin with replay, you must handle two keywords options in the plugin. | |||
>> myplugin replay=true | |||
>> myplugin step=1 | |||
===Handle command options=== | |||
So add something like this to your on-line help part of handleCommand method: | |||
bool myclass::handleCommand(UServerInMsg * msg, void * extra) | |||
... | |||
sendHelpStart( ... | |||
... | |||
sendText("replay=true|false Start or stop replay mode for this plug-in\n"); | |||
sendText("step = N replay N steps from replay file\n"); | |||
... | |||
sendHelpDone(); | |||
And to handle these options in the same function, something like: | |||
... | |||
bool valueBool; | |||
if (msg->tag.getAttBool("replay", &valueBool, true)) | |||
setReplay(valueBool); | |||
// replay step | |||
int valueInt; | |||
if (msg->tag.getAttInteger("step", &valueInt, 1)) | |||
replayStep(valueInt); | |||
The setReplay(bool) and replayStep(int) is already available in the plug-in and resource classes. | |||
===handle replay lines=== | |||
The replay system will call ''decodeReplayLine(char * line)'' whenever it is time to replay a new line of data. | |||
So define a method to handle the decode of line to replay, this could look something like: | |||
virtual bool decodeReplayLine(char * line) | |||
{ | |||
unsigned long int sec, usec; | |||
double x, y, z; | |||
UTime t; | |||
int n = sscanf(line, "%lu.%lu x y z", &sec, &usec, &x, &y, &z); | |||
// fake a sensor update, as if it came from the sensor itself | |||
t.setTimeU(sec, usec); | |||
sensorUpdate(t, x, y, z); | |||
} | |||
===Replay logfile name and path=== | |||
The replay must know the name of the replay file. This filename should be a reserved name for this plug-in, preferred the same name as the plug-in, with a ''.log'' extension. | |||
Set this filename in the plug-in constructor: | |||
... | |||
replaySetBaseFileName("myplugin"); | |||
... | |||
The ''.log'' extension is added, and the file must be present in the ''replayPath''. This ''replayPath'' should be set in the ''.ini'' file of the server, e.g.: | |||
... | |||
server replayPath="/home/myname/replayLogs/20110618/" | |||
... | |||
===Replay status=== | |||
If you want replay status (replay mode, replay line and replay time) as part of the global variables, then | |||
call createReplayVar(UVarPool * vp) when the remaining global variables are created. | |||
createReplayVar(getVarPool()); | |||
To test if the plug-in is in replay mode a function isReplay() is available. | |||
isReplay(); | |||
===Replay synchronize with other servers=== | |||
If the server is to synchronize the replay with other servers, then the servers must be connected with interface plug-ins. E.g. if the camera server ''ucamserver'' is to replay in sync with the laser scanner server ''ulmsserver'', then set up an interface connection between them, and set this interface in replay mode. | |||
The ''.ini'' file should include something like: | |||
== | # camsera server ini-file ucamserver.ini | ||
... | |||
# load interface to laser scanner server | |||
module load=if alias=laser | |||
laser connect=localhost:24919 | |||
laser replay | |||
.. | |||
# laser server ini-file ulmsserver.ini | |||
... | |||
# load interface to camera server | |||
module load=if alias=cam | |||
cam connect=localhost:24920 | |||
cam replay | |||
.. |
Latest revision as of 07:51, 17 September 2011
Introduction
Logfiles typically belong to a plugin, and often describe data from an interface (a sensor or its like). These files may further be directly - or after removing a few introductary text lines - be importable into e.g. MATLAB or SCILAB.
AURS supports replay of such files and has the ability to synchronize replay of many logfiles across a ARUS server and across more servers.
Replay File format
A replay file is line oriented and the filename is related to the interface - often the plug-in name.
A file could look like this (in this case orientation relative to north in radians):
1299310465.928301 0.1 0.14 3.03 1299310465.944308 0.12 0.12 3.05 1299310465.964305 0.1 0.08 3.07 1299310465.984304 0.09 0.11 3.07 1299310466.004308 0.07 0.1 3.08 1299310466.028311 0.07 0.08 3.1 1299310466.052313 0.05 0.04 3.1 # crc-check error in communication with sensor 1299310466.088313 0.07 0.05 3.12
The the timestamp must be the first value in all replay files, as it is read by the replay system, this should then be followed by any value relevant for the interface for this time - all on the same line.
Any line that starts with a text character - e.g. a '#' - will be ignored by the replay function.
Replay mode
When an interface is set in replay mode it will open the specified logfile (in the path specified by the (global) replay path.
The interface can then be stepped (one or more lines at a time)
The plug-in will then insert the data (typically as if it came from the interface)
All plug-in modules are connected, so that if one plug-in module is stepped one line. The replay time (the first element in any replay line) is advanced and all other plug-ins in replay mode are requested to advance to this time.
The other plug-ins then advance until the next replay line has a timestamp that is ahead of this replay time. All the lines up to this time (zero or many) will be send to the plug-in - in a decodeReplayLine(..) call.
Check the on-line help of plug-ins to see if they support replay.
How to use
To make a plugin with replay, you must handle two keywords options in the plugin.
>> myplugin replay=true >> myplugin step=1
Handle command options
So add something like this to your on-line help part of handleCommand method:
bool myclass::handleCommand(UServerInMsg * msg, void * extra) ... sendHelpStart( ... ... sendText("replay=true|false Start or stop replay mode for this plug-in\n"); sendText("step = N replay N steps from replay file\n"); ... sendHelpDone();
And to handle these options in the same function, something like:
... bool valueBool; if (msg->tag.getAttBool("replay", &valueBool, true)) setReplay(valueBool); // replay step int valueInt; if (msg->tag.getAttInteger("step", &valueInt, 1)) replayStep(valueInt);
The setReplay(bool) and replayStep(int) is already available in the plug-in and resource classes.
handle replay lines
The replay system will call decodeReplayLine(char * line) whenever it is time to replay a new line of data. So define a method to handle the decode of line to replay, this could look something like:
virtual bool decodeReplayLine(char * line) { unsigned long int sec, usec; double x, y, z; UTime t; int n = sscanf(line, "%lu.%lu x y z", &sec, &usec, &x, &y, &z); // fake a sensor update, as if it came from the sensor itself t.setTimeU(sec, usec); sensorUpdate(t, x, y, z); }
Replay logfile name and path
The replay must know the name of the replay file. This filename should be a reserved name for this plug-in, preferred the same name as the plug-in, with a .log extension. Set this filename in the plug-in constructor:
... replaySetBaseFileName("myplugin"); ...
The .log extension is added, and the file must be present in the replayPath. This replayPath should be set in the .ini file of the server, e.g.:
... server replayPath="/home/myname/replayLogs/20110618/" ...
Replay status
If you want replay status (replay mode, replay line and replay time) as part of the global variables, then call createReplayVar(UVarPool * vp) when the remaining global variables are created.
createReplayVar(getVarPool());
To test if the plug-in is in replay mode a function isReplay() is available.
isReplay();
Replay synchronize with other servers
If the server is to synchronize the replay with other servers, then the servers must be connected with interface plug-ins. E.g. if the camera server ucamserver is to replay in sync with the laser scanner server ulmsserver, then set up an interface connection between them, and set this interface in replay mode. The .ini file should include something like:
# camsera server ini-file ucamserver.ini ... # load interface to laser scanner server module load=if alias=laser laser connect=localhost:24919 laser replay ..
# laser server ini-file ulmsserver.ini ... # load interface to camera server module load=if alias=cam cam connect=localhost:24920 cam replay ..