00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
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
00093 helper::system::SetDirectory chdir ( filename );
00094
00095 #ifndef WIN32
00096
00097 setlocale(LC_ALL,"C");
00098 setlocale(LC_NUMERIC,"C");
00099 #endif
00100
00101
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
00116
00117
00118 FindByTypeVisitor<Simulation> findSimu;
00119 findSimu.execute(root);
00120 if( !findSimu.found.empty() )
00121 setSimulation( findSimu.found[0] );
00122
00123
00124 getSimulation()->init ( root );
00125
00126
00127
00128
00129
00130 return root;
00131 }
00132
00134 GNode* Simulation::loadFromMemory ( const char *filename, const char *data, unsigned int size )
00135 {
00136
00137
00138 xml::BaseElement* xml = xml::loadFromMemory (filename, data, size );
00139
00140 GNode* root = processXML(xml, filename);
00141
00142
00143 delete xml;
00144
00145 return root;
00146 }
00147
00148
00150 GNode* Simulation::loadFromFile ( const char *filename )
00151 {
00152
00153
00154 xml::BaseElement* xml = xml::loadFromFile ( filename );
00155
00156 GNode* root = processXML(xml, filename);
00157
00158
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
00175
00176 args.push_back(std::string("-f" + std::string(filename)));
00177
00178 std::string newFilename="";
00179
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
00253 setContext( root->getContext());
00254 if ( !root ) return;
00255 root->execute<InitVisitor>();
00256
00257 root->execute<MechanicalPropagatePositionAndVelocityVisitor>();
00258 root->execute<MechanicalPropagateFreePositionVisitor>();
00259 root->execute<StoreResetStateVisitor>();
00260
00261
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
00287 double startTime = root->getTime();
00288 double mechanicalDt = dt/numMechSteps.getValue();
00289
00290
00291
00292
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
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
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
00473 int SimulationClass = core::RegisterObject ( "Main simulation algorithm" )
00474 .add< Simulation >()
00475 ;
00476
00477
00478
00479 }
00480
00481 }
00482
00483 }
00484