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 457 additions and 968 deletions
.. dynamic-graph-python documentation master file, created by
sphinx-quickstart on Mon Nov 22 16:45:27 2010.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
Welcome to dynamic-graph-python's documentation!
================================================
.. toctree::
:maxdepth: 2
Python module dynamic_graph implements bindings for dynamic-graph_ library. To each main C++ class is associated a Python class. Main classes are listed below.
Entity
------
maps dynamicgraph::Entity_ C++ class.
.. autoclass:: dynamic_graph.entity.Entity
:members:
SignalBase
----------
maps dynamicgraph::SignalBase_ C++ class.
.. autoclass:: dynamic_graph.signal_base.SignalBase
:members:
Other funtions of the module
----------------------------
.. automodule:: dynamic_graph
:members:
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`
.. _dynamic-graph: file://@DYNAMIC_GRAPH_DOXYGENDOCDIR@/index.html
.. _Entity: file://@DYNAMIC_GRAPH_DOXYGENDOCDIR@/classdynamicgraph_1_1_entity.html
.. _SignalBase: file://@DYNAMIC_GRAPH_DOXYGENDOCDIR@/classdynamicgraph_1_1_signal_base.html
# Copyright 2010, 2011, Florent Lamiraux, 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-python. If not, see <http://www.gnu.org/licenses/>.
// -*- 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_API_HH
# define DYNAMIC_GRAPH_PYTHON_API_HH
# include <dynamic-graph/python/config.hh>
#endif //DYNAMIC_GRAPH_PYTHON_API_HH
#define DYNAMIC_GRAPH_PYTHON_API_HH
#include <dynamic-graph/python/config.hh>
#endif // DYNAMIC_GRAPH_PYTHON_API_HH
// Copyright 2010, Florent Lamiraux, Thomas Moulard, LAAS-CNRS.
#include <dynamic-graph/linear-algebra.h>
#include <dynamic-graph/value.h>
#include <boost/python.hpp>
namespace dynamicgraph {
namespace python {
namespace convert {
command::Value toValue(boost::python::object o,
const command::Value::Type& type);
boost::python::object fromValue(const command::Value& value);
} // namespace convert
} // namespace python
} // namespace dynamicgraph
#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/dynamic-graph-api.h>
# include <dynamic-graph/exception-abstract.h>
namespace dynamicgraph {
namespace python {
/// \ingroup error
///
/// \brief Generic error class.
class DYNAMIC_GRAPH_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"
#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
std::string python( const std::string& command );
/// \brief Method to exectue a python script.
/// \param filename the filename
void runPythonFile( std::string filename );
/// \brief Process input stream to send relevant blocks to python
/// \param stream input stream
std::string processStream(std::istream& stream, std::ostream& os);
private:
/// 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
#
INCLUDE(FindPythonLibs)
IF (NOT ${PYTHONLIBS_FOUND} STREQUAL TRUE)
MESSAGE(FATAL_ERROR "Python has not been found.")
ENDIF (NOT ${PYTHONLIBS_FOUND} STREQUAL TRUE)
add_subdirectory(dynamic_graph)
INCLUDE(FindPythonInterp)
IF (NOT ${PYTHONINTERP_FOUND} STREQUAL TRUE)
MESSAGE(FATAL_ERROR "Python executable has not been found.")
ENDIF (NOT ${PYTHONINTERP_FOUND} STREQUAL TRUE)
INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS})
# provide path to library libdynamic-graph.so
LINK_DIRECTORIES(${DYNAMIC_GRAPH_LIBRARY_DIRS})
ADD_DEFINITIONS(${DYNAMIC_GRAPH_CFLAGS})
#
#
# Python interpreter
#
#
SET(LIBRARY_NAME ${PROJECT_NAME})
ADD_LIBRARY(${LIBRARY_NAME}
SHARED
interpreter.cc)
TARGET_LINK_LIBRARIES(${LIBRARY_NAME}
${Boost_LIBRARIES}
${PYTHON_LIBRARY})
SET_TARGET_PROPERTIES(${LIBRARY_NAME} PROPERTIES SOVERSION ${PROJECT_VERSION})
PKG_CONFIG_USE_DEPENDENCY(${LIBRARY_NAME} dynamic-graph)
INSTALL(TARGETS ${LIBRARY_NAME}
DESTINATION lib)
SET(EXECUTABLE_NAME dg-python)
ADD_EXECUTABLE(${EXECUTABLE_NAME} dg-python.cc)
TARGET_LINK_LIBRARIES(${EXECUTABLE_NAME}
${LIBRARY_NAME}
)
INSTALL(TARGETS dg-python DESTINATION bin)
#
#
# Python bindings
#
#
SET(PYTHON_MODULE wrap)
ADD_LIBRARY(${PYTHON_MODULE}
MODULE
exception-python.cc
convert-dg-to-py.cc
dynamic-graph-py.cc
signal-base-py.cc
entity-py.cc
factory-py.cc
signal-caster-py.cc
)
# Remove prefix lib
SET_TARGET_PROPERTIES(${PYTHON_MODULE}
PROPERTIES PREFIX "")
TARGET_LINK_LIBRARIES(${PYTHON_MODULE} ${DYNAMIC_GRAPH_LIBRARIES})
INCLUDE_DIRECTORIES(${PYTHON_INCLUDE_PATH})
#
# Installation
#
EXEC_PROGRAM(${PYTHON_EXECUTABLE} ARGS "-c \"from distutils import sysconfig; print sysconfig.get_python_lib(0,0,prefix='')\""
OUTPUT_VARIABLE PYTHON_SITELIB)
MESSAGE(STATUS "PYTHON_SITELIB=${PYTHON_SITELIB}")
SET(PYTHON_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/${PYTHON_SITELIB}/dynamic_graph)
INSTALL(TARGETS ${PYTHON_MODULE}
DESTINATION
${PYTHON_INSTALL_DIR})
SET (PYTHON_SOURCES
dynamic_graph/__init__.py
dynamic_graph/entity.py
dynamic_graph/signal_base.py
dynamic_graph/matlab.py
dynamic_graph/script_shortcuts.py
)
SET (PYTHON_SOURCES_FULLPATH "")
FOREACH (SOURCE ${PYTHON_SOURCES})
SET(PYTHON_SOURCES_FULLPATH
${PYTHON_SOURCES_FULLPATH}
${CMAKE_SOURCE_DIR}/src/${SOURCE}
)
ENDFOREACH (SOURCE)
INSTALL(FILES ${PYTHON_SOURCES_FULLPATH}
DESTINATION ${PYTHON_INSTALL_DIR})
set(PYTHON_SOURCES __init__.py attrpath.py entity.py signal_base.py
script_shortcuts.py tools.py)
foreach(source ${PYTHON_SOURCES})
python_install_on_site(dynamic_graph ${source})
endforeach(source)
# --- ADD the wrap on the dg modules
INCLUDE(../cmake/python.cmake)
EXEC_PROGRAM("${PKG_CONFIG_EXECUTABLE}"
ARGS "--variable=plugindir" "dynamic-graph"
OUTPUT_VARIABLE "DYNAMIC_GRAPH_PLUGIN_DIR")
# Tracer plugin
ADD_DEPENDENCIES(${LIBRARY_NAME} MKDIR_tracer)
ADD_CUSTOM_TARGET(MKDIR_tracer mkdir -p ../lib/dynamic_graph/tracer)
SET(TRACER_PLUGIN ${DYNAMIC_GRAPH_PLUGIN_DIR}/tracer.so)
DYNAMIC_GRAPH_PYTHON_MODULE("tracer" ${TRACER_PLUGIN} tracer/wrap)
# TracerRealTime plugin
ADD_DEPENDENCIES(${LIBRARY_NAME} MKDIR_TracerRealTime)
ADD_CUSTOM_TARGET(MKDIR_TracerRealTime mkdir -p ../lib/dynamic_graph/tracer_real_time)
SET(TRACERREALTIME_PLUGIN ${DYNAMIC_GRAPH_PLUGIN_DIR}/tracer-real-time.so)
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* tuple)
{
if (PyTuple_Size(tuple) != (int)m.nbCols()) {
throw ExceptionPython(ExceptionPython::MATRIX_PARSING,
"lines of matrix have different sizes.");
}
for (unsigned int iCol=0; iCol < m.nbCols(); iCol++) {
PyObject* pyDouble = PyTuple_GetItem(tuple, 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;
unsigned int nCols;
unsigned int size;
PyObject* row;
unsigned int nRows;
switch (valueType) {
case (Value::BOOL) :
if (!PyBool_Check(pyObject)) {
throw ExceptionPython(ExceptionPython::VALUE_PARSING,
"bool");
}
bvalue = (pyObject == Py_True);
return Value(bvalue);
break;
case (Value::UNSIGNED) :
if (!PyInt_Check(pyObject)) {
throw ExceptionPython(ExceptionPython::VALUE_PARSING,
"unsigned int");
}
uvalue = 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 = 0.0+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 (!PyTuple_Check(pyObject)) {
throw ExceptionPython(ExceptionPython::VALUE_PARSING,
"vector");
}
size = PyTuple_Size(pyObject);
v.resize(size);
for (unsigned int i=0; i<size; i++) {
PyObject* pyDouble = PyTuple_GetItem(pyObject, i);
if (PyFloat_Check(pyDouble))
v(i) = PyFloat_AsDouble(pyDouble);
else if(PyInt_Check(pyDouble))
v(i) = (int)PyInt_AS_LONG(pyObject)+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 (!PyTuple_Check(pyObject)) {
throw ExceptionPython(ExceptionPython::VALUE_PARSING,
"matrix");
}
nRows = PyTuple_Size(pyObject);
if (nRows == 0) {
return Value(Matrix());
}
row = PyTuple_GetItem(pyObject, 0);
if (!PyTuple_Check(row)) {
throw ExceptionPython(ExceptionPython::MATRIX_PARSING,
"matrix");
}
nCols = PyTuple_Size(row);
m.resize(nRows, nCols);
fillMatrixRow(m, 0, row);
for (unsigned int iRow=1; iRow<nRows; iRow++) {
row = PyTuple_GetItem(pyObject, iRow);
if (!PyTuple_Check(row)) {
throw ExceptionPython(ExceptionPython::MATRIX_PARSING,
"matrix");
}
fillMatrixRow(m, iRow, row);
}
return Value(m);
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 (unsigned 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.nbRows());
for (unsigned int iRow = 0; iRow < matrix.nbRows(); iRow++) {
PyObject* row = PyTuple_New(matrix.nbCols());
for (unsigned iCol=0; iCol < matrix.nbCols(); 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;
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);
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* valueToPython(const ::dynamicgraph::command::Value& value);
} // namespace dynamicgraph
} // namespace python
}
// 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/>.
#include <sstream>
#include <string>
#include <vector>
#include <list>
#include <boost/filesystem.hpp>
#include <boost/foreach.hpp>
#include <boost/format.hpp>
#include <boost/program_options.hpp>
#include <dynamic-graph/debug.h>
#include "dynamic-graph/python/interpreter.hh"
// Factorize exception catching code.
#define CATCH_EXCEPTIONS() \
catch (std::exception& e) \
{ \
std::cout \
<< errorPrefix \
<< e.what () << std::endl; \
} \
catch (const char* str) \
{ \
std::cout << errorPrefix \
<< "Unknown exception " << str << std::endl; \
} \
catch (...) \
{ \
dgDEBUG(5) << errorPrefix << " Unknown exception " << std::endl; \
} \
struct e_n_d__w_i_t_h__s_e_m_i_c_o_l_o_n
struct Options
{
/// \brief Prologue path (a prologue is a script implicitly
/// evaluated at start-up).
};
int main (int argc, char** argv)
{
dgDEBUGIN(15);
dgDEBUG(5) << " Loading..." << std::endl;
// Parse options.
std::vector<std::string> inputs;
namespace po = boost::program_options;
po::options_description desc ("Allowed options");
desc.add_options ()
("input,i",
po::value<std::vector<std::string> >(&inputs),
"file(s) evaluated at start-up")
("help,h", "produce help message")
;
po::positional_options_description p;
p.add("input", -1);
po::variables_map vm;
try
{
po::store(po::command_line_parser(argc, argv).
options(desc).positional(p).run(), vm);
po::notify(vm);
if (vm.count ("help"))
{
std::cout << "Usage: " << argv[0] << " [options]" << std::endl
<< desc << std::endl
<< "Report bugs to <hpp@laas.fr>" << std::endl;
return 1;
}
}
catch (po::error& error)
{
std::cerr << "Error while parsing argument: "
<< error.what () << std::endl;
return 1;
}
std::list<std::string> inputList (inputs.begin (),
inputs.end ());
// Load all input files.
dynamicgraph::python::Interpreter interpreter;
BOOST_FOREACH (const std::string& pathStr, inputList)
{
boost::filesystem::path path (pathStr);
std::stringstream ss;
ss << "!! In file <" << path.file_string () << "> : ";
std::string errorPrefix = ss.str ();
try
{
interpreter.runPythonFile (path.file_string ());
}
CATCH_EXCEPTIONS ();
return 0;
}
std::string errorPrefix = "";
std::string command;
while(1) {
command = interpreter.processStream(std::cin, std::cout);
if (command != "\n") {
std::string result = interpreter.python(command);
if (result != "None") {
std::cout << result << std::endl;
}
}
if (std::cin.eof ())
break;
}
std::cout << std::endl;
return 0;
}
// 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>
namespace dynamicgraph {
namespace python {
// Declare functions defined in other source files
namespace signalBase {
extern PyObject* create(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* 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);
}
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* 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);
}
namespace factory {
PyObject* getEntityClassList(PyObject* self, PyObject* args);
}
namespace signalCaster {
PyObject* getSignalTypeList(PyObject* self, PyObject* args);
}
PyObject* error;
/**
\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 (std::exception& exc) {
PyErr_SetString(error, exc.what());
return NULL;
}
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 (boolean == Py_True) {
try {
DebugTrace::openFile(filename);
} catch (const std::exception& exc) {
PyErr_SetString(PyExc_IOError, exc.what());
return NULL;
}
} else {
try {
DebugTrace::closeFile(filename);
} catch (const std::exception& exc) {
PyErr_SetString(PyExc_IOError, exc.what());
return NULL;
}
}
} 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"},
{"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_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"},
// 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_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"},
{"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"},
{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::error =
PyErr_NewException(const_cast<char*>(msg.c_str()), NULL, NULL);
Py_INCREF(dynamicgraph::python::error);
PyModule_AddObject(m, "error", dynamicgraph::python::error);
}