Home › Forum › SOFA › Programming with SOFA › [SOLVED] Load a Python scene from a C++ unit test
Tagged: 64_bits, c++, gil, Linux_other, python, scene, SOFA_1712, unit testing
- This topic has 2 replies, 2 voices, and was last updated 6 years, 2 months ago by Ant0nin.
-
AuthorPosts
-
11 September 2018 at 16:24 #11926Ant0ninBlocked
Hi guys,
I wrote a simple unit test in C++ using GUnit as recommanded in the documentation. In the code example given in https://www.sofa-framework.org/community/doc/programming-with-sofa/contribute-to-sofa/writing-tests/ there is a function called
sceneLoad()
which is able to load an existing XML scene. However, when I try to load a valid Python scene in the same way, an error occurs at the instructionPythonEnvironment::gil lock(__func__);
located at the beginning of the methodSceneLoaderPY::loadSceneWithArguments
. So the error seems to be related to the Python GIL (Global Interpreter Lock), and it says:Fatal Python error: PyEval_SaveThread: NULL tstate
. Maybe I missed an initialization or something about the SofaPython plugin. I had a look in the file applications/projects/runSofa/Main.cpp to try to understand what is wrong in my code but I still struggle to figure it out. I also looked for another examples in some SOFA plugins but I have only seen XML file scene loading at the moment. Is someone has already encounters this issue? What is the correct way to load a Python scene in C++?Here is my C++ code:
#include <SofaTest/Sofa_test.h> #include <SofaTest/TestMessageHandler.h> #include <SofaPython/SceneLoaderPY.h> #include <SofaSimulationGraph/init.h> #include <SofaSimulationGraph/DAGSimulation.h> #include <string> #include <chrono> namespace sofa { using namespace defaulttype; using namespace sofa::helper::testing; using namespace simulation; using namespace sofa::gui; template< typename DataTypes > struct SuctionCup_benchmark :public BaseSimulationTest { /// Root of the scene graph Node::SPtr root; Simulation* simulation; void onSetUp() { sofa::simulation::graph::init(); sofa::simulation::setSimulation(simulation = new sofa::simulation::graph::DAGSimulation()); } void sceneLoad() { std::string sceneFilename = std::string("/home/abernard/Workspace/suction_cup/examples/scene_08.py"); root = sofa::simulation::getSimulation()->load(sceneFilename.c_str()); } void onTearDown() { if (root!=NULL) sofa::simulation::getSimulation()->unload(root); } void initScene() { sofa::simulation::getSimulation()->init(root.get()); } bool simpleBenchmark() { using namespace std::chrono; high_resolution_clock::time_point t0 = high_resolution_clock::now(); // Run the simulation this->runSimulationSteps(); high_resolution_clock::time_point t1 = high_resolution_clock::now(); duration<double> time_span = duration_cast<duration<double>>(t1 - t0); EXPECT_LT(time_span.count(), 10.0); } void runSimulationSteps() { float timeStep = 0.1; float timeEvaluation = 10.0; //Animate simulation unsigned int nbSteps = timeEvaluation/timeStep; unsigned int stepId; for (stepId = 0; stepId < nbSteps; ++stepId) sofa::simulation::getSimulation()->animate(root.get(),timeStep); } }; using testing::Types; typedef Types< Vec3Types > DataTypes; TYPED_TEST_CASE(SuctionCup_benchmark, DataTypes); TYPED_TEST( SuctionCup_benchmark, benchmark_1) { this->onSetUp(); this->sceneLoad(); this->initScene(); ASSERT_TRUE( this->simpleBenchmark() ); this->onTearDown(); } } // namespace sofa
My operating system is Fedora 26.
11 September 2018 at 19:39 #11929HugoKeymasterHey @ant0nin
I never did such a full-python test scene. I would rather 1) create a usual simulation, as you are doing with
sofa::simulation::setSimulation(simulation = new sofa::simulation::graph::DAGSimulation());
2) add a RequiredPlugin component loading the SofaPython.so library in your root node and 3) add a PythonScriptController loading your python script.Have you tried this?
Cheers,Hugo
17 September 2018 at 18:36 #11957Ant0ninBlockedThank you @hugo (and sorry for the late answer). I tried your solution but the problem is the same (I obtained the same error about GIL). But, I created a classical XML file scene (.scn) containing a PythonScriptController component which is configured to load my python controller. With this setup, when I try to load the XML file scene on C++ side, it works well!
-
AuthorPosts
- You must be logged in to reply to this topic.