Merge branch 'python_singleton' of github.com:introlab/rtabmap into gtest

This commit is contained in:
matlabbe
2026-05-26 20:52:31 -07:00
12 changed files with 48 additions and 52 deletions
+12 -4
View File
@@ -21,16 +21,24 @@ class gil_scoped_release;
namespace rtabmap {
/**
* Create a single PythonInterface on main thread at
* global scope before any Python classes.
* Process-wide singleton owning the embedded Python interpreter.
* Call PythonInterface::instance() from the main thread (typically near
* the top of main()) before any Python-using class is constructed.
*/
class RTABMAP_CORE_EXPORT PythonInterface
{
public:
PythonInterface();
virtual ~PythonInterface();
// Pass a caller tag (e.g. class name) so the main-thread assertion
// can report who triggered the first construction.
static PythonInterface & instance(const std::string & caller = "");
PythonInterface(const PythonInterface &) = delete;
PythonInterface & operator=(const PythonInterface &) = delete;
private:
explicit PythonInterface(const std::string & caller);
~PythonInterface();
pybind11::scoped_interpreter* guard_;
pybind11::gil_scoped_release* release_;
};
-6
View File
@@ -50,7 +50,6 @@ class Memory;
class BayesFilter;
class Signature;
class Optimizer;
class PythonInterface;
/**
* @class Rtabmap
@@ -1040,11 +1039,6 @@ private:
Transform _pathTransformToGoal;
int _pathStuckCount;
float _pathStuckDistance;
#ifdef RTABMAP_PYTHON
PythonInterface * _python;
#endif
};
} // namespace rtabmap
+6 -3
View File
@@ -181,10 +181,13 @@ Rtabmap::Rtabmap() :
_pathTransformToGoal(Transform::getIdentity()),
_pathStuckCount(0),
_pathStuckDistance(0.0f)
#ifdef RTABMAP_PYTHON
,_python(new PythonInterface())
#endif
{
#ifdef RTABMAP_PYTHON
// Ensure the embedded Python interpreter is up. The first call here will
// assert that it runs on the main thread; callers building Rtabmap on a
// worker thread should construct the singleton in main() beforehand.
PythonInterface::instance("Rtabmap");
#endif
}
Rtabmap::~Rtabmap() {
+1
View File
@@ -23,6 +23,7 @@ PyDescriptor::PyDescriptor(
dim_(Parameters::defaultPyDescriptorDim())
{
UDEBUG("");
PythonInterface::instance("PyDescriptor");
this->parseParameters(parameters);
}
+1
View File
@@ -24,6 +24,7 @@ PyDetector::PyDetector(const ParametersMap & parameters) :
path_(Parameters::defaultPyDetectorPath()),
cuda_(Parameters::defaultPyDetectorCuda())
{
PythonInterface::instance("PyDetector");
this->parseParameters(parameters);
UDEBUG("path = %s", path_.c_str());
+1
View File
@@ -30,6 +30,7 @@ PyMatcher::PyMatcher(
iterations_(iterations),
cuda_(cuda)
{
PythonInterface::instance("PyMatcher");
path_ = uReplaceChar(pythonMatcherPath, '~', UDirectory::homeDir());
model_ = uReplaceChar(model, '~', UDirectory::homeDir());
UINFO("path = %s", path_.c_str());
+27 -2
View File
@@ -8,14 +8,39 @@
#include <rtabmap/core/PythonInterface.h>
#include <rtabmap/utilite/ULogger.h>
#include <rtabmap/utilite/UThread.h>
#include <rtabmap/utilite/UConversion.h>
#include <pybind11/embed.h>
#include <filesystem>
#include <thread>
namespace rtabmap {
PythonInterface::PythonInterface()
namespace {
// Captured when librtabmap_core is loaded. The dynamic loader runs static
// initializers on the main thread before main(), so this records the main
// thread id (as long as the library isn't dlopen'd from a worker thread).
const std::thread::id g_mainThreadId = std::this_thread::get_id();
}
PythonInterface & PythonInterface::instance(const std::string & caller)
{
UINFO("Initialize python interpreter");
// Meyers singleton: thread-safe construction in C++11, destroyed at exit.
// The constructor asserts it runs on the main thread; the caller tag
// from the first invocation is captured into the assertion message.
static PythonInterface inst(caller);
return inst;
}
PythonInterface::PythonInterface(const std::string & caller)
{
UASSERT_MSG(std::this_thread::get_id() == g_mainThreadId,
uFormat("PythonInterface must be created on the main thread "
"(first construction triggered by \"%s\"). Call "
"PythonInterface::instance() early in main() before "
"any worker thread touches a Python-backed class.",
caller.empty()?"<unspecified>":caller.c_str()).c_str());
UINFO("Initialize python interpreter (triggered by \"%s\")",
caller.empty()?"<unspecified>":caller.c_str());
guard_ = new pybind11::scoped_interpreter();
// Tell Python to look in this directory for DLLs
-8
View File
@@ -40,10 +40,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <pcl/filters/filter.h>
#include <rtabmap/core/SensorCaptureThread.h>
#ifdef RTABMAP_PYTHON
#include "rtabmap/core/PythonInterface.h"
#endif
#include "MapBuilder.h"
void showUsage()
@@ -77,10 +73,6 @@ int main(int argc, char * argv[])
ULogger::setType(ULogger::kTypeConsole);
ULogger::setLevel(ULogger::kInfo);
#ifdef RTABMAP_PYTHON
PythonInterface python; // Make sure we initialize python in main thread
#endif
int driver = 0;
if(argc < 2)
{
-8
View File
@@ -36,10 +36,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <QApplication>
#include <stdio.h>
#ifdef RTABMAP_PYTHON
#include "rtabmap/core/PythonInterface.h"
#endif
#include "MapBuilderWifi.h"
#include "WifiThread.h"
@@ -61,10 +57,6 @@ int main(int argc, char * argv[])
ULogger::setType(ULogger::kTypeConsole);
ULogger::setLevel(ULogger::kWarning);
#ifdef RTABMAP_PYTHON
PythonInterface python; // Make sure we initialize python in main thread
#endif
std::string interfaceName = "wlan0";
int driver = 0;
bool mirroring = false;
-7
View File
@@ -28,9 +28,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <QApplication>
#include "rtabmap/gui/DatabaseViewer.h"
#include "rtabmap/utilite/ULogger.h"
#ifdef RTABMAP_PYTHON
#include <rtabmap/core/PythonInterface.h>
#endif
#include <vtkObject.h>
#include <vtkVersionMacros.h>
@@ -53,10 +50,6 @@ int main(int argc, char * argv[])
QSurfaceFormat::setDefaultFormat(QVTKRenderWidget::defaultFormat());
#endif
#ifdef RTABMAP_PYTHON
rtabmap::PythonInterface pythonInterface;
#endif
QApplication * app = new QApplication(argc, argv);
rtabmap::DatabaseViewer * mainWindow = new rtabmap::DatabaseViewer();
-7
View File
@@ -42,9 +42,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <rtabmap/utilite/UFile.h>
#include <rtabmap/utilite/UStl.h>
#include <rtabmap/utilite/UTimer.h>
#ifdef RTABMAP_PYTHON
#include <rtabmap/core/PythonInterface.h>
#endif
#include <fstream>
#include <string>
#include <QApplication>
@@ -186,10 +183,6 @@ int main(int argc, char * argv[])
printf(" --raw (images will be rectified)\n");
}
#ifdef RTABMAP_PYTHON
rtabmap::PythonInterface pythonInterface;
#endif
ParametersMap parameters = Parameters::parseArguments(argc, argv);
parameters.insert(ParametersPair(Parameters::kRegRepeatOnce(), "false"));
-7
View File
@@ -37,9 +37,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <rtabmap/utilite/UTimer.h>
#include <rtabmap/utilite/UFile.h>
#include <rtabmap/utilite/UStl.h>
#ifdef RTABMAP_PYTHON
#include <rtabmap/core/PythonInterface.h>
#endif
#include <pcl/filters/filter.h>
#include <pcl/io/ply_io.h>
#include <pcl/io/obj_io.h>
@@ -119,10 +116,6 @@ int main(int argc, char * argv[])
printf(" keep_linked = %s\n", keepLinked?"true":"false");
printf(" pre_cleanup = %s\n", preCleanup?"true":"false");
#ifdef RTABMAP_PYTHON
rtabmap::PythonInterface pythonInterface;
#endif
// Just parse logging options
Parameters::parseArguments(argc, argv);