Simulation.cpp

Go to the documentation of this file.
00001 /******************************************************************************
00002 *       SOFA, Simulation Open-Framework Architecture, version 1.0 beta 3      *
00003 *                (c) 2006-2008 MGH, INRIA, USTL, UJF, CNRS                    *
00004 *                                                                             *
00005 * This library is free software; you can redistribute it and/or modify it     *
00006 * under the terms of the GNU Lesser General Public License as published by    *
00007 * the Free Software Foundation; either version 2.1 of the License, or (at     *
00008 * your option) any later version.                                             *
00009 *                                                                             *
00010 * This library is distributed in the hope that it will be useful, but WITHOUT *
00011 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
00012 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
00013 * for more details.                                                           *
00014 *                                                                             *
00015 * You should have received a copy of the GNU Lesser General Public License    *
00016 * along with this library; if not, write to the Free Software Foundation,     *
00017 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.          *
00018 *******************************************************************************
00019 *                               SOFA :: Modules                               *
00020 *                                                                             *
00021 * Authors: The SOFA Team and external contributors (see Authors.txt)          *
00022 *                                                                             *
00023 * Contact information: contact@sofa-framework.org                             *
00024 ******************************************************************************/
00025 #include <sofa/simulation/tree/Simulation.h>
00026 #include <sofa/helper/system/SetDirectory.h>
00027 #include <sofa/helper/system/FileRepository.h>
00028 #include <sofa/simulation/common/PrintVisitor.h>
00029 #include <sofa/simulation/common/FindByTypeVisitor.h>
00030 #include <sofa/simulation/common/ExportGnuplotVisitor.h>
00031 #include <sofa/simulation/common/InitVisitor.h>
00032 #include <sofa/simulation/common/InstrumentVisitor.h>
00033 #include <sofa/simulation/common/AnimateVisitor.h>
00034 #include <sofa/simulation/common/MechanicalVisitor.h>
00035 #include <sofa/simulation/common/CollisionVisitor.h>
00036 #include <sofa/simulation/common/UpdateContextVisitor.h>
00037 #include <sofa/simulation/common/UpdateMappingVisitor.h>
00038 #include <sofa/simulation/common/ResetVisitor.h>
00039 #include <sofa/simulation/common/VisualVisitor.h>
00040 #include <sofa/simulation/tree/DeleteVisitor.h>
00041 #include <sofa/simulation/common/ExportOBJVisitor.h>
00042 #include <sofa/simulation/common/WriteStateVisitor.h>
00043 #include <sofa/simulation/common/XMLPrintVisitor.h>
00044 #include <sofa/simulation/common/PropagateEventVisitor.h>
00045 #include <sofa/simulation/common/BehaviorUpdatePositionVisitor.h>
00046 #include <sofa/simulation/common/AnimateBeginEvent.h>
00047 #include <sofa/simulation/common/AnimateEndEvent.h>
00048 #include <sofa/simulation/common/UpdateMappingEndEvent.h>
00049 #include <sofa/core/ObjectFactory.h>
00050 #include <sofa/helper/system/PipeProcess.h>
00051 
00052 #include <fstream>
00053 #include <string.h>
00054 #ifndef WIN32
00055 #include <locale.h>
00056 #endif
00057 
00058 namespace sofa
00059 {
00060 
00061     namespace simulation
00062     {
00063 
00064         namespace tree
00065         {
00066 
00067             using namespace sofa::defaulttype;
00068 
00070             Simulation* theSimulation = NULL;
00071 
00072             void setSimulation ( Simulation* s )
00073             {
00074                 theSimulation = s;
00075             }
00076 
00077             Simulation* getSimulation()
00078             {
00079                 if ( theSimulation==NULL )
00080                     theSimulation = new Simulation;
00081                 return theSimulation;
00082             }
00083 
00085             GNode* Simulation::processXML(xml::BaseElement* xml, const char *filename)
00086             {
00087                 if ( xml==NULL )
00088                 {
00089                     return NULL;
00090                 }
00091 
00092                 // We go the the current file's directory so that all relative path are correct
00093                 helper::system::SetDirectory chdir ( filename );
00094 
00095 #ifndef WIN32
00096                 // Reset local settings to make sure that floating-point values are interpreted correctly
00097                 setlocale(LC_ALL,"C");
00098                 setlocale(LC_NUMERIC,"C");
00099 #endif
00100 
00101 //              std::cout << "Initializing objects"<<std::endl;
00102                 if ( !xml->init() )
00103                 {
00104                     std::cerr << "Objects initialization failed."<<std::endl;
00105                 }
00106 
00107                 GNode* root = dynamic_cast<GNode*> ( xml->getObject() );
00108                 if ( root == NULL )
00109                 {
00110                     std::cerr << "Objects initialization failed."<<std::endl;
00111                     delete xml;
00112                     return NULL;
00113                 }
00114 
00115 //              std::cout << "Initializing simulation "<<root->getName() <<std::endl;
00116                 
00117                 // Find the Simulation component in the scene
00118                 FindByTypeVisitor<Simulation> findSimu;
00119                 findSimu.execute(root);
00120                 if( !findSimu.found.empty() )
00121                     setSimulation( findSimu.found[0] );
00122                 // if no Simulation is found, getSimulation() will automatically create one, of the default type.
00123 
00124                 getSimulation()->init ( root );
00125                 
00126                 // As mappings might be initialized after visual models, it is necessary to update them
00127                 // BUGFIX (Jeremie A.): disabled as initTexture was not called yet, and the GUI might not even be up yet
00128                 //root->execute<VisualUpdateVisitor>();
00129                 
00130                 return root;
00131             }
00132             
00134             GNode* Simulation::loadFromMemory ( const char *filename, const char *data, unsigned int size )
00135             {
00136                 //::sofa::simulation::init();
00137 //              std::cerr << "Loading simulation XML file "<<filename<<std::endl;
00138                 xml::BaseElement* xml = xml::loadFromMemory (filename, data, size );
00139                 
00140                 GNode* root = processXML(xml, filename);
00141 
00142 //              std::cout << "load done."<<std::endl;
00143                 delete xml;
00144 
00145                 return root;    
00146             }
00147             
00148             
00150             GNode* Simulation::loadFromFile ( const char *filename )
00151             {
00152                 //::sofa::simulation::init();
00153 //              std::cerr << "Loading simulation XML file "<<filename<<std::endl;
00154                 xml::BaseElement* xml = xml::loadFromFile ( filename );
00155                 
00156                 GNode* root = processXML(xml, filename);
00157 
00158 //              std::cout << "load done."<<std::endl;
00159                 delete xml;
00160 
00161                 return root;
00162             }
00163             
00165             GNode* Simulation::load ( const char *filename )
00166             {
00167                 std::string ext = sofa::helper::system::SetDirectory::GetExtension(filename);
00168                 if (ext == "php" || ext == "pscn")
00169                 {
00170                     std::string out="",error="";
00171                     std::vector<std::string> args;
00172                     
00173                     
00174                     //TODO : replace when PipeProcess will get file as stdin
00175                     //at the moment, the filename is given as an argument
00176                     args.push_back(std::string("-f" + std::string(filename)));
00177                     //args.push_back("-w");
00178                     std::string newFilename="";
00179                     //std::string newFilename=filename;
00180                     
00181                     helper::system::FileRepository fp("PATH", ".");
00182 #ifdef WIN32
00183                     std::string command = "php.exe";
00184 #else
00185                     std::string command = "php";
00186 #endif
00187                     if (!fp.findFile(command,""))
00188                     {
00189                         std::cerr << "Simulation : Error : php not found in your PATH environment" << std::endl;
00190                         return NULL;
00191                     }
00192                     
00193                     sofa::helper::system::PipeProcess::executeProcess(command.c_str(), args,  newFilename, out, error);
00194                     
00195                     if(error != "")
00196                     {
00197                         std::cerr << "Simulation : load : "<< error << std::endl;
00198                         if (out == "")
00199                             return NULL;
00200                     }
00201                     
00202                     return loadFromMemory(filename, out.c_str(), out.size());
00203                 }
00204                 
00205                 if (ext == "scn" || ext == "xml")
00206                 {
00207                     return loadFromFile(filename);
00208                 }
00209                 
00210                 std::cerr << "Simulation : Error : extension not handled" << std::endl;
00211                 return NULL;
00212                 
00213             }
00214 
00215 Simulation::Simulation()
00216 : numMechSteps( initData(&numMechSteps,(unsigned) 1,"numMechSteps","Number of mechanical steps within one update step. If the update time step is dt, the mechanical time step is dt/numMechSteps.") ),
00217 gnuplotDirectory( initData(&gnuplotDirectory,std::string(""),"gnuplotDirectory","Directory where the gnuplot files will be saved")),
00218 instrumentInUse( initData( &instrumentInUse, -1, "instrumentinuse", "Numero of the instrument currently used"))
00219 {}
00220 
00221 Simulation::~Simulation(){
00222   setSimulation( NULL );
00223 }
00224             
00226             void Simulation::print ( Node* root )
00227             {
00228                 if ( !root ) return;
00229                 root->execute<PrintVisitor>();
00230             }
00231 
00233             void Simulation::printXML ( Node* root, const char* fileName )
00234             {
00235                 if ( !root ) return;
00236                 if ( fileName!=NULL )
00237                 {
00238                     std::ofstream out ( fileName );
00239                     XMLPrintVisitor print ( out );
00240                     root->execute ( print );
00241                 }
00242                 else
00243                 {
00244                     XMLPrintVisitor print ( std::cout );
00245                     root->execute ( print );
00246                 }
00247             }
00248 
00250             void Simulation::init ( Node* root )
00251             {
00252                 //cerr<<"Simulation::init"<<endl;
00253                 setContext( root->getContext());
00254                 if ( !root ) return;
00255                 root->execute<InitVisitor>();
00256                 // Save reset state for later uses in reset()
00257                 root->execute<MechanicalPropagatePositionAndVelocityVisitor>();
00258                 root->execute<MechanicalPropagateFreePositionVisitor>();
00259                 root->execute<StoreResetStateVisitor>();
00260                 
00261                 //Get the list of instruments present in the scene graph
00262                 getInstruments(root);
00263             }
00264 
00265             void Simulation::getInstruments( Node *node)
00266             {
00267               InstrumentVisitor fetchInstrument;
00268               node->execute<InstrumentVisitor>();
00269               fetchInstrument.execute(node); 
00270               instruments = fetchInstrument.getInstruments();
00271             }
00272             
00274             void Simulation::animate ( Node* root, double dt )
00275             {
00276                 if ( !root ) return;
00277                 if ( root->getMultiThreadSimulation() )
00278                     return;
00279 
00280                 {
00281                     AnimateBeginEvent ev ( dt );
00282                     PropagateEventVisitor act ( &ev );
00283                     root->execute ( act );
00284                 }
00285 
00286                 //std::cout << "animate\n";
00287                 double startTime = root->getTime();
00288                 double mechanicalDt = dt/numMechSteps.getValue();
00289                 //double nextTime = root->getTime() + root->getDt();
00290 
00291                 // CHANGE to support MasterSolvers : CollisionVisitor is now activated within AnimateVisitor
00292                 //root->execute<CollisionVisitor>();
00293 
00294                 AnimateVisitor act;
00295                 act.setDt ( mechanicalDt );
00296                                 BehaviorUpdatePositionVisitor beh(root->getDt());       
00297                 for( unsigned i=0; i<numMechSteps.getValue(); i++ )
00298                                 {
00299                                         root->execute ( act );
00300                                         root->execute ( beh );                     
00301                     root->setTime ( startTime + (i+1)* act.getDt() ); 
00302                     root->execute<UpdateSimulationContextVisitor>();
00303                 }
00304                             
00305                             {
00306                                 AnimateEndEvent ev ( dt );
00307                                 PropagateEventVisitor act ( &ev );
00308                                 root->execute ( act );
00309                             }
00310                             
00311                 root->execute<UpdateMappingVisitor>();
00312                             {
00313                                 UpdateMappingEndEvent ev ( dt );
00314                                 PropagateEventVisitor act ( &ev );
00315                                 root->execute ( act );
00316                             }
00317                 root->execute<VisualUpdateVisitor>();
00318             }
00319 
00321             void Simulation::reset ( Node* root )
00322             {
00323                 if ( !root ) return;
00324                              
00325                 root->execute<ResetVisitor>();
00326                 root->execute<MechanicalPropagatePositionAndVelocityVisitor>();
00327                 root->execute<UpdateMappingVisitor>();
00328                                 root->execute<VisualUpdateVisitor>();
00329             }
00330 
00332             void Simulation::initTextures ( Node* root )
00333             {
00334                 if ( !root ) return;
00335                 root->execute<VisualInitVisitor>();
00336                 // Do a visual update now as it is not done in load() anymore
00338                 root->execute<VisualUpdateVisitor>();
00339             }
00340 
00341 
00343             void Simulation::computeBBox ( Node* root, SReal* minBBox, SReal* maxBBox )
00344             {
00345                 VisualComputeBBoxVisitor act;
00346                 if ( root )
00347                     root->execute ( act );
00348                 minBBox[0] = (SReal)(act.minBBox[0]);
00349                 minBBox[1] = (SReal)(act.minBBox[1]);
00350                 minBBox[2] = (SReal)(act.minBBox[2]);
00351                 maxBBox[0] = (SReal)(act.maxBBox[0]);
00352                 maxBBox[1] = (SReal)(act.maxBBox[1]);
00353                 maxBBox[2] = (SReal)(act.maxBBox[2]);
00354             }
00355 
00357             void Simulation::updateContext ( Node* root )
00358             {
00359                 if ( !root ) return;
00360                 root->execute<UpdateContextVisitor>();
00361             }
00362             
00364             void Simulation::updateVisualContext ( Node* root, int FILTER)
00365             {
00366               if ( !root ) return;
00367               UpdateVisualContextVisitor vis(FILTER);
00368               vis.execute(root);              
00369             }
00371             void Simulation::draw ( Node* root )
00372             {
00373                 if ( !root ) return;
00374                 VisualDrawVisitor act ( core::VisualModel::Std );
00375                 root->execute ( &act );
00376 
00377                 VisualDrawVisitor act2 ( core::VisualModel::Transparent );
00378                 root->execute ( &act2 );
00379             }
00380 
00382             void Simulation::drawShadows ( Node* root )
00383             {
00384                 if ( !root ) return;
00385                 //std::cout << "drawShadows\n";
00386                 VisualDrawVisitor act ( core::VisualModel::Shadow );
00387                 root->execute ( &act );
00388             }
00389 
00391             void Simulation::unload ( GNode* root )
00392             {
00393                 if ( !root ) return;
00394                 instruments.clear();
00395                 instrumentInUse.setValue(-1);
00396                 root->execute<CleanupVisitor>();
00397                 root->execute<DeleteVisitor>();
00398                 if ( root->getParent() !=NULL )
00399                     root->getParent()->removeChild ( root );
00400                 delete root;
00401             }
00402 
00404             void Simulation::exportOBJ ( Node* root, const char* filename, bool exportMTL )
00405             {
00406                 if ( !root ) return;
00407                 std::ofstream fout ( filename );
00408 
00409                 fout << "# Generated from SOFA Simulation" << std::endl;
00410 
00411                 if ( !exportMTL )
00412                 {
00413                     ExportOBJVisitor act ( &fout );
00414                     root->execute ( &act );
00415                 }
00416                 else
00417                 {
00418                     const char *path1 = strrchr ( filename, '/' );
00419                     const char *path2 = strrchr ( filename, '\\' );
00420                     const char* path = ( path1==NULL ) ? ( ( path2==NULL ) ?filename : path2+1 ) : ( path2==NULL ) ? path1+1 : ( ( path1-filename ) > ( path2-filename ) ) ? path1+1 : path2+1;
00421 
00422                     const char *ext = strrchr ( path, '.' );
00423 
00424                     if ( !ext ) ext = path + strlen ( path );
00425                     std::string mtlfilename ( path, ext );
00426                     mtlfilename += ".mtl";
00427                     std::string mtlpathname ( filename, ext );
00428                     mtlpathname += ".mtl";
00429                     std::ofstream mtl ( mtlpathname.c_str() );
00430                     mtl << "# Generated from SOFA Simulation" << std::endl;
00431                     fout << "mtllib "<<mtlfilename<<'\n';
00432 
00433                     ExportOBJVisitor act ( &fout,&mtl );
00434                     root->execute ( &act );
00435                 }
00436             }
00437 
00439             void Simulation::exportXML ( Node* root, const char* filename )
00440             {
00441                 if ( !root ) return;
00442                 std::ofstream fout ( filename );
00443                 XMLPrintVisitor act ( fout );
00444                 root->execute ( &act );
00445             }
00446 
00447             void Simulation::dumpState ( Node* root, std::ofstream& out )
00448             {
00449                 out<<root->getTime() <<" ";
00450                 WriteStateVisitor ( out ).execute ( root );
00451                 out<<endl;
00452             }
00453 
00455             void Simulation::initGnuplot ( Node* root )
00456             {
00457                 if ( !root ) return;
00458                 InitGnuplotVisitor v(gnuplotDirectory.getValue());
00459                 root->execute( v );
00460             }
00461 
00463             void Simulation::exportGnuplot ( Node* root, double time )
00464             {
00465                 if ( !root ) return;
00466                 ExportGnuplotVisitor expg ( time );
00467                 root->execute ( expg );
00468             }
00469 
00470 
00471             SOFA_DECL_CLASS ( Simulation );
00472 // Register in the Factory
00473             int SimulationClass = core::RegisterObject ( "Main simulation algorithm" )
00474                                   .add< Simulation >()
00475                                   ;
00476 
00477 
00478 
00479         } // namespace tree
00480 
00481     } // namespace simulation
00482 
00483 } // namespace sofa
00484 

Generated on Sun Nov 23 04:05:48 2008 for Sofa by  doxygen 1.5.7.1