OpenTracker

An Open Architecture for Reconfigurable Tracking based on XML | Contact

ARTDataTrackerChomp.cxx

Go to the documentation of this file.
00001 /* ========================================================================
00002  * Copyright (c) 2006,
00003  * Institute for Computer Graphics and Vision
00004  * Graz University of Technology
00005  * All rights reserved.
00006  *
00007  * Redistribution and use in source and binary forms, with or without
00008  * modification, are permitted provided that the following conditions are
00009  * met:
00010  *
00011  * Redistributions of source code must retain the above copyright notice,
00012  * this list of conditions and the following disclaimer.
00013  *
00014  * Redistributions in binary form must reproduce the above copyright
00015  * notice, this list of conditions and the following disclaimer in the
00016  * documentation and/or other materials provided with the distribution.
00017  *
00018  * Neither the name of the Graz University of Technology nor the names of
00019  * its contributors may be used to endorse or promote products derived from
00020  * this software without specific prior written permission.
00021  *
00022  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
00023  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
00024  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
00025  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
00026  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00027  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00028  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00029  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00030  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00031  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00032  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00033  * ========================================================================
00034  * PROJECT: OpenTracker
00035  * ======================================================================== */
00042 /* ======================================================================= */
00043 
00044 // this will remove the warning 4786
00045 #include "../tool/disable4786.h"
00046 
00047 #include <stdlib.h>
00048 #include "ARTDataTrackerChomp.h"
00049 
00050 #include <stdlib.h>
00051 #include <sys/types.h>
00052 #include <stdio.h>
00053 
00054 #include <iostream>
00055 #include <sstream>
00056 
00057 #include <ace/Log_Msg.h>
00058 
00059 
00060 #ifndef OT_NO_ARTDATATRACKER_SUPPORT
00061 
00062 
00063 namespace ot {
00064 
00065     // Destructor method
00066 
00067     ARTDataTrackerChomp::~ARTDataTrackerChomp()
00068     {   
00069     }
00070 
00071 
00072     ARTDataTrackerChomp::ARTDataTrackerChomp()
00073     {
00074     }
00075 
00076     void ARTDataTrackerChomp::chomp(std::string datagramm)
00077     {
00078     using namespace std;
00079 
00080     istringstream iss(datagramm);
00081               
00082     int linenumber = 0;
00083 
00084     unsigned long elcount = 0;
00085     int station = -1;
00086     double timestamp = 0.0;
00087 
00088     std::map<int, BodyRecord>::iterator bdit;
00089     std::map<int, MarkerRecord>::iterator mkit;
00090     std::map<int, FlystickRecord>::iterator fsit;
00091     std::map<int, MeasuretargetRecord>::iterator mtit;
00092     for ( bdit = tempBodyRecord.begin(); bdit != tempBodyRecord.end(); bdit++) {
00093         ((*bdit).second).valid = false;
00094     }
00095     for ( mkit = tempMarkerRecord.begin(); mkit != tempMarkerRecord.end(); mkit++) {
00096         ((*mkit).second).valid = false;
00097     }
00098     for ( fsit = tempFlystickRecord.begin(); fsit != tempFlystickRecord.end(); fsit++) {
00099         ((*fsit).second).valid = false;
00100     }
00101     for ( mtit = tempMeasuretargetRecord.begin(); mtit != tempMeasuretargetRecord.end(); mtit++) {
00102         ((*mtit).second).valid = false;
00103     }
00104     numberTrackedBodies = 0;
00105     numberTrackedMarkers = 0;
00106     numberTrackedFlysticks = 0;
00107     numberTrackedMeasuretargets = 0;
00108 
00109     while (!iss.eof()) {
00110         stringbuf linetype;
00111         stringbuf linecontent;
00112 
00113         iss.get(linetype,' ');
00114         
00115         if ((linenumber == 0) && (linetype.str() != "fr")) {
00116         ACE_DEBUG((LM_ERROR, ACE_TEXT("ot:Error receiving correct Data!!! [#001]\n")));
00117         ACE_DEBUG((LM_ERROR, ACE_TEXT("ot:Check if Format in ARTTracker Software is set to ASCII !!!\n")));
00118         return;       
00119         }
00120 
00121         //ACE_DEBUG((LM_INFO, ACE_TEXT("%d linetype    |%s|\n"), linenumber, linetype.str().c_str() ));     
00122         if (linetype.str() == "fr") {
00123         iss >> frameNumber;
00124         
00125         iss.get(linecontent);
00126 
00127         if (static_cast<int>(iss.peek()) == 10) {           
00128             iss.ignore(1);
00129         }
00130         }
00131         else if (linetype.str() == "ts") {      
00132         iss >> timestamp;
00133         //ACE_DEBUG((LM_INFO, ACE_TEXT("%d timestamp  |%f|\n"), linenumber, timestamp ));
00134         iss.get(linecontent);
00135         if (static_cast<int>(iss.peek()) == 10) {           
00136             iss.ignore(1);
00137         }
00138         }
00139         else if (linetype.str() == "6d") {
00140         iss >> numberTrackedBodies;
00141         //ACE_DEBUG((LM_INFO, ACE_TEXT("%d 6dcount   |%d|\n"), linenumber, numberTrackedBodies ));
00142 
00143         if (numberTrackedBodies > 0) iss.ignore(2);
00144         
00145         int i;
00146         for (i=0; i<numberTrackedBodies; i++) {
00147             iss >> station;
00148             //ACE_DEBUG((LM_INFO, ACE_TEXT("%d station   |%d|\n"), linenumber, station ));
00149             
00150             tempBodyRecord[station].id = station;
00151             iss >> tempBodyRecord[station].quality;
00152             iss.ignore(2);
00153             iss >> tempBodyRecord[station].location[0];
00154             iss >> tempBodyRecord[station].location[1];
00155             iss >> tempBodyRecord[station].location[2];
00156             iss >> tempBodyRecord[station].eulerAngles[0];
00157             iss >> tempBodyRecord[station].eulerAngles[1];
00158             iss >> tempBodyRecord[station].eulerAngles[2];
00159             iss.ignore(2);
00160             iss >> tempBodyRecord[station].rotationMatrix[0];
00161             iss >> tempBodyRecord[station].rotationMatrix[1];
00162             iss >> tempBodyRecord[station].rotationMatrix[2];
00163             iss >> tempBodyRecord[station].rotationMatrix[3];
00164             iss >> tempBodyRecord[station].rotationMatrix[4];
00165             iss >> tempBodyRecord[station].rotationMatrix[5];
00166             iss >> tempBodyRecord[station].rotationMatrix[6];
00167             iss >> tempBodyRecord[station].rotationMatrix[7];
00168             iss >> tempBodyRecord[station].rotationMatrix[8];
00169 
00170             tempBodyRecord[station].valid = true;
00171 
00172             if (i < numberTrackedBodies-1) iss.ignore(3); else iss.ignore(1);           
00173         }
00174 
00175         iss.get(linecontent);       
00176         if (static_cast<int>(iss.peek()) == 10) {           
00177             iss.ignore(1);
00178         }
00179         }
00180         else if (linetype.str() == "3d") {
00181         iss >> numberTrackedMarkers;
00182         //ACE_DEBUG((LM_INFO, ACE_TEXT("%d 3dcount   |%d|\n"), linenumber, numberTrackedMarkers ));
00183 
00184         if (numberTrackedMarkers > 0) iss.ignore(2);
00185 
00186         int i;      
00187         for (i=0; i<numberTrackedMarkers; i++) {
00188             iss >> station;
00189             //ACE_DEBUG((LM_INFO, ACE_TEXT("%d station   |%d|\n"), linenumber, station ));
00190             
00191             tempMarkerRecord[station].id = station;
00192             iss >> tempMarkerRecord[station].quality;
00193             
00194             iss.ignore(2);
00195             iss >> tempMarkerRecord[station].location[0];
00196             iss >> tempMarkerRecord[station].location[1];
00197             iss >> tempMarkerRecord[station].location[2];
00198 
00199             tempMarkerRecord[station].valid = true;
00200 
00201             if (i < numberTrackedMarkers-1) iss.ignore(3); else iss.ignore(1);
00202         }
00203     
00204         iss.get(linecontent);       
00205         if (static_cast<int>(iss.peek()) == 10) {           
00206             iss.ignore(1);
00207         }
00208         }
00209         else if (linetype.str() == "6df") {     
00210         iss >> numberTrackedFlysticks;      
00211         //ACE_DEBUG((LM_INFO, ACE_TEXT("%d 6dfcount   |%d|\n"), linenumber, numberTrackedFlysticks ));
00212 
00213         if (numberTrackedFlysticks > 0) iss.ignore(2);
00214         
00215         int i;
00216         for (i=0; i<numberTrackedFlysticks; i++) {
00217             iss >> station;
00218             //ACE_DEBUG((LM_INFO, ACE_TEXT("%d station   |%d|\n"), linenumber, station ));
00219             
00220             tempFlystickRecord[station].id = station;
00221             iss >> tempFlystickRecord[station].quality;
00222             iss >> tempFlystickRecord[station].buttons;
00223             iss.ignore(2);
00224             iss >> tempFlystickRecord[station].location[0];
00225             iss >> tempFlystickRecord[station].location[1];
00226             iss >> tempFlystickRecord[station].location[2];
00227             iss >> tempFlystickRecord[station].eulerAngles[0];
00228             iss >> tempFlystickRecord[station].eulerAngles[1];
00229             iss >> tempFlystickRecord[station].eulerAngles[2];
00230             iss.ignore(2);
00231             iss >> tempFlystickRecord[station].rotationMatrix[0];
00232             iss >> tempFlystickRecord[station].rotationMatrix[1];
00233             iss >> tempFlystickRecord[station].rotationMatrix[2];
00234             iss >> tempFlystickRecord[station].rotationMatrix[3];
00235             iss >> tempFlystickRecord[station].rotationMatrix[4];
00236             iss >> tempFlystickRecord[station].rotationMatrix[5];
00237             iss >> tempFlystickRecord[station].rotationMatrix[6];
00238             iss >> tempFlystickRecord[station].rotationMatrix[7];
00239             iss >> tempFlystickRecord[station].rotationMatrix[8];
00240 
00241             tempFlystickRecord[station].valid = true;
00242 
00243             if (i < numberTrackedFlysticks-1) iss.ignore(3); else iss.ignore(1);            
00244         }
00245 
00246         iss.get(linecontent);       
00247         if (static_cast<int>(iss.peek()) == 10) {           
00248             iss.ignore(1);
00249         }
00250         }
00251         else if (linetype.str() == "6dmt") {
00252         iss >> numberTrackedMeasuretargets;
00253         //ACE_DEBUG((LM_INFO, ACE_TEXT("%d 6dmtcount   |%d|\n"), linenumber, numberTrackedMeasuretargets ));
00254 
00255         if (numberTrackedMeasuretargets > 0) iss.ignore(2);
00256                         
00257         int i;
00258         for (i=0; i<numberTrackedMeasuretargets; i++) {
00259             iss >> station;
00260             //ACE_DEBUG((LM_INFO, ACE_TEXT("%d station   |%d|\n"), linenumber, station ));
00261             
00262             tempMeasuretargetRecord[station].id = station;
00263             iss >> tempMeasuretargetRecord[station].quality;
00264             iss >> tempMeasuretargetRecord[station].buttons;
00265             iss.ignore(2);
00266             iss >> tempMeasuretargetRecord[station].location[0];
00267             iss >> tempMeasuretargetRecord[station].location[1];
00268             iss >> tempMeasuretargetRecord[station].location[2];
00269             iss.ignore(2);
00270             iss >> tempMeasuretargetRecord[station].rotationMatrix[0];
00271             iss >> tempMeasuretargetRecord[station].rotationMatrix[1];
00272             iss >> tempMeasuretargetRecord[station].rotationMatrix[2];
00273             iss >> tempMeasuretargetRecord[station].rotationMatrix[3];
00274             iss >> tempMeasuretargetRecord[station].rotationMatrix[4];
00275             iss >> tempMeasuretargetRecord[station].rotationMatrix[5];
00276             iss >> tempMeasuretargetRecord[station].rotationMatrix[6];
00277             iss >> tempMeasuretargetRecord[station].rotationMatrix[7];
00278             iss >> tempMeasuretargetRecord[station].rotationMatrix[8];
00279 
00280             tempMeasuretargetRecord[station].valid = true;
00281 
00282             if (i < numberTrackedMeasuretargets-1) iss.ignore(3); else iss.ignore(1);           
00283         }
00284         
00285         iss.get(linecontent);       
00286         if (static_cast<int>(iss.peek()) == 10) {           
00287             iss.ignore(1);
00288         }
00289         }
00290         else if (linetype.str() == "6dcal") {
00291         iss >> numberTrackedCalBodies;
00292         //ACE_DEBUG((LM_INFO, ACE_TEXT("%d 6dcalcount   |%d|\n"), linenumber, numberTrackedCalBodies ));
00293         iss.get(linecontent);
00294         if (static_cast<int>(iss.peek()) == 10) {           
00295             iss.ignore(1);
00296         }       
00297         }
00298         else {
00299         iss.get(linecontent);
00300         if (static_cast<int>(iss.peek()) == 10) {           
00301             iss.ignore(1);
00302         }
00303         }
00304         
00305         ++linenumber;
00306     }
00307 
00308     }
00309 
00310 
00311     void ARTDataTrackerChomp::displayRecords()
00312     {
00313     // Output
00314     ACE_DEBUG((LM_INFO, ACE_TEXT("ot:Contents of tempBodyRecord, tempMarkerRecord, tempFlystickRecord and tempMeasuretargetRecord\n")));
00315 
00316 
00317     ACE_DEBUG((LM_INFO, ACE_TEXT("ot:Number of  Tracked Bodies for 6d: %d\n"), tempBodyRecord.size() ));
00318     std::map<int, BodyRecord>::iterator itb;
00319     for ( itb = tempBodyRecord.begin(); itb != tempBodyRecord.end(); itb++)
00320         {
00321         ACE_DEBUG((LM_INFO, ACE_TEXT("ot:Framenumber of Datagramm is: %d\n"), frameNumber));
00322         ACE_DEBUG((LM_INFO, ACE_TEXT("ot:Number of  Tracked Bodies for 6d: %d\n"), numberTrackedBodies));
00323         if ( itb->second.valid == true )
00324             {
00325             ACE_DEBUG((LM_INFO, ACE_TEXT("ot:tempBodyRecord[%d].id  %d\n"), itb->first, itb->second.id));
00326             ACE_DEBUG((LM_INFO, ACE_TEXT("ot:tempBodyRecord[%d].quality %f\n"), itb->first, itb->second.quality));
00327             int j;
00328             for(j=0; j < 3; j++)
00329                 {
00330                 ACE_DEBUG((LM_INFO, ACE_TEXT("ot:tempBodyRecord[%d].location[%d]: \n"), 
00331                        itb->first, j, itb->second.location[j]));
00332                 }
00333             for(j=0; j < 3; j++)
00334                 {
00335                 ACE_DEBUG((LM_INFO, ACE_TEXT("ot:tempBodyRecord[%d].eulerAngles[%d]: \n"), 
00336                        itb->first, j, itb->second.eulerAngles[j]));
00337                 }
00338             for(j=0; j < 9; j++)
00339                 {
00340                 ACE_DEBUG((LM_INFO, ACE_TEXT("ot:tempBodyRecord[%d].rotationMatrix[%d]: \n"), 
00341                        itb->first, j, itb->second.rotationMatrix[j]));
00342                 }
00343             }// END if
00344         else
00345             {
00346             ACE_DEBUG((LM_ERROR, ACE_TEXT("ot:#### No Valid DATA for this Body ####")));
00347             }// END else
00348         }
00349 
00350     std::map<int, MarkerRecord>::iterator itm;
00351     for(itm = tempMarkerRecord.begin(); itm != tempMarkerRecord.end(); itm++)
00352         {
00353         ACE_DEBUG((LM_ERROR, ACE_TEXT("ot:Number of Markers for 3d: %d\n"), numberTrackedMarkers));
00354 
00355         if ( itm->second.valid == true )
00356             {
00357 
00358             ACE_DEBUG((LM_ERROR, ACE_TEXT("ot:tempMarkerRecord[%d].id %d\n"), itm->first, itm->second.id));
00359             ACE_DEBUG((LM_ERROR, ACE_TEXT("ot:tempMarkerRecord[%d].quality %d\n"), itm->first, itm->second.quality));
00360             
00361             for(int j=0; j < 3; j++)
00362                 {
00363                 ACE_DEBUG((LM_INFO, ACE_TEXT("ot:tempBodyRecord[%d].location[%d]: \n"), itm->first, j, itm->second.location[j]));
00364                 }
00365             }
00366         else
00367             {
00368             ACE_DEBUG((LM_ERROR, ACE_TEXT("ot:#### No Valid DATA for this Marker ####")));
00369             }
00370         }
00371 
00372     std::map<int, FlystickRecord>::iterator itf;
00373     for ( itf = tempFlystickRecord.begin(); itf != tempFlystickRecord.end(); itf++)
00374         {
00375         ACE_DEBUG((LM_INFO, ACE_TEXT("ot:Framenumber of Datagramm is: %d\n"), frameNumber));
00376         ACE_DEBUG((LM_INFO, ACE_TEXT("ot:Number of Tracked Flysticks: %d\n"), numberTrackedFlysticks));
00377         if ( itf->second.valid == true )
00378             {
00379             ACE_DEBUG((LM_INFO, ACE_TEXT("ot:tempFlystickRecord[%d].id  %d\n"), itf->first, itf->second.id));
00380             ACE_DEBUG((LM_INFO, ACE_TEXT("ot:tempFlystickRecord[%d].quality %f\n"), itf->first, itf->second.quality));
00381             ACE_DEBUG((LM_INFO, ACE_TEXT("ot:tempFlystickRecord[%d].buttons %d\n"), itf->first, itf->second.buttons));
00382             int j;
00383             for(j=0; j < 3; j++)
00384                 {
00385                 ACE_DEBUG((LM_INFO, ACE_TEXT("ot:tempFlystickRecord[%d].location[%d]: \n"), 
00386                        itf->first, j, itf->second.location[j]));
00387                 }
00388             for(j=0; j < 3; j++)
00389                 {
00390                 ACE_DEBUG((LM_INFO, ACE_TEXT("ot:tempFlystickRecord[%d].eulerAngles[%d]: \n"), 
00391                        itf->first, j, itf->second.eulerAngles[j]));
00392                 }
00393             for(j=0; j < 9; j++)
00394                 {
00395                 ACE_DEBUG((LM_INFO, ACE_TEXT("ot:tempFlystickRecord[%d].rotationMatrix[%d]: \n"), 
00396                        itf->first, j, itf->second.rotationMatrix[j]));
00397                 }
00398             }// END if
00399         else
00400             {
00401             ACE_DEBUG((LM_ERROR, ACE_TEXT("ot:#### No Valid DATA for this Flystick ####")));
00402             }// END else
00403         }
00404 
00405     std::map<int, MeasuretargetRecord>::iterator itmt;
00406     for ( itmt = tempMeasuretargetRecord.begin(); itmt != tempMeasuretargetRecord.end(); itmt++)
00407         {
00408         ACE_DEBUG((LM_INFO, ACE_TEXT("ot:Framenumber of Datagramm is: %d\n"), frameNumber));
00409         ACE_DEBUG((LM_INFO, ACE_TEXT("ot:Number of Tracked Measurement Targets: %d\n"), numberTrackedMeasuretargets));
00410         if ( itmt->second.valid == true )
00411             {
00412             ACE_DEBUG((LM_INFO, ACE_TEXT("ot:tempMeasureTargetRecord[%d].id  %d\n"), itmt->first, itmt->second.id));
00413             ACE_DEBUG((LM_INFO, ACE_TEXT("ot:tempMeasureTargetRecord[%d].quality %f\n"), itmt->first, itmt->second.quality));
00414             ACE_DEBUG((LM_INFO, ACE_TEXT("ot:tempMeasureTargetRecord[%d].buttons %d\n"), itmt->first, itmt->second.buttons));
00415             int j;
00416             for(j=0; j < 3; j++)
00417                 {
00418                 ACE_DEBUG((LM_INFO, ACE_TEXT("ot:tempMeasureTargetRecord[%d].location[%d]: \n"), 
00419                        itmt->first, j, itmt->second.location[j]));
00420                 }
00421             for(j=0; j < 9; j++)
00422                 {
00423                 ACE_DEBUG((LM_INFO, ACE_TEXT("ot:tempMeasureTargetRecord[%d].rotationMatrix[%d]: \n"), 
00424                        itmt->first, j, itmt->second.rotationMatrix[j]));
00425                 }
00426             }// END if
00427         else
00428             {
00429             ACE_DEBUG((LM_ERROR, ACE_TEXT("ot:#### No Valid DATA for this Measurement Target ####")));
00430             }// END else
00431         }
00432 
00433 
00434     if(numberTrackedCalBodies != 0)
00435         {
00436         ACE_DEBUG((LM_ERROR, ACE_TEXT("ot:Number of calibrated Bodies: %d\n"), numberTrackedCalBodies));
00437         }
00438 
00439     //assert(0);
00440     //assert(tempBodyRecord.size() != 0);
00441 
00442     }
00443 
00444     int ARTDataTrackerChomp::getFrameNumber()
00445     {
00446     return frameNumber;
00447     }
00448 
00449     int ARTDataTrackerChomp::getTrackedBodyNumber()
00450     {
00451     return numberTrackedBodies;
00452     }
00453 
00454     std::map<int, ARTDataTrackerChomp::BodyRecord > & ARTDataTrackerChomp::getBodyRecord()
00455     {
00456     return tempBodyRecord;
00457     }
00458 
00459     int ARTDataTrackerChomp::getTrackedMarkerNumber()
00460     {
00461     return numberTrackedMarkers;
00462     }
00463 
00464     std::map<int, ARTDataTrackerChomp::MarkerRecord > &ARTDataTrackerChomp::getMarkerRecord()
00465     {
00466     return tempMarkerRecord;
00467     }
00468 
00469     int ARTDataTrackerChomp::getTrackedFlystickNumber()
00470     {
00471     return numberTrackedFlysticks;
00472     }
00473 
00474     std::map<int, ARTDataTrackerChomp::FlystickRecord > &ARTDataTrackerChomp::getFlystickRecord()
00475     {
00476     return tempFlystickRecord;
00477     }
00478 
00479     int ARTDataTrackerChomp::getTrackedMeasuretargetNumber()
00480     {
00481     return numberTrackedMeasuretargets;
00482     }
00483 
00484     std::map<int, ARTDataTrackerChomp::MeasuretargetRecord > &ARTDataTrackerChomp::getMeasuretargetRecord()
00485     {
00486     return tempMeasuretargetRecord;
00487     }
00488 
00489     int ARTDataTrackerChomp::getCalibratedTrackedBodyNumber()
00490     {
00491     return numberTrackedCalBodies;
00492     }
00493 
00494 } // namespace ot
00495 
00496 
00497 #else
00498 #pragma message(">>> OT_NO_ARTDATATRACKER_SUPPORT")
00499 #endif // OT_NO_ARTDATATRACKER_SUPPORT
00500 
00501 
00502 /* ===========================================================================
00503    End of ARTDataTrackerChomp.cxx
00504    ===========================================================================
00505    Automatic Emacs configuration follows.
00506    Local Variables:
00507    mode:c++
00508    c-basic-offset: 4
00509    eval: (c-set-offset 'subeventment-open 0)
00510    eval: (c-set-offset 'case-label '+)
00511    eval: (c-set-offset 'eventment 'c-lineup-runin-eventments)
00512    eval: (setq indent-tabs-mode nil)
00513    End:
00514    =========================================================================== */

copyright (c) 2006 Graz University of Technology