Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • ostasse/dynamic-graph-python
  • gsaurel/dynamic-graph-python
  • stack-of-tasks/dynamic-graph-python
3 results
Show changes
Showing
with 637 additions and 1090 deletions
#ifndef DYNAMIC_GRAPH_PY
#define DYNAMIC_GRAPH_PY
#include <dynamic-graph/debug.h>
#include <dynamic-graph/exception-factory.h>
#include <dynamic-graph/signal-base.h>
#include <boost/python.hpp>
#include <boost/python/stl_iterator.hpp>
#include <iostream>
#include <sstream>
#include "dynamic-graph/python/signal-wrapper.hh"
namespace bp = boost::python;
namespace dynamicgraph {
namespace python {
template <typename Iterator>
inline bp::list to_py_list(Iterator begin, Iterator end) {
typedef typename Iterator::value_type T;
bp::list lst;
std::for_each(begin, end, [&](const T& t) { lst.append(t); });
return lst;
}
template <typename Iterator>
inline bp::tuple to_py_tuple(Iterator begin, Iterator end) {
return bp::tuple(to_py_list(begin, end));
}
template <typename T>
inline std::vector<T> to_std_vector(const bp::object& iterable) {
return std::vector<T>(bp::stl_input_iterator<T>(iterable),
bp::stl_input_iterator<T>());
}
void exposeSignals();
// Declare functions defined in other source files
namespace signalBase {
SignalBase<int>* createSignalWrapper(const char* name, const char* type,
bp::object object);
} // namespace signalBase
namespace entity {
/// \param obj an Entity object
void addCommands(boost::python::object obj);
void addSignals(boost::python::object obj);
Entity* create(const char* type, const char* name);
bp::object executeCmd(bp::tuple args, bp::dict);
} // namespace entity
namespace factory {
bp::tuple getEntityClassList();
}
namespace pool {
void writeGraph(const char* filename);
bp::list getEntityList();
const std::map<std::string, Entity*>* getEntityMap();
} // namespace pool
namespace debug {
void addLoggerFileOutputStream(const char* filename);
void addLoggerCoutOutputStream();
void closeLoggerFileOutputStream();
void realTimeLoggerSpinOnce();
void realTimeLoggerDestroy();
void realTimeLoggerInstance();
} // namespace debug
} // namespace python
} // namespace dynamicgraph
#endif
// -*- mode: c++ -*-
// Copyright 2010, François Bleibel, Thomas Moulard, Olivier Stasse,
// JRL, CNRS/AIST.
//
// This file is part of dynamic-graph.
// dynamic-graph is free software: you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public License
// as published by the Free Software Foundation, either version 3 of
// the License, or (at your option) any later version.
//
// dynamic-graph is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Lesser Public License for more details. You should have
// received a copy of the GNU Lesser General Public License along with
// dynamic-graph. If not, see <http://www.gnu.org/licenses/>.
#ifndef DYNAMIC_GRAPH_PYTHON_EXCEPTION_PYTHON_H
# define DYNAMIC_GRAPH_PYTHON_EXCEPTION_PYTHON_H
# include <string>
# include <dynamic-graph/fwd.hh>
# include <dynamic-graph/exception-abstract.h>
// Depending on whether one is building or using the
// library define DLLAPI to import or export.
# if defined (WIN32)
# if defined (wrap_EXPORTS)
# define WRAP_DLLAPI __declspec(dllexport)
# else
# define WRAP_DLLAPI __declspec(dllimport)
# endif
# else
# define WRAP_DLLAPI
# endif
namespace dynamicgraph {
namespace python {
/// \ingroup error
///
/// \brief Generic error class.
class WRAP_DLLAPI ExceptionPython : public ExceptionAbstract
{
public:
enum ErrorCodeEnum
{
GENERIC
,VALUE_PARSING
,VECTOR_PARSING
,MATRIX_PARSING
,CLASS_INCONSISTENT
};
static const std::string EXCEPTION_NAME;
explicit ExceptionPython (const ExceptionPython::ErrorCodeEnum& errcode,
const std::string & msg = "");
ExceptionPython (const ExceptionPython::ErrorCodeEnum& errcode,
const std::string& msg, const char* format, ...);
virtual ~ExceptionPython () throw ()
{}
virtual const std::string& getExceptionName () const
{
return ExceptionPython::EXCEPTION_NAME;
}
};
} // end of namespace python
} // end of namespace dynamicgraph
#endif //! DYNAMIC_GRAPH_PYTHON_EXCEPTION_PYTHON_H
/*
* Copyright CNRS 2021
*
* Author: Florent Lamiraux
*
* This file is part of sot-core.
*/
#ifndef DYNAMIC_GRAPH_PYTHON_FWD_HH
#define DYNAMIC_GRAPH_PYTHON_FWD_HH
#include <dynamic-graph/fwd.hh>
namespace dynamicgraph {
namespace python {
class Interpreter;
typedef shared_ptr<Interpreter> InterpreterPtr_t;
} // namespace python
} // namespace dynamicgraph
#endif // DYNAMIC_GRAPH_PYTHON_FWD_HH
// -*- mode: c++ -*-
// Copyright 2011, Florent Lamiraux, CNRS.
//
// This file is part of dynamic-graph-python.
// dynamic-graph is free software: you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public License
// as published by the Free Software Foundation, either version 3 of
// the License, or (at your option) any later version.
//
// dynamic-graph is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Lesser Public License for more details. You should have
// received a copy of the GNU Lesser General Public License along with
// dynamic-graph. If not, see <http://www.gnu.org/licenses/>.
#ifndef DYNAMIC_GRAPH_PYTHON_INTERPRETER_H
#define DYNAMIC_GRAPH_PYTHON_INTERPRETER_H
#undef _POSIX_C_SOURCE
#undef _XOPEN_SOURCE
#include <Python.h>
#include <string>
#include "dynamic-graph/python/api.hh"
#include "dynamic-graph/python/deprecated.hh"
#ifndef DYNAMIC_GRAPH_PYTHON_INTERPRETER_H
# define DYNAMIC_GRAPH_PYTHON_INTERPRETER_H
#include <dynamic-graph/python/fwd.hh>
#include "dynamic-graph/python/api.hh"
#include "dynamic-graph/python/python-compat.hh"
namespace dynamicgraph {
namespace python {
///
/// This class implements a basis python interpreter.
///
/// String sent to method python are interpreted by an onboard python
/// interpreter.
class DYNAMIC_GRAPH_PYTHON_DLLAPI Interpreter
{
public:
Interpreter();
~Interpreter();
/// \brief Method to start python interperter.
/// \param command string to execute
/// Method deprecated, you *SHOULD* handle error messages.
DYNAMIC_GRAPH_PYTHON_DEPRECATED std::string python( const std::string& command );
/// \brief Method to start python interperter.
/// \param command string to execute, result, stdout, stderr strings
void python( const std::string& command , std::string& result,
std::string& out, std::string& err);
/// \brief Method to exectue a python script.
/// \param filename the filename
void runPythonFile( std::string filename );
void runPythonFile( std::string filename, std::string& err);
void runMain( void );
/// \brief Process input stream to send relevant blocks to python
/// \param stream input stream
std::string processStream(std::istream& stream, std::ostream& os);
/// \brief Return a pointer to the dictionary of global variables
PyObject* globals();
private:
/// The Pythone thread state
PyThreadState *_pyState;
/// Pointer to the dictionary of global variables
PyObject* globals_;
/// Pointer to the dictionary of local variables
PyObject* locals_;
PyObject* mainmod_;
PyObject* traceback_format_exception_;
};
} // namespace python
} // namespace dynamicgraph
#endif // DYNAMIC_GRAPH_PYTHON_INTERPRETER_H
namespace python {
///
/// This class implements a basis python interpreter.
///
/// String sent to method python are interpreted by an onboard python
/// interpreter.
class DYNAMIC_GRAPH_PYTHON_DLLAPI Interpreter {
public:
Interpreter();
~Interpreter();
/// \brief Method to start python interperter.
/// \param command string to execute
/// Method deprecated, you *SHOULD* handle error messages.
[[deprecated("you *SHOULD* handle error messages")]] std::string python(
const std::string& command);
/// \brief Method to start python interperter.
/// \param command string to execute, result, stdout, stderr strings
void python(const std::string& command, std::string& result, std::string& out,
std::string& err);
/// \brief Method to exectue a python script.
/// \param filename the filename
void runPythonFile(std::string filename);
void runPythonFile(std::string filename, std::string& err);
void runMain(void);
/// \brief Process input stream to send relevant blocks to python
/// \param stream input stream
std::string processStream(std::istream& stream, std::ostream& os);
/// \brief Return a pointer to the dictionary of global variables
PyObject* globals();
private:
/// The Python thread state
PyThreadState* _pyState;
/// Pointer to the dictionary of global variables
PyObject* globals_;
/// Pointer to the dictionary of local variables
PyObject* locals_;
PyObject* mainmod_;
};
} // namespace python
} // namespace dynamicgraph
#endif // DYNAMIC_GRAPH_PYTHON_INTERPRETER_H
#ifndef DYNAMIC_GRAPH_PYTHON_MODULE_HH
#define DYNAMIC_GRAPH_PYTHON_MODULE_HH
#ifdef PINOCCHIO_WITH_URDFDOM
// If pinocchio is used, we have to include pinocchio header before boost mpl
#include <pinocchio/fwd.hpp>
#endif
#include <dynamic-graph/entity.h>
#include <boost/mpl/for_each.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/python.hpp>
#include <dynamic-graph/python/dynamic-graph-py.hh>
namespace dynamicgraph {
namespace python {
constexpr int AddSignals = 1;
constexpr int AddCommands = 2;
namespace internal {
template <typename T, int Options = AddCommands | AddSignals>
bp::object makeEntity1(const char* name) {
Entity* ent = entity::create(T::CLASS_NAME.c_str(), name);
assert(dynamic_cast<T*>(ent) != NULL);
bp::object obj(bp::ptr(static_cast<T*>(ent)));
if (Options & AddCommands) entity::addCommands(obj);
if (Options & AddSignals) entity::addSignals(obj);
return obj;
}
template <typename T, int Options = AddCommands | AddSignals>
bp::object makeEntity2() {
return makeEntity1<T, Options>("");
}
} // namespace internal
/// \tparam Options by default, all the signals and commands are added as
/// attribute to the Python object. This behaviour works fine for
/// entities that have static commands and signals.
/// If some commands or signals are added or removed dynamiccally, then
/// it is better to disable the default behaviour and handle it
/// specifically.
template <typename T,
typename bases = boost::python::bases<dynamicgraph::Entity>,
int Options = AddCommands | AddSignals>
inline auto exposeEntity() {
// std::string hiddenClassName ("_" + T::CLASS_NAME);
std::string hiddenClassName(T::CLASS_NAME);
namespace bp = boost::python;
bp::class_<T, bases, boost::noncopyable> obj(hiddenClassName.c_str(),
bp::init<std::string>());
/* TODO at the moment, I couldn't easily find a way to define a Python
constructor
* that would create the entity via the factory and then populate the
* python object with its commands.
* This is achieved with a factory function of the same name.
obj.def ("__init__", bp::raw_function(+[](bp::object args, bp::dict) {
if (bp::len(args) != 2)
throw std::length_error("Expected 2 arguments.");
bp::object self = args[0];
self.attr("__init__")(bp::extract<std::string>(args[1]));
Entity* ent = entity::create(T::CLASS_NAME.c_str(), name);
if (dynamic_cast<T*>(ent) == NULL)
std::cout << "foo" << std::endl;
assert(dynamic_cast<T*>(ent) != NULL);
self = bp::object(bp::ptr(static_cast<T*>(ent)));
//dynamicgraph::Entity& unused =
bp::extract<dynamicgraph::Entity&>(self);
//entity::addCommands(self);
})
;
*/
bp::def(T::CLASS_NAME.c_str(), &internal::makeEntity1<T, Options>);
bp::def(T::CLASS_NAME.c_str(), &internal::makeEntity2<T, Options>);
if (!(Options & AddCommands)) obj.def("add_commands", &entity::addCommands);
if (!(Options & AddSignals)) obj.def("add_signals", &entity::addSignals);
return obj;
}
} // namespace python
} // namespace dynamicgraph
#endif // DYNAMIC_GRAPH_PYTHON_MODULE_HH
#ifndef DGPY_PYTHON_COMPAT_H
#define DGPY_PYTHON_COMPAT_H
#include <string>
#define PY_SSIZE_T_CLEAN
#include <Python.h>
// Get any PyObject and get its str() representation as an std::string
std::string obj_to_str(PyObject* o);
#endif
// Copyright (c) 2018, Joseph Mirabel
// Authors: Joseph Mirabel (joseph.mirabel@laas.fr)
#ifndef DGPY_SIGNAL_WRAPPER
#define DGPY_SIGNAL_WRAPPER
#include <dynamic-graph/entity.h>
#include <dynamic-graph/linear-algebra.h>
#include <dynamic-graph/signal.h>
#include <boost/bind.hpp>
#include <boost/python.hpp>
#include "dynamic-graph/python/python-compat.hh"
namespace dynamicgraph {
namespace python {
class PythonSignalContainer : public Entity {
DYNAMIC_GRAPH_ENTITY_DECL();
public:
using Entity::Entity;
void signalRegistration(const SignalArray<int>& signals);
void rmSignal(const std::string& name);
};
template <class T, class Time>
class SignalWrapper : public Signal<T, Time> {
public:
typedef Signal<T, Time> parent_t;
typedef boost::python::object pyobject;
static bool checkCallable(pyobject c, std::string& error);
SignalWrapper(std::string name, pyobject callable)
: parent_t(name), callable(callable) {
typedef boost::function2<T&, T&, Time> function_t;
function_t f = boost::bind(&SignalWrapper::call, this, _1, _2);
this->setFunction(f);
}
virtual ~SignalWrapper(){};
private:
T& call(T& value, Time t) {
PyGILState_STATE gstate;
gstate = PyGILState_Ensure();
if (PyGILState_GetThisThreadState() == NULL) {
dgDEBUG(10) << "python thread not initialized" << std::endl;
}
pyobject obj = callable(t);
value = boost::python::extract<T>(obj);
PyGILState_Release(gstate);
return value;
}
pyobject callable;
};
} // namespace python
} // namespace dynamicgraph
#endif
// Copyright 2020, Joseph Mirabel, LAAS-CNRS.
#include <dynamic-graph/signal-base.h>
#include <dynamic-graph/signal-ptr.h>
#include <dynamic-graph/signal-time-dependent.h>
#include <dynamic-graph/signal.h>
#include <boost/python.hpp>
#include <sstream>
#include "dynamic-graph/python/signal-wrapper.hh"
namespace dynamicgraph {
namespace python {
template <typename T, typename Time>
auto exposeSignal(const std::string& name) {
namespace bp = boost::python;
typedef Signal<T, Time> S_t;
bp::class_<S_t, bp::bases<SignalBase<Time> >, boost::noncopyable> obj(
name.c_str(), bp::init<std::string>());
obj.add_property(
"value",
bp::make_function(&S_t::accessCopy,
bp::return_value_policy<bp::copy_const_reference>()),
&S_t::setConstant, // TODO check the setter
"the signal value.\n"
"warning: for Eigen objects, sig.value[0] = 1. may not work).");
return obj;
}
template <typename T, typename Time>
auto exposeSignalWrapper(const std::string& name) {
namespace bp = boost::python;
typedef SignalWrapper<T, Time> S_t;
bp::class_<S_t, bp::bases<Signal<T, Time> >, boost::noncopyable> obj(
name.c_str(), bp::no_init);
return obj;
}
template <typename T, typename Time>
auto exposeSignalPtr(const std::string& name) {
namespace bp = boost::python;
typedef SignalPtr<T, Time> S_t;
bp::class_<S_t, bp::bases<Signal<T, Time> >, boost::noncopyable> obj(
name.c_str(), bp::no_init);
return obj;
}
template <typename T, typename Time>
auto exposeSignalTimeDependent(const std::string& name) {
namespace bp = boost::python;
typedef SignalTimeDependent<T, Time> S_t;
bp::class_<S_t, bp::bases<Signal<T, Time> >, boost::noncopyable> obj(
name.c_str(), bp::no_init);
return obj;
}
template <typename T, typename Time>
void exposeSignalsOfType(const std::string& name) {
exposeSignal<T, Time>("Signal" + name);
exposeSignalPtr<T, Time>("SignalPtr" + name);
exposeSignalWrapper<T, Time>("SignalWrapper" + name);
exposeSignalTimeDependent<T, Time>("SignalTimeDependent" + name);
}
} // namespace python
} // namespace dynamicgraph
<?xml version="1.0"?>
<package format="3">
<name>dynamic-graph-python</name>
<version>4.0.11</version>
<description>Dynamic graph library Python bindings</description>
<maintainer email="guilhem.saurel@laas.fr">Guilhem Saurel</maintainer>
<author>Nicolas Mansard</author>
<author>Olivier Stasse</author>
<license>BSD</license>
<url type="website">https://github.com/stack-of-tasks/dynamic-graph-python</url>
<build_depend>git</build_depend>
<build_depend>doxygen</build_depend>
<!-- The following tag is recommended by REP-136 -->
<exec_depend condition="$ROS_VERSION == 1">catkin</exec_depend>
<depend condition="$ROS_PYTHON_VERSION == 2">python</depend>
<depend condition="$ROS_PYTHON_VERSION == 3">python3</depend>
<depend condition="$ROS_PYTHON_VERSION == 2">python-numpy</depend>
<depend condition="$ROS_PYTHON_VERSION == 3">python3-numpy</depend>
<depend>eigen</depend>
<depend>boost</depend>
<depend>eigenpy</depend>
<depend>dynamic-graph</depend>
<buildtool_depend>cmake</buildtool_depend>
<export>
<build_type>cmake</build_type>
</export>
</package>
[tool.black]
exclude = "cmake"
extend-exclude = "tests/test_python-syntax_error.py"
[flake8]
exclude = cmake,tests/test_python-syntax_error.py
max-line-length = 88
ignore = E226, E704, E24, E121, W504, E126, E123, W503, E203
# Copyright 2010, 2011, Florent Lamiraux, Thomas Moulard, JRL, CNRS/AIST
#
# This file is part of dynamic-graph-python.
# dynamic-graph-python is free software: you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public License
# as published by the Free Software Foundation, either version 3 of
# the License, or (at your option) any later version.
#
# dynamic-graph-python is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Lesser Public License for more details. You should have
# received a copy of the GNU Lesser General Public License along with
# dynamic-graph-python. If not, see <http://www.gnu.org/licenses/>.
# Python bindings
#
# Python
#
add_subdirectory(dynamic_graph)
INCLUDE_DIRECTORIES(SYSTEM ${Boost_INCLUDE_DIRS})
LINK_DIRECTORIES(${Boost_LIBRARY_DIRS} ${PYTHON_LIBRARY_DIRS})
set(PYTHON_SOURCES __init__.py attrpath.py entity.py signal_base.py
script_shortcuts.py tools.py)
#
#
# Python interpreter
#
#
SET(LIBRARY_NAME ${PROJECT_NAME})
ADD_LIBRARY(${LIBRARY_NAME}
SHARED
interpreter.cc)
TARGET_LINK_LIBRARIES(${LIBRARY_NAME}
${PYTHON_LIBRARY})
TARGET_LINK_BOOST_PYTHON(${LIBRARY_NAME})
IF(UNIX)
TARGET_LINK_LIBRARIES(${LIBRARY_NAME} ${Boost_LIBRARIES})
TARGET_LINK_LIBRARIES(${LIBRARY_NAME} ${CMAKE_DL_LIBS})
ENDIF(UNIX)
SET_TARGET_PROPERTIES(${LIBRARY_NAME} PROPERTIES SOVERSION ${PROJECT_VERSION})
PKG_CONFIG_USE_DEPENDENCY(${LIBRARY_NAME} dynamic-graph)
INSTALL(TARGETS ${LIBRARY_NAME}
DESTINATION lib)
#
#
# Python bindings
#
#
SET(PYTHON_MODULE wrap)
ADD_LIBRARY(${PYTHON_MODULE}
MODULE
convert-dg-to-py.cc
debug-py.cc
dynamic-graph-py.cc
entity-py.cc
exception-python.cc
factory-py.cc
pool-py.cc
signal-base-py.cc
signal-caster-py.cc
signal-wrapper.cc
)
# Remove prefix lib
SET_TARGET_PROPERTIES(${PYTHON_MODULE}
PROPERTIES PREFIX "")
PKG_CONFIG_USE_DEPENDENCY(${PYTHON_MODULE} dynamic-graph)
#TARGET_LINK_LIBRARIES(${PYTHON_MODULE} ${PYTHON_LIBRARY})
CONFIG_FILES(link-to-python.hh)
INCLUDE_DIRECTORIES(SYSTEM ${PYTHON_INCLUDE_PATH})
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
#
# Installation
#
SET(PYTHON_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/${PYTHON_SITELIB}/dynamic_graph)
INSTALL(TARGETS ${PYTHON_MODULE}
DESTINATION
${PYTHON_INSTALL_DIR})
SET (PYTHON_SOURCES
__init__.py
attrpath.py
entity.py
signal_base.py
matlab.py
script_shortcuts.py
tools.py
)
FOREACH (SOURCE ${PYTHON_SOURCES})
PYTHON_INSTALL_ON_SITE(dynamic_graph ${SOURCE} )
ENDFOREACH (SOURCE)
foreach(source ${PYTHON_SOURCES})
python_install_on_site(dynamic_graph ${source})
endforeach(source)
# --- ADD the wrap on the dg modules
# Tracer plugin
IF(WIN32)
SET(TRACER_PLUGIN ${DYNAMIC_GRAPH_PLUGINDIR}/tracer${CMAKE_STATIC_LIBRARY_SUFFIX})
ELSE(WIN32)
SET(TRACER_PLUGIN ${DYNAMIC_GRAPH_PLUGINDIR}/tracer${CMAKE_SHARED_LIBRARY_SUFFIX})
ENDIF(WIN32)
DYNAMIC_GRAPH_PYTHON_MODULE("tracer" ${TRACER_PLUGIN} tracer-wrap)
# TracerRealTime plugin
IF(WIN32)
SET(TRACERREALTIME_PLUGIN ${DYNAMIC_GRAPH_PLUGINDIR}/tracer-real-time${CMAKE_STATIC_LIBRARY_SUFFIX})
ELSE(WIN32)
SET(TRACERREALTIME_PLUGIN ${DYNAMIC_GRAPH_PLUGINDIR}/tracer-real-time${CMAKE_SHARED_LIBRARY_SUFFIX})
ENDIF(WIN32)
DYNAMIC_GRAPH_PYTHON_MODULE("tracer_real_time" ${TRACERREALTIME_PLUGIN} tracer_real_time-wrap)
link_directories(${DYNAMIC_GRAPH_PLUGINDIR})
dynamic_graph_python_module(
"tracer" dynamic-graph::tracer tracer-wrap SOURCE_PYTHON_MODULE
${CMAKE_CURRENT_SOURCE_DIR}/dynamic_graph/tracer/wrap.cc)
dynamic_graph_python_module(
"tracer_real_time" dynamic-graph::tracer-real-time tracer_real_time-wrap
SOURCE_PYTHON_MODULE
${CMAKE_CURRENT_SOURCE_DIR}/dynamic_graph/tracer_real_time/wrap.cc)
// Copyright 2010, Florent Lamiraux, Thomas Moulard, LAAS-CNRS.
//
// This file is part of dynamic-graph-python.
// dynamic-graph-python is free software: you can redistribute it
// and/or modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation, either
// version 3 of the License, or (at your option) any later version.
//
// dynamic-graph-python is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Lesser Public License for more details. You should
// have received a copy of the GNU Lesser General Public License along
// with dynamic-graph. If not, see <http://www.gnu.org/licenses/>.
#include "../src/convert-dg-to-py.hh"
#include <iostream>
#include <sstream>
#include <dynamic-graph/signal-base.h>
#include <dynamic-graph/signal.h>
#include <dynamic-graph/signal-caster.h>
namespace dynamicgraph {
using ::dynamicgraph::SignalBase;
namespace python {
namespace convert {
void fillMatrixRow(Matrix& m, unsigned iRow, PyObject* sequence)
{
if (PySequence_Size(sequence) != (int)m.cols()) {
throw ExceptionPython(ExceptionPython::MATRIX_PARSING,
"lines of matrix have different sizes.");
}
for (int iCol=0; iCol < m.cols(); iCol++) {
PyObject* pyDouble = PySequence_GetItem(sequence, iCol);
if (PyFloat_Check(pyDouble))
m(iRow, iCol) = PyFloat_AsDouble(pyDouble);
else if(PyInt_Check(pyDouble))
m(iRow, iCol) = (int)PyInt_AS_LONG(pyDouble)+0.0;
else
throw ExceptionPython(ExceptionPython::MATRIX_PARSING,
"element of matrix should be "
"a floating point number.");
}
}
void fillMatrixRow(Eigen::Matrix4d& m, unsigned iRow, PyObject* sequence)
{
if (PySequence_Size(sequence) != (int)m.cols()) {
throw ExceptionPython(ExceptionPython::MATRIX_PARSING,
"lines of matrix have different sizes.");
}
for (int iCol=0; iCol < m.cols(); iCol++) {
PyObject* pyDouble = PySequence_GetItem(sequence, iCol);
if (PyFloat_Check(pyDouble))
m(iRow, iCol) = PyFloat_AsDouble(pyDouble);
else if(PyInt_Check(pyDouble))
m(iRow, iCol) = (int)PyInt_AS_LONG(pyDouble)+0.0;
else
throw ExceptionPython(ExceptionPython::MATRIX_PARSING,
"element of matrix should be "
"a floating point number.");
}
}
command::Value pythonToValue(PyObject* pyObject,
const command::Value::Type& valueType)
{
using command::Value;
bool bvalue;
unsigned uvalue;
int ivalue;
float fvalue;
double dvalue;
std::string svalue;
Vector v;
Matrix m;
Eigen::Matrix4d m4;
Py_ssize_t nCols;
Py_ssize_t size;
PyObject* row;
Py_ssize_t nRows;
switch (valueType) {
case (Value::BOOL) :
if (!PyBool_Check(pyObject)) {
throw ExceptionPython(ExceptionPython::VALUE_PARSING,
"bool");
}
bvalue = PyObject_IsTrue(pyObject);
return Value(bvalue);
break;
case (Value::UNSIGNED) :
if (!PyInt_Check(pyObject)) {
throw ExceptionPython(ExceptionPython::VALUE_PARSING,
"unsigned int");
}
uvalue = (unsigned int)PyInt_AsUnsignedLongMask(pyObject);
return Value(uvalue);
break;
case (Value::INT) :
if (!PyInt_Check(pyObject)) {
throw ExceptionPython(ExceptionPython::VALUE_PARSING,
"int");
}
ivalue = (int)PyInt_AS_LONG(pyObject);
return Value(ivalue);
break;
case (Value::FLOAT) :
if (PyFloat_Check(pyObject)) {
fvalue = (float)PyFloat_AsDouble(pyObject);
return Value(fvalue);
} else if (PyInt_Check(pyObject)) {
fvalue = (float)PyInt_AS_LONG(pyObject);
return Value(fvalue);
} else {
throw ExceptionPython(ExceptionPython::VALUE_PARSING,
"float");
}
break;
case (Value::DOUBLE) :
if (PyFloat_Check(pyObject)) {
dvalue = PyFloat_AsDouble(pyObject);
return Value(dvalue);
} else if (PyInt_Check(pyObject)) {
dvalue = (double)PyInt_AS_LONG(pyObject);
return Value(dvalue);
} else {
throw ExceptionPython(ExceptionPython::VALUE_PARSING,
"double");
}
break;
case (Value::STRING) :
if (!PyString_Check(pyObject)) {
throw ExceptionPython(ExceptionPython::VALUE_PARSING,
"string");
}
svalue = PyString_AsString(pyObject);
return Value(svalue);
break;
case (Value::VECTOR) :
// Check that argument is a tuple
if (!PySequence_Check(pyObject)) {
throw ExceptionPython(ExceptionPython::VALUE_PARSING,
"vector");
}
size = PySequence_Size(pyObject);
v.resize(size);
for (Py_ssize_t i=0; i<size; i++) {
PyObject* pyDouble = PySequence_GetItem(pyObject, i);
if (PyFloat_Check(pyDouble))
v(i) = PyFloat_AsDouble(pyDouble);
else if(PyInt_Check(pyDouble))
v(i) = (int)PyInt_AS_LONG(pyDouble)+0.0;
else
throw ExceptionPython(ExceptionPython::VECTOR_PARSING,
"element of vector should be a floating "
"point number.");
}
return Value(v);
break;
case (Value::MATRIX) :
// Check that argument is a tuple
if (!PySequence_Check(pyObject)) {
throw ExceptionPython(ExceptionPython::VALUE_PARSING,
"matrix");
}
nRows = PySequence_Size(pyObject);
if (nRows == 0) {
return Value(Matrix());
}
row = PySequence_GetItem(pyObject, 0);
if (!PySequence_Check(row)) {
throw ExceptionPython(ExceptionPython::MATRIX_PARSING,
"matrix");
}
nCols = PySequence_Size(row);
m.resize((unsigned int)nRows, (unsigned int)nCols);
fillMatrixRow(m, 0, row);
for (Py_ssize_t iRow=1; iRow<nRows; iRow++) {
row = PySequence_GetItem(pyObject, iRow);
if (!PySequence_Check(row)) {
throw ExceptionPython(ExceptionPython::MATRIX_PARSING,
"matrix");
}
fillMatrixRow(m, static_cast<unsigned> (iRow), row);
}
return Value(m);
break;
case (Value::MATRIX4D) :
// Check that argument is a tuple
if (!PySequence_Check(pyObject)) {
throw ExceptionPython(ExceptionPython::VALUE_PARSING,
"matrix4d");
}
nRows = PySequence_Size(pyObject);
if (nRows == 0) {
return Value(Eigen::Matrix4d());
}
row = PySequence_GetItem(pyObject, 0);
if (!PySequence_Check(row)) {
throw ExceptionPython(ExceptionPython::MATRIX_PARSING,
"matrix4d");
}
nCols = PySequence_Size(row);
m4.resize(nRows, nCols);
fillMatrixRow(m4, 0, row);
for (Py_ssize_t iRow=1; iRow<nRows; iRow++) {
row = PySequence_GetItem(pyObject, iRow);
if (!PySequence_Check(row)) {
throw ExceptionPython(ExceptionPython::MATRIX_PARSING,
"matrix");
}
fillMatrixRow(m4, static_cast<unsigned> (iRow), row);
}
return Value(m4);
break;
default:
std::cerr << "Only int, double and string are supported."
<< std::endl;
}
return Value();
}
PyObject* vectorToPython(const Vector& vector)
{
PyObject* tuple = PyTuple_New(vector.size());
for (int index = 0; index < vector.size() ; index++) {
PyObject* pyDouble = PyFloat_FromDouble(vector(index));
PyTuple_SET_ITEM(tuple, index, pyDouble);
}
return tuple;
}
PyObject* matrixToPython(const Matrix& matrix)
{
PyObject* tuple = PyTuple_New(matrix.rows());
for (int iRow = 0; iRow < matrix.rows(); iRow++) {
PyObject* row = PyTuple_New(matrix.cols());
for (int iCol=0; iCol < matrix.cols(); iCol++) {
PyObject* pyDouble = PyFloat_FromDouble(matrix(iRow, iCol));
PyTuple_SET_ITEM(row, iCol, pyDouble);
}
PyTuple_SET_ITEM(tuple, iRow, row);
}
return tuple;
}
PyObject* matrix4dToPython(const Eigen::Matrix4d& matrix)
{
PyObject* tuple = PyTuple_New(matrix.rows());
for (int iRow = 0; iRow < matrix.rows(); iRow++) {
PyObject* row = PyTuple_New(matrix.cols());
for (int iCol=0; iCol < matrix.cols(); iCol++) {
PyObject* pyDouble = PyFloat_FromDouble(matrix(iRow, iCol));
PyTuple_SET_ITEM(row, iCol, pyDouble);
}
PyTuple_SET_ITEM(tuple, iRow, row);
}
return tuple;
}
PyObject* valueToPython(const command::Value& value)
{
using command::Value;
bool boolValue;
unsigned unsignedValue;
int intValue;
float floatValue;
double doubleValue;
std::string stringValue;
Vector vectorValue;
Matrix matrixValue;
Eigen::Matrix4d matrix4dValue;
switch(value.type()) {
case (Value::BOOL) :
boolValue = value.value();
if (boolValue) {
return PyBool_FromLong(1);
}
return PyBool_FromLong(0);
case (Value::UNSIGNED) :
unsignedValue = value.value();
return Py_BuildValue("I", unsignedValue);
case (Value::INT) :
intValue = value.value();
return Py_BuildValue("i", intValue);
case (Value::FLOAT) :
floatValue = value.value();
return Py_BuildValue("f", floatValue);
case (Value::DOUBLE) :
doubleValue = value.value();
return Py_BuildValue("d", doubleValue);
case (Value::STRING) :
stringValue = (std::string) value.value();
return Py_BuildValue("s", stringValue.c_str());
case (Value::VECTOR) :
vectorValue = value.value();
return vectorToPython(vectorValue);
case (Value::MATRIX) :
matrixValue = value.value();
return matrixToPython(matrixValue);
case (Value::MATRIX4D) :
matrix4dValue = value.value();
return matrix4dToPython(matrix4dValue);
default:
return Py_BuildValue("");
}
return Py_BuildValue("");
}
} // namespace dynamicgraph
} // namespace python
} // namespace convert
// Copyright 2010, Florent Lamiraux, Thomas Moulard, LAAS-CNRS.
//
// This file is part of dynamic-graph-python.
// dynamic-graph-python is free software: you can redistribute it
// and/or modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation, either
// version 3 of the License, or (at your option) any later version.
//
// dynamic-graph-python is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Lesser Public License for more details. You should
// have received a copy of the GNU Lesser General Public License along
// with dynamic-graph. If not, see <http://www.gnu.org/licenses/>.
#include <Python.h>
#include <dynamic-graph/linear-algebra.h>
#include <dynamic-graph/value.h>
#include <dynamic-graph/python/exception-python.hh>
namespace dynamicgraph {
namespace python {
namespace convert {
command::Value pythonToValue(PyObject* pyObject,
const command::Value::Type& valueType);
PyObject* vectorToPython(const Vector& vector);
PyObject* matrixToPython(const ::dynamicgraph::Matrix& matrix);
PyObject* matrix4dToPython(const Eigen::Matrix4d& matrix);
PyObject* valueToPython(const ::dynamicgraph::command::Value& value);
} // namespace dynamicgraph
} // namespace python
}
// Copyright 2019, Olivier Stasse, LAAS-CNRS.
//
// See LICENSE
#include <iostream>
#define ENABLE_RT_LOG
#include <dynamic-graph/real-time-logger.h>
#include <map>
#include <Python.h>
#include <dynamic-graph/pool.h>
#include <dynamic-graph/entity.h>
#include <vector>
#include "exception.hh"
#include <boost/shared_ptr.hpp>
typedef boost::shared_ptr<std::ofstream> ofstreamShrPtr;
namespace dynamicgraph {
namespace python {
extern PyObject* dgpyError;
namespace debug {
std::map<std::string, ofstreamShrPtr > mapOfFiles_;
PyObject* addLoggerFileOutputStream (PyObject* /*self*/, PyObject* args)
{
char* filename;
if (!PyArg_ParseTuple(args, "s", &filename))
return NULL;
std::string sfilename(filename);
try {
std::ofstream *aofs = new std::ofstream;
ofstreamShrPtr ofs_shrptr = boost::shared_ptr<std::ofstream>(aofs);
aofs->open(filename,
std::ofstream::out);
dynamicgraph::RealTimeLogger::instance();
dgADD_OSTREAM_TO_RTLOG(*aofs);
dgRTLOG() << "Added " << filename << " as an output stream \n";
mapOfFiles_[sfilename]= ofs_shrptr;
} CATCH_ALL_EXCEPTIONS();
return Py_BuildValue ("");
}
PyObject* closeLoggerFileOutputStream (PyObject* /*self*/, PyObject* /*args */)
{
try {
for (std::map<std::string,ofstreamShrPtr>::iterator
it=mapOfFiles_.begin();
it!=mapOfFiles_.end(); ++it)
{
it->second->close();
}
} CATCH_ALL_EXCEPTIONS();
return Py_BuildValue ("");
}
PyObject* addLoggerCoutOutputStream (PyObject* /*self*/, PyObject* /*args*/)
{
try {
dgADD_OSTREAM_TO_RTLOG(std::cout);
} CATCH_ALL_EXCEPTIONS();
return Py_BuildValue ("");
}
PyObject* realTimeLoggerDestroy (PyObject* /*self*/, PyObject* /*args*/)
{
try {
RealTimeLogger::destroy();
} CATCH_ALL_EXCEPTIONS();
return Py_BuildValue ("");
}
PyObject* realTimeLoggerSpinOnce (PyObject* /*self*/, PyObject* /*args*/)
{
try {
RealTimeLogger::instance().spinOnce();
} CATCH_ALL_EXCEPTIONS();
return Py_BuildValue ("");
}
PyObject* realTimeLoggerInstance (PyObject* /*self*/, PyObject* /*args*/)
{
try {
RealTimeLogger::instance();
} CATCH_ALL_EXCEPTIONS();
return Py_BuildValue ("");
}
} // python
} // namespace debug
} // dynamicgraph
// Copyright 2010, Florent Lamiraux, Thomas Moulard, LAAS-CNRS.
//
// This file is part of dynamic-graph-python.
// dynamic-graph-python is free software: you can redistribute it
// and/or modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation, either
// version 3 of the License, or (at your option) any later version.
//
// dynamic-graph-python is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Lesser Public License for more details. You should
// have received a copy of the GNU Lesser General Public License along
// with dynamic-graph. If not, see <http://www.gnu.org/licenses/>.
#include <Python.h>
#include <iostream>
#include <sstream>
#include <string>
#include <dynamic-graph/debug.h>
#include <dynamic-graph/exception-factory.h>
#include <dynamic-graph/signal-base.h>
#include "exception.hh"
#include "signal-wrapper.hh"
namespace dynamicgraph {
namespace python {
// Declare functions defined in other source files
namespace signalBase {
extern PyObject* create(PyObject* self, PyObject* args);
extern PyObject* createSignalWrapper(PyObject* self, PyObject* args);
extern PyObject* getTime(PyObject* self, PyObject* args);
extern PyObject* setTime(PyObject* self, PyObject* args);
extern PyObject* getName(PyObject* self, PyObject* args);
extern PyObject* getClassName(PyObject* self, PyObject* args);
extern PyObject* display(PyObject* self, PyObject* args);
extern PyObject* displayDependencies(PyObject* self, PyObject* args);
extern PyObject* getValue(PyObject* self, PyObject* args);
extern PyObject* setValue(PyObject* self, PyObject* args);
extern PyObject* recompute(PyObject* self, PyObject* args);
extern PyObject* unplug(PyObject* self, PyObject* args);
extern PyObject* isPlugged(PyObject* self, PyObject* args);
extern PyObject* getPlugged(PyObject* self, PyObject* args);
}
namespace entity {
extern PyObject* create(PyObject* self, PyObject* args);
extern PyObject* display(PyObject* self, PyObject* args);
extern PyObject* display(PyObject* self, PyObject* args);
extern PyObject* getName(PyObject* self, PyObject* args);
extern PyObject* getClassName(PyObject* self, PyObject* args);
extern PyObject* hasSignal(PyObject* self, PyObject* args);
extern PyObject* getSignal(PyObject* self, PyObject* args);
extern PyObject* listSignals(PyObject* self, PyObject* args);
extern PyObject* executeCommand(PyObject* self, PyObject* args);
extern PyObject* listCommands(PyObject* self, PyObject* args);
extern PyObject* getCommandDocstring(PyObject* self, PyObject* args);
extern PyObject* getDocString(PyObject* self, PyObject* args);
extern PyObject* setLoggerVerbosityLevel(PyObject*self, PyObject *args);
extern PyObject* getLoggerVerbosityLevel(PyObject *self, PyObject *args);
extern PyObject* setTimeSample(PyObject*self, PyObject *args);
extern PyObject* getTimeSample(PyObject *self, PyObject *args);
extern PyObject* setStreamPrintPeriod(PyObject*self, PyObject *args);
extern PyObject* getStreamPrintPeriod(PyObject *self, PyObject *args);
}
namespace factory {
extern PyObject* getEntityClassList(PyObject* self, PyObject* args);
}
namespace signalCaster {
extern PyObject* getSignalTypeList(PyObject* self, PyObject* args);
}
namespace pool {
extern PyObject* writeGraph (PyObject* self, PyObject* args);
extern PyObject* getEntityList(PyObject* self, PyObject* args);
}
namespace debug {
extern PyObject* addLoggerFileOutputStream(PyObject* self, PyObject* args);
extern PyObject* addLoggerCoutOutputStream(PyObject* self, PyObject* args);
extern PyObject* closeLoggerFileOutputStream(PyObject* self, PyObject* args);
extern PyObject* realTimeLoggerSpinOnce(PyObject* self, PyObject* args);
extern PyObject* realTimeLoggerDestroy(PyObject* self, PyObject* args);
extern PyObject* realTimeLoggerInstance(PyObject* self, PyObject* args);
}
PyObject* dgpyError;
/**
\brief plug a signal into another one.
*/
PyObject*
plug(PyObject* /*self*/, PyObject* args)
{
PyObject* objOut = NULL;
PyObject* objIn = NULL;
void* pObjOut;
void* pObjIn;
if (!PyArg_ParseTuple(args,"OO", &objOut, &objIn))
return NULL;
if (!PyCObject_Check(objOut)) {
PyErr_SetString(PyExc_TypeError,
"first argument should be a pointer to"
" signalBase<int>.");
return NULL;
}
if (!PyCObject_Check(objIn)) {
PyErr_SetString(PyExc_TypeError,
"second argument should be a pointer to"
" signalBase<int>.");
return NULL;
}
pObjIn = PyCObject_AsVoidPtr(objIn);
SignalBase<int>* signalIn = (SignalBase<int>*)pObjIn;
pObjOut = PyCObject_AsVoidPtr(objOut);
SignalBase<int>* signalOut = (SignalBase<int>*)pObjOut;
std::ostringstream os;
try {
signalIn->plug(signalOut);
} CATCH_ALL_EXCEPTIONS();
return Py_BuildValue("");
}
PyObject*
enableTrace(PyObject* /*self*/, PyObject* args)
{
PyObject* boolean;
char* filename = NULL;
if (PyArg_ParseTuple(args,"Os", &boolean, &filename)) {
if (!PyBool_Check(boolean)) {
PyErr_SetString(PyExc_TypeError, "enableTrace takes as first "
"argument True or False,\n"" and as "
"second argument a filename.");
return NULL;
}
if (PyObject_IsTrue(boolean)) {
try {
DebugTrace::openFile(filename);
} CATCH_ALL_EXCEPTIONS();
} else {
try {
DebugTrace::closeFile(filename);
} CATCH_ALL_EXCEPTIONS();
}
} else {
return NULL;
}
return Py_BuildValue("");
}
}
}
/**
\brief List of python functions
*/
static PyMethodDef dynamicGraphMethods[] = {
{"w_plug", dynamicgraph::python::plug, METH_VARARGS,
"plug an output signal into an input signal"},
{"enableTrace", dynamicgraph::python::enableTrace, METH_VARARGS,
"Enable or disable tracing debug info in a file"},
// Signals
{"create_signal_base", dynamicgraph::python::signalBase::create, METH_VARARGS,
"create a SignalBase C++ object"},
{"create_signal_wrapper", dynamicgraph::python::signalBase::createSignalWrapper, METH_VARARGS,
"create a SignalWrapper C++ object"},
{"signal_base_get_time", dynamicgraph::python::signalBase::getTime,
METH_VARARGS, "Get time of a SignalBase"},
{"signal_base_set_time", dynamicgraph::python::signalBase::setTime,
METH_VARARGS, "Set time of a SignalBase"},
{"signal_base_get_name", dynamicgraph::python::signalBase::getName,
METH_VARARGS, "Get the name of a signal"},
{"signal_base_get_class_name", dynamicgraph::python::signalBase::getClassName,
METH_VARARGS, "Get the class name of a signal"},
{"signal_base_display", dynamicgraph::python::signalBase::display,
METH_VARARGS, "Print the signal in a string"},
{"signal_base_display_dependencies", dynamicgraph::python::signalBase::displayDependencies,
METH_VARARGS, "Print the signal dependencies in a string"},
{"signal_base_get_value", dynamicgraph::python::signalBase::getValue,
METH_VARARGS, "Read the value of a signal"},
{"signal_base_set_value", dynamicgraph::python::signalBase::setValue,
METH_VARARGS, "Set the value of a signal"},
{"signal_base_recompute", dynamicgraph::python::signalBase::recompute,
METH_VARARGS, "Recompute the signal at given time"},
{"signal_base_unplug", dynamicgraph::python::signalBase::unplug,
METH_VARARGS, "Unplug the signal"},
{"signal_base_isPlugged", dynamicgraph::python::signalBase::isPlugged,
METH_VARARGS, "Whether the signal is plugged"},
{"signal_base_getPlugged", dynamicgraph::python::signalBase::getPlugged,
METH_VARARGS, "To which signal the signal is plugged"},
// Entity
{"create_entity", dynamicgraph::python::entity::create, METH_VARARGS,
"create an Entity C++ object"},
{"display_entity", dynamicgraph::python::entity::display, METH_VARARGS,
"print an Entity C++ object"},
{"entity_get_name", dynamicgraph::python::entity::getName, METH_VARARGS,
"get the name of an Entity"},
{"entity_get_class_name", dynamicgraph::python::entity::getClassName, METH_VARARGS,
"get the class name of an Entity"},
{"entity_has_signal", dynamicgraph::python::entity::hasSignal, METH_VARARGS,
"return True if the entity has a signal with the given name"},
{"entity_get_signal", dynamicgraph::python::entity::getSignal, METH_VARARGS,
"get signal by name from an Entity"},
{"entity_list_signals", dynamicgraph::python::entity::listSignals,
METH_VARARGS,
"Return the list of signals of an entity."},
{"entity_execute_command",
dynamicgraph::python::entity::executeCommand,
METH_VARARGS,
"execute a command"},
{"entity_list_commands",
dynamicgraph::python::entity::listCommands,
METH_VARARGS,
"list the commands of an entity"},
{"entity_get_command_docstring",
dynamicgraph::python::entity::getCommandDocstring,
METH_VARARGS,
"get the docstring of an entity command"},
{"entity_get_docstring",
dynamicgraph::python::entity::getDocString,
METH_VARARGS,
"get the doc string of an entity type"},
{"factory_get_entity_class_list",
dynamicgraph::python::factory::getEntityClassList,
METH_VARARGS,
"return the list of entity classes"},
{"signal_caster_get_type_list",
dynamicgraph::python::signalCaster::getSignalTypeList,
METH_VARARGS,
"return the list of signal type names"},
{"writeGraph",
dynamicgraph::python::pool::writeGraph,
METH_VARARGS,
"Write the graph of entities in a filename."},
{"get_entity_list",
dynamicgraph::python::pool::getEntityList,
METH_VARARGS,
"return the list of instanciated entities"},
{"entity_set_logger_verbosity",
dynamicgraph::python::entity::setLoggerVerbosityLevel,
METH_VARARGS,
"set the verbosity level of the entity"},
{"entity_get_logger_verbosity",
dynamicgraph::python::entity::getLoggerVerbosityLevel,
METH_VARARGS,
"get the verbosity level of the entity"},
{"addLoggerFileOutputStream",
dynamicgraph::python::debug::addLoggerFileOutputStream,
METH_VARARGS,
"add a output file stream to the logger by filename"},
{"addLoggerCoutOutputStream",
dynamicgraph::python::debug::addLoggerCoutOutputStream,
METH_VARARGS,
"add std::cout as output stream to the logger"},
{"closeLoggerFileOutputStream",
dynamicgraph::python::debug::closeLoggerFileOutputStream,
METH_VARARGS,
"close all the loggers file output streams."},
{"entity_set_time_sample",
dynamicgraph::python::entity::setTimeSample,
METH_VARARGS,
"set the time sample for printing debugging information"},
{"entity_get_time_sample",
dynamicgraph::python::entity::getTimeSample,
METH_VARARGS,
"get the time sample for printing debugging information"},
{"entity_set_stream_print_period",
dynamicgraph::python::entity::setStreamPrintPeriod,
METH_VARARGS,
"set the period at which debugging information are printed"},
{"entity_get_stream_print_period",
dynamicgraph::python::entity::getStreamPrintPeriod,
METH_VARARGS,
"get the period at which debugging information are printed"},
{"real_time_logger_destroy",
dynamicgraph::python::debug::realTimeLoggerDestroy,
METH_VARARGS,
"Destroy the real time logger."},
{"real_time_logger_spin_once",
dynamicgraph::python::debug::realTimeLoggerSpinOnce,
METH_VARARGS,
"Destroy the real time logger."},
{"real_time_logger_instance",
dynamicgraph::python::debug::realTimeLoggerInstance,
METH_VARARGS,
"Starts the real time logger."},
{NULL, NULL, 0, NULL} /* Sentinel */
};
PyMODINIT_FUNC
initwrap(void)
{
PyObject *m;
m = Py_InitModule("wrap", dynamicGraphMethods);
if (m == NULL)
return;
std::string msg("dynamic_graph.error");
dynamicgraph::python::dgpyError =
PyErr_NewException(const_cast<char*>(msg.c_str()), NULL, NULL);
Py_INCREF(dynamicgraph::python::dgpyError);
PyModule_AddObject(m, "error", dynamicgraph::python::dgpyError);
}
# Copyright 2010-2021, Florent Lamiraux, Thomas Moulard, Olivier Stasse, Guilhem
# Saurel, JRL, CNRS/AIST, LAAS-CNRS
set(PYTHON_MODULE wrap)
add_library(
${PYTHON_MODULE} MODULE debug-py.cc dynamic-graph-py.cc factory-py.cc
pool-py.cc signal-base-py.cc signal-wrapper.cc)
target_link_libraries(${PYTHON_MODULE} PUBLIC ${PROJECT_NAME} eigenpy::eigenpy)
# Remove prefix lib
set_target_properties(${PYTHON_MODULE} PROPERTIES PREFIX "")
if(UNIX AND NOT APPLE)
set_target_properties(${PYTHON_MODULE} PROPERTIES INSTALL_RPATH
"\$ORIGIN/../../..")
endif()
install(
TARGETS ${PYTHON_MODULE}
EXPORT ${TARGETS_EXPORT_NAME}
DESTINATION ${PYTHON_SITELIB}/dynamic_graph)
......@@ -3,20 +3,8 @@ Copyright (c) 2010 CNRS
Author: Florent Lamiraux
"""
import sys, DLFCN
flags = sys.getdlopenflags()
# Import C++ symbols in a global scope
# This is necessary for signal compiled in different modules to be compatible
sys.setdlopenflags(DLFCN.RTLD_NOW|DLFCN.RTLD_GLOBAL)
from wrap import *
# Recover previous flags
sys.setdlopenflags(flags)
from __future__ import print_function
import entity, signal_base
def plug (signalOut, signalIn) :
"""
Plug an output signal into an input signal
"""
# get signals and entities
w_plug(signalOut.obj, signalIn.obj)
from . import entity # noqa
from . import signal_base # noqa
from .wrap import * # noqa
......@@ -9,6 +9,8 @@
# >>> e.a.b.c.d( ...)
# as if it was a classical member function of e.
from __future__ import print_function
class CommandPath(object):
"""
......@@ -16,95 +18,115 @@ class CommandPath(object):
to store entity commands. It has no members except those automatically
defined at run time (which should be CommandPath or functions).
"""
mother=None
def __getattr__(self,name):
privateName=name+'_obj'
mother = None
def __getattr__(self, name):
privateName = name + "_obj"
if privateName in self.__dict__:
obj=getattr(self,privateName)
obj.mother=self.mother
obj = getattr(self, privateName)
obj.mother = self.mother
return obj
return object.__getattr__(self,name)
return object.__getattr__(self, name)
def createCommandModule( target,name ):
def createGetter( name ):
def __( self ):
obj = getattr(self,name)
obj.mother=self
def createCommandModule(target, name):
def createGetter(name):
def __(self):
obj = getattr(self, name)
obj.mother = self
return obj
return __
privateName = name+'_obj'
setattr( target,privateName, CommandPath() )
module = getattr( target,privateName )
privateName = name + "_obj"
setattr(target, privateName, CommandPath())
if not isinstance(target, CommandPath):
setattr(target, name, property(createGetter(privateName)))
if not isinstance(target,CommandPath) :
setattr( target,name, property(createGetter(privateName)) )
class CommandLauncher(object):
"""
"""
mother=None
fun=None
def __init__(self,fun): self.fun=fun
def __call__(self,*arg):
return self.fun(self.mother,*arg)
def createCommandLauncher( target,name,fun ):
if isinstance(target,CommandPath) :
privateName = name+'_obj'
setattr( target,privateName, CommandLauncher(fun) )
""" """
mother = None
fun = None
def __init__(self, fun):
self.fun = fun
def __call__(self, *arg):
return self.fun(self.mother, *arg)
def createCommandLauncher(target, name, fun):
if isinstance(target, CommandPath):
privateName = name + "_obj"
setattr(target, privateName, CommandLauncher(fun))
else:
setattr( target,name,fun )
setattr(target, name, fun)
def setattrpath( target,path,attribute ):
def setattrpath(target, path, attribute):
"""
Create in target an new attribute with value path (available at
target.path1. ... .pathn).
"""
pathk=target
read=True
if type(path)==type(str()): path=path.split('.')
pathk = target
read = True
if isinstance(path, str):
path = path.split(".")
for tokenk in path[0:-1]:
if (not read) | (tokenk not in pathk.__dict__):
read=False
createCommandModule(pathk,tokenk)
pathk = getattr(pathk,tokenk+"_obj")
read = False
createCommandModule(pathk, tokenk)
pathk = getattr(pathk, tokenk + "_obj")
if callable(attribute):
createCommandLauncher( pathk,path[-1],attribute )
createCommandLauncher(pathk, path[-1], attribute)
else:
print("Should not happen")
setattr(pathk,path[-1],attribute )
setattr(pathk, path[-1], attribute)
def getattrpath( target,path ):
def getattrpath(target, path):
"""
Get in target the value located at path (available at
target.path1. ... .pathn).
"""
pathk=target
if type(path)==type(str()): path=path.split('.')
pathk = target
if isinstance(path, str):
path = path.split(".")
for tokenk in path:
privateName=tokenk+"_obj"
if (privateName in pathk.__dict__): pathk = getattr(pathk,privateName)
privateName = tokenk + "_obj"
if hasattr(pathk, privateName):
pathk = getattr(pathk, privateName)
else:
if ( tokenk in pathk.__dict__): pathk = getattr(pathk,tokenk)
if hasattr(pathk, tokenk):
pathk = getattr(pathk, tokenk)
else:
raise Exception('Path does not exist -- while accessing "'+tokenk+'" in '+'.'.join(path))
raise Exception(
'Path does not exist -- while accessing "'
+ tokenk
+ '" in '
+ ".".join(path)
)
return pathk
def existattrpath( target,path ):
def existattrpath(target, path):
"""
Check for the existence in target of a value located at path (available at
target.path1. ... .pathn).
"""
pathk=target
if type(path)==type(str()): path=path.split('.')
pathk = target
if isinstance(path, str):
path = path.split(".")
for tokenk in path[0:-1]:
print('check ',tokenk)
privateName=tokenk+"_obj"
if (privateName not in pathk.__dict__):
print("check ", tokenk)
privateName = tokenk + "_obj"
if privateName not in pathk.__dict__:
return False
pathk = getattr(pathk,privateName)
name=path[-1]
privateName=name+"_obj"
return (name in pathk.__dict__)|(privateName in pathk.__dict__)
pathk = getattr(pathk, privateName)
name = path[-1]
privateName = name + "_obj"
return (name in pathk.__dict__) | (privateName in pathk.__dict__)
// Copyright 2010, Florent Lamiraux, Thomas Moulard, LAAS-CNRS.
#include "dynamic-graph/python/convert-dg-to-py.hh"
#include <dynamic-graph/signal-base.h>
#include <dynamic-graph/signal-caster.h>
#include <dynamic-graph/signal.h>
#include <boost/python.hpp>
#include <boost/python/stl_iterator.hpp>
#include <iostream>
#include <sstream>
#include "dynamic-graph/python/python-compat.hh"
namespace dynamicgraph {
using ::dynamicgraph::SignalBase;
namespace python {
namespace convert {
namespace bp = boost::python;
command::Value toValue(bp::object o, const command::Value::Type& valueType) {
using command::Value;
switch (valueType) {
case (Value::BOOL):
return Value(bp::extract<bool>(o));
case (Value::UNSIGNED):
return Value(bp::extract<unsigned>(o));
case (Value::INT):
return Value(bp::extract<int>(o));
case (Value::FLOAT):
return Value(bp::extract<float>(o));
case (Value::DOUBLE):
return Value(bp::extract<double>(o));
case (Value::STRING):
return Value(bp::extract<std::string>(o));
case (Value::VECTOR):
// TODO for backward compatibility, support tuple or list ?
// I don't think so
return Value(bp::extract<Vector>(o));
case (Value::MATRIX):
// TODO for backward compatibility, support tuple or list ?
// I don't think so
return Value(bp::extract<Matrix>(o));
case (Value::MATRIX4D):
return Value(bp::extract<Eigen::Matrix4d>(o));
case (Value::VALUES):
// TODO the vector of values cannot be built since
// - the value type inside the vector are not know
// - inferring the value type from the Python type is not implemented.
throw std::invalid_argument(
"not implemented: cannot create a vector of values");
break;
default:
std::cerr << "Only int, double and string are supported." << std::endl;
}
return Value();
}
bp::object fromValue(const command::Value& value) {
using command::Value;
switch (value.type()) {
case (Value::BOOL):
return bp::object(value.boolValue());
case (Value::UNSIGNED):
return bp::object(value.unsignedValue());
case (Value::INT):
return bp::object(value.intValue());
case (Value::FLOAT):
return bp::object(value.floatValue());
case (Value::DOUBLE):
return bp::object(value.doubleValue());
case (Value::STRING):
return bp::object(value.stringValue());
case (Value::VECTOR):
return bp::object(value.vectorValue());
case (Value::MATRIX):
return bp::object(value.matrixXdValue());
case (Value::MATRIX4D):
return bp::object(value.matrix4dValue());
case (Value::VALUES): {
bp::list list;
for (const Value& v : value.constValuesValue()) list.append(fromValue(v));
return list;
}
case (Value::NONE):
default:
return bp::object();
}
}
} // namespace convert
} // namespace python
} // namespace dynamicgraph