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
Select Git revision

Target

Select target project
  • ostasse/dynamic-graph-python
  • gsaurel/dynamic-graph-python
  • stack-of-tasks/dynamic-graph-python
3 results
Select Git revision
Show changes
Showing
with 391 additions and 278 deletions
[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
# Python bindings
# Python bindings
ADD_SUBDIRECTORY(dynamic_graph)
add_subdirectory(dynamic_graph)
SET(PYTHON_SOURCES
__init__.py
attrpath.py
entity.py
signal_base.py
script_shortcuts.py
tools.py
)
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)
foreach(source ${PYTHON_SOURCES})
python_install_on_site(dynamic_graph ${source})
endforeach(source)
# --- ADD the wrap on the dg modules
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)
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-2020, Florent Lamiraux, Thomas Moulard, Olivier Stasse, Guilhem Saurel, JRL, CNRS/AIST, LAAS-CNRS
# Copyright 2010-2021, Florent Lamiraux, Thomas Moulard, Olivier Stasse, Guilhem
# Saurel, JRL, CNRS/AIST, LAAS-CNRS
SET(PYTHON_MODULE wrap)
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
)
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)
TARGET_LINK_BOOST_PYTHON(${PYTHON_MODULE} PRIVATE)
target_link_libraries(${PYTHON_MODULE} PUBLIC ${PROJECT_NAME} eigenpy::eigenpy)
# Remove prefix lib
SET_TARGET_PROPERTIES(${PYTHON_MODULE} PROPERTIES PREFIX "")
set_target_properties(${PYTHON_MODULE} PROPERTIES PREFIX "")
INSTALL(TARGETS ${PYTHON_MODULE}
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)
......@@ -5,9 +5,6 @@ Author: Florent Lamiraux
from __future__ import print_function
import sys
from . import entity # noqa
from . import signal_base # noqa
from .wrap import * # noqa
......@@ -18,10 +18,11 @@ 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'
privateName = name + "_obj"
if privateName in self.__dict__:
obj = getattr(self, privateName)
obj.mother = self.mother
......@@ -38,7 +39,7 @@ def createCommandModule(target, name):
return __
privateName = name + '_obj'
privateName = name + "_obj"
setattr(target, privateName, CommandPath())
if not isinstance(target, CommandPath):
......@@ -46,8 +47,8 @@ def createCommandModule(target, name):
class CommandLauncher(object):
"""
"""
""" """
mother = None
fun = None
......@@ -60,7 +61,7 @@ class CommandLauncher(object):
def createCommandLauncher(target, name, fun):
if isinstance(target, CommandPath):
privateName = name + '_obj'
privateName = name + "_obj"
setattr(target, privateName, CommandLauncher(fun))
else:
setattr(target, name, fun)
......@@ -74,7 +75,7 @@ def setattrpath(target, path, attribute):
pathk = target
read = True
if isinstance(path, str):
path = path.split('.')
path = path.split(".")
for tokenk in path[0:-1]:
if (not read) | (tokenk not in pathk.__dict__):
read = False
......@@ -94,7 +95,7 @@ def getattrpath(target, path):
"""
pathk = target
if isinstance(path, str):
path = path.split('.')
path = path.split(".")
for tokenk in path:
privateName = tokenk + "_obj"
if hasattr(pathk, privateName):
......@@ -103,7 +104,12 @@ def getattrpath(target, path):
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
......@@ -114,11 +120,11 @@ def existattrpath(target, path):
"""
pathk = target
if isinstance(path, str):
path = path.split('.')
path = path.split(".")
for tokenk in path[0:-1]:
print('check ', tokenk)
print("check ", tokenk)
privateName = tokenk + "_obj"
if (privateName not in pathk.__dict__):
if privateName not in pathk.__dict__:
return False
pathk = getattr(pathk, privateName)
name = path[-1]
......
// Copyright 2010, Florent Lamiraux, Thomas Moulard, LAAS-CNRS.
#include <iostream>
#include <sstream>
#include <boost/python.hpp>
#include <boost/python/stl_iterator.hpp>
#include "dynamic-graph/python/convert-dg-to-py.hh"
#include <dynamic-graph/signal-base.h>
#include <dynamic-graph/signal.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/convert-dg-to-py.hh"
#include "dynamic-graph/python/python-compat.hh"
namespace dynamicgraph {
......@@ -51,7 +51,8 @@ command::Value toValue(bp::object o, const command::Value::Type& valueType) {
// 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");
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;
......
......@@ -5,14 +5,14 @@
#include <iostream>
#define ENABLE_RT_LOG
#include <dynamic-graph/entity.h>
#include <dynamic-graph/pool.h>
#include <dynamic-graph/real-time-logger.h>
#include <boost/shared_ptr.hpp>
#include <map>
#include <dynamic-graph/pool.h>
#include <dynamic-graph/entity.h>
#include <vector>
#include <boost/shared_ptr.hpp>
#include "dynamic-graph/python/dynamic-graph-py.hh"
typedef boost::shared_ptr<std::ofstream> ofstreamShrPtr;
......
// Copyright 2010, Florent Lamiraux, Thomas Moulard, LAAS-CNRS.
#include <iostream>
#include <sstream>
#include <boost/python.hpp>
#include <boost/python/suite/indexing/map_indexing_suite.hpp>
#include <eigenpy/eigenpy.hpp>
#include <Eigen/Geometry>
#include <eigenpy/geometry.hpp>
#include "dynamic-graph/python/dynamic-graph-py.hh"
#include <dynamic-graph/command.h>
#include <dynamic-graph/debug.h>
#include <dynamic-graph/exception-factory.h>
#include <dynamic-graph/signal-base.h>
#include <dynamic-graph/signal.h>
#include <dynamic-graph/signal-time-dependent.h>
#include <dynamic-graph/entity.h>
#include <dynamic-graph/command.h>
#include <dynamic-graph/exception-factory.h>
#include <dynamic-graph/factory.h>
#include <dynamic-graph/pool.h>
#include <dynamic-graph/signal-base.h>
#include <dynamic-graph/signal-time-dependent.h>
#include <dynamic-graph/signal.h>
#include <dynamic-graph/tracer.h>
#include "dynamic-graph/python/dynamic-graph-py.hh"
#include "dynamic-graph/python/signal-wrapper.hh"
#include <Eigen/Geometry>
#include <boost/python.hpp>
#include <boost/python/raw_function.hpp>
#include <boost/python/suite/indexing/map_indexing_suite.hpp>
#include <eigenpy/eigenpy.hpp>
#include <eigenpy/geometry.hpp>
#include <iostream>
#include <sstream>
#include "dynamic-graph/python/convert-dg-to-py.hh"
#include "dynamic-graph/python/module.hh"
#include "dynamic-graph/python/signal-wrapper.hh"
namespace dynamicgraph {
namespace python {
......@@ -33,7 +32,9 @@ namespace python {
/**
\brief plug a signal into another one.
*/
void plug(SignalBase<int>* signalOut, SignalBase<int>* signalIn) { signalIn->plug(signalOut); }
void plug(SignalBase<int>* signalOut, SignalBase<int>* signalIn) {
signalIn->plug(signalOut);
}
void enableTrace(bool enable, const char* filename) {
if (enable)
......@@ -49,7 +50,8 @@ namespace bp = boost::python;
namespace dg = dynamicgraph;
typedef bp::return_value_policy<bp::manage_new_object> manage_new_object;
typedef bp::return_value_policy<bp::reference_existing_object> reference_existing_object;
typedef bp::return_value_policy<bp::reference_existing_object>
reference_existing_object;
typedef dg::PoolStorage::Entities MapOfEntities;
......@@ -59,9 +61,14 @@ struct MapOfEntitiesPairToPythonConverter {
}
};
MapOfEntities* getEntityMap() { return const_cast<MapOfEntities*>(&dg::PoolStorage::getInstance()->getEntityMap()); }
MapOfEntities* getEntityMap() {
return const_cast<MapOfEntities*>(
&dg::PoolStorage::getInstance()->getEntityMap());
}
dg::SignalBase<int>* getSignal(dg::Entity& e, const std::string& name) { return &e.getSignal(name); }
dg::SignalBase<int>* getSignal(dg::Entity& e, const std::string& name) {
return &e.getSignal(name);
}
class PythonEntity : public dg::Entity {
DYNAMIC_GRAPH_ENTITY_DECL();
......@@ -69,8 +76,12 @@ class PythonEntity : public dg::Entity {
public:
using dg::Entity::Entity;
void signalRegistration(dg::SignalBase<int>& signal) { dg::Entity::signalRegistration(signal); }
void signalDeregistration(const std::string& name) { dg::Entity::signalDeregistration(name); }
void signalRegistration(dg::SignalBase<int>& signal) {
dg::Entity::signalRegistration(signal);
}
void signalDeregistration(const std::string& name) {
dg::Entity::signalDeregistration(name);
}
};
DYNAMICGRAPH_FACTORY_ENTITY_PLUGIN(PythonEntity, "PythonEntity");
......@@ -86,57 +97,73 @@ void exposeEntityBase() {
.export_values();
bp::class_<Entity, boost::noncopyable>("Entity", bp::no_init)
.add_property("name", bp::make_function(&Entity::getName, bp::return_value_policy<bp::copy_const_reference>()))
.add_property("name",
bp::make_function(
&Entity::getName,
bp::return_value_policy<bp::copy_const_reference>()))
.add_property("className",
bp::make_function(&Entity::getClassName, bp::return_value_policy<bp::copy_const_reference>()),
bp::make_function(
&Entity::getClassName,
bp::return_value_policy<bp::copy_const_reference>()),
"the class name of the Entity")
.add_property("__doc__", &Entity::getDocString)
.def("setLoggerVerbosityLevel", &Entity::setLoggerVerbosityLevel)
.def("getLoggerVerbosityLevel", &Entity::getLoggerVerbosityLevel)
.add_property("loggerVerbosityLevel", &Entity::setLoggerVerbosityLevel, &Entity::getLoggerVerbosityLevel,
.add_property("loggerVerbosityLevel", &Entity::setLoggerVerbosityLevel,
&Entity::getLoggerVerbosityLevel,
"the verbosity level of the entity")
.def("setTimeSample", &Entity::setTimeSample)
.def("getTimeSample", &Entity::getTimeSample)
.add_property("timeSample", &Entity::getTimeSample, &Entity::setTimeSample,
.add_property("timeSample", &Entity::getTimeSample,
&Entity::setTimeSample,
"the time sample for printing debugging information")
.def("setStreamPrintPeriod", &Entity::setStreamPrintPeriod)
.def("getStreamPrintPeriod", &Entity::getStreamPrintPeriod)
.add_property("streamPrintPeriod", &Entity::getStreamPrintPeriod, &Entity::setStreamPrintPeriod,
.add_property("streamPrintPeriod", &Entity::getStreamPrintPeriod,
&Entity::setStreamPrintPeriod,
"set the period at which debugging information are printed")
.def("__str__",
+[](const Entity& e) -> std::string {
std::ostringstream os;
e.display(os);
return os.str();
})
.def("signals",
+[](const Entity& e) -> bp::list {
bp::list ret;
for (auto& el : e.getSignalMap()) ret.append(bp::ptr(el.second));
return ret;
},
"Return the list of signals.")
//.def("signal", +[](Entity& e, const std::string &name) { return &e.getSignal(name); },
.def(
"__str__",
+[](const Entity& e) -> std::string {
std::ostringstream os;
e.display(os);
return os.str();
})
.def(
"signals",
+[](const Entity& e) -> bp::list {
bp::list ret;
for (auto& el : e.getSignalMap()) ret.append(bp::ptr(el.second));
return ret;
},
"Return the list of signals.")
//.def("signal", +[](Entity& e, const std::string &name) { return
//&e.getSignal(name); },
// reference_existing_object())
.def("signal", &getSignal, reference_existing_object(), "get signal by name from an Entity", bp::arg("name"))
.def("hasSignal", &Entity::hasSignal, "return True if the entity has a signal with the given name")
.def("displaySignals",
+[](const Entity& e) {
Entity::SignalMap signals(e.getSignalMap());
std::cout << "--- <" << e.getName();
if (signals.empty())
std::cout << "> has no signal\n";
else
std::cout << "> signal list:\n";
for (const auto& el : signals) el.second->display(std::cout << " |-- <") << '\n';
},
"Print the list of signals into standard output: temporary.")
.def("signal", &getSignal, reference_existing_object(),
"get signal by name from an Entity", bp::arg("name"))
.def("hasSignal", &Entity::hasSignal,
"return True if the entity has a signal with the given name")
.def(
"displaySignals",
+[](const Entity& e) {
Entity::SignalMap signals(e.getSignalMap());
std::cout << "--- <" << e.getName();
if (signals.empty())
std::cout << "> has no signal\n";
else
std::cout << "> signal list:\n";
for (const auto& el : signals)
el.second->display(std::cout << " |-- <") << '\n';
},
"Print the list of signals into standard output: temporary.")
/*
.def("__getattr__", +[](Entity& e, const std::string &name) -> SignalBase<int>* { return &e.getSignal(name); },
.def("__getattr__", +[](Entity& e, const std::string &name) ->
SignalBase<int>* { return &e.getSignal(name); },
reference_existing_object())
def __getattr__(self, name):
try:
......@@ -145,16 +172,16 @@ void exposeEntityBase() {
try:
object.__getattr__(self, name)
except AttributeError:
raise AttributeError("'%s' entity has no attribute %s\n" % (self.name, name) +
' entity attributes are usually either\n' + ' - commands,\n' +
' - signals or,\n' + ' - user defined attributes')
raise AttributeError("'%s' entity has no attribute %s\n" %
(self.name, name) + ' entity attributes are usually either\n' + ' -
commands,\n' + ' - signals or,\n' + ' - user defined attributes')
*/
/*
.def("__setattr__", +[](bp::object self, const std::string &name, bp::object value) {
Entity& e = bp::extract<Entity&> (self);
if (e.hasSignal(name))
throw std::invalid_argument(name + " already designates a signal. "
"It is not advised to set a new attribute of the same name.");
.def("__setattr__", +[](bp::object self, const std::string &name,
bp::object value) { Entity& e = bp::extract<Entity&> (self); if
(e.hasSignal(name)) throw std::invalid_argument(name + " already
designates a signal. " "It is not advised to set a new attribute of the
same name.");
// TODO How do you do that ? I am sure it is possible.
//object.__setattr__(self, name, value)
})
......@@ -163,66 +190,85 @@ void exposeEntityBase() {
/* TODO ?
def boundNewCommand(self, cmdName):
"""
At construction, all existing commands are bound directly in the class.
This method enables to bound new commands dynamically. These new bounds
are not made with the class, but directly with the object instance.
At construction, all existing commands are bound directly in the
class. This method enables to bound new commands dynamically. These new
bounds are not made with the class, but directly with the object instance.
"""
def boundAllNewCommands(self):
"""
For all commands that are not attribute of the object instance nor of the
class, a new attribute of the instance is created to bound the command.
For all commands that are not attribute of the object instance nor of
the class, a new attribute of the instance is created to bound the
command.
"""
*/
// For backward compat
.add_static_property("entities", bp::make_function(&getEntityMap, reference_existing_object()));
.add_static_property(
"entities",
bp::make_function(&getEntityMap, reference_existing_object()));
python::exposeEntity<PythonEntity, bp::bases<Entity>, 0>()
.def("signalRegistration", &PythonEntity::signalRegistration)
.def("signalDeregistration", &PythonEntity::signalDeregistration);
python::exposeEntity<python::PythonSignalContainer, bp::bases<Entity>, 0>().def(
"rmSignal", &python::PythonSignalContainer::rmSignal, "Remove a signal", bp::arg("signal_name"));
python::exposeEntity<python::PythonSignalContainer, bp::bases<Entity>, 0>()
.def("rmSignal", &python::PythonSignalContainer::rmSignal,
"Remove a signal", bp::arg("signal_name"));
}
void exposeCommand() {
using dg::command::Command;
bp::class_<Command, boost::noncopyable>("Command", bp::no_init)
.def("__call__", bp::raw_function(dg::python::entity::executeCmd, 1), "execute the command")
.def("__call__", bp::raw_function(dg::python::entity::executeCmd, 1),
"execute the command")
.add_property("__doc__", &Command::getDocstring);
}
void exposeOldAPI() {
bp::def("plug", dynamicgraph::python::plug, "plug an output signal into an input signal",
bp::def("plug", dynamicgraph::python::plug,
"plug an output signal into an input signal",
(bp::arg("signalOut"), "signalIn"));
bp::def("enableTrace", dynamicgraph::python::enableTrace, "Enable or disable tracing debug info in a file");
bp::def("enableTrace", dynamicgraph::python::enableTrace,
"Enable or disable tracing debug info in a file");
// Signals
bp::def("create_signal_wrapper", dynamicgraph::python::signalBase::createSignalWrapper, reference_existing_object(),
"create a SignalWrapper C++ object");
bp::def("create_signal_wrapper",
dynamicgraph::python::signalBase::createSignalWrapper,
reference_existing_object(), "create a SignalWrapper C++ object");
// Entity
bp::def("factory_get_entity_class_list", dynamicgraph::python::factory::getEntityClassList,
bp::def("factory_get_entity_class_list",
dynamicgraph::python::factory::getEntityClassList,
"return the list of entity classes");
bp::def("writeGraph", dynamicgraph::python::pool::writeGraph, "Write the graph of entities in a filename.");
bp::def("get_entity_list", dynamicgraph::python::pool::getEntityList, "return the list of instanciated entities");
bp::def("addLoggerFileOutputStream", dynamicgraph::python::debug::addLoggerFileOutputStream,
bp::def("writeGraph", dynamicgraph::python::pool::writeGraph,
"Write the graph of entities in a filename.");
bp::def("get_entity_list", dynamicgraph::python::pool::getEntityList,
"return the list of instanciated entities");
bp::def("addLoggerFileOutputStream",
dynamicgraph::python::debug::addLoggerFileOutputStream,
"add a output file stream to the logger by filename");
bp::def("addLoggerCoutOutputStream", dynamicgraph::python::debug::addLoggerCoutOutputStream,
bp::def("addLoggerCoutOutputStream",
dynamicgraph::python::debug::addLoggerCoutOutputStream,
"add std::cout as output stream to the logger");
bp::def("closeLoggerFileOutputStream", dynamicgraph::python::debug::closeLoggerFileOutputStream,
bp::def("closeLoggerFileOutputStream",
dynamicgraph::python::debug::closeLoggerFileOutputStream,
"close all the loggers file output streams.");
bp::def("real_time_logger_destroy", dynamicgraph::python::debug::realTimeLoggerDestroy,
bp::def("real_time_logger_destroy",
dynamicgraph::python::debug::realTimeLoggerDestroy,
"Destroy the real time logger.");
bp::def("real_time_logger_spin_once", dynamicgraph::python::debug::realTimeLoggerSpinOnce,
bp::def("real_time_logger_spin_once",
dynamicgraph::python::debug::realTimeLoggerSpinOnce,
"Destroy the real time logger.");
bp::def("real_time_logger_instance", dynamicgraph::python::debug::realTimeLoggerInstance,
bp::def("real_time_logger_instance",
dynamicgraph::python::debug::realTimeLoggerInstance,
"Starts the real time logger.");
}
void enableEigenPy() {
eigenpy::enableEigenPy();
if (!eigenpy::register_symbolic_link_to_registered_type<Eigen::Quaterniond>()) eigenpy::exposeQuaternion();
if (!eigenpy::register_symbolic_link_to_registered_type<Eigen::AngleAxisd>()) eigenpy::exposeAngleAxis();
if (!eigenpy::register_symbolic_link_to_registered_type<Eigen::Quaterniond>())
eigenpy::exposeQuaternion();
if (!eigenpy::register_symbolic_link_to_registered_type<Eigen::AngleAxisd>())
eigenpy::exposeAngleAxis();
eigenpy::enableEigenPySpecific<Eigen::Matrix4d>();
}
......@@ -239,22 +285,33 @@ BOOST_PYTHON_MODULE(wrap) {
typedef dg::PoolStorage::Entities MapOfEntities;
bp::class_<MapOfEntities>("MapOfEntities")
.def("__len__", &MapOfEntities::size)
.def("keys",
+[](const MapOfEntities& m) -> bp::tuple {
bp::list res;
for (const auto& el : m) res.append(el.first);
return bp::tuple(res);
})
.def("values",
+[](const MapOfEntities& m) -> bp::tuple {
bp::list res;
for (const auto& el : m) res.append(bp::ptr(el.second));
return bp::tuple(res);
})
.def("__getitem__", static_cast<dg::Entity*& (MapOfEntities::*)(const std::string& k)>(&MapOfEntities::at),
.def(
"keys",
+[](const MapOfEntities& m) -> bp::tuple {
bp::list res;
for (const auto& el : m) res.append(el.first);
return bp::tuple(res);
})
.def(
"values",
+[](const MapOfEntities& m) -> bp::tuple {
bp::list res;
for (const auto& el : m) res.append(bp::ptr(el.second));
return bp::tuple(res);
})
.def("__getitem__",
static_cast<dg::Entity*& (MapOfEntities::*)(const std::string& k)>(
&MapOfEntities::at),
reference_existing_object())
.def("__setitem__", +[](MapOfEntities& m, const std::string& n, dg::Entity* e) { m.emplace(n, e); })
.def(
"__setitem__", +[](MapOfEntities& m, const std::string& n,
dg::Entity* e) { m.emplace(n, e); })
.def("__iter__", bp::iterator<MapOfEntities>())
.def("__contains__", +[](const MapOfEntities& m, const std::string& n) -> bool { return m.count(n); });
bp::to_python_converter<MapOfEntities::value_type, MapOfEntitiesPairToPythonConverter>();
.def(
"__contains__",
+[](const MapOfEntities& m, const std::string& n) -> bool {
return m.count(n);
});
bp::to_python_converter<MapOfEntities::value_type,
MapOfEntitiesPairToPythonConverter>();
}
// Copyright 2010, Florent Lamiraux, Thomas Moulard, LAAS-CNRS.
#include <iostream>
#include <dynamic-graph/command.h>
#include <dynamic-graph/entity.h>
#include <dynamic-graph/factory.h>
#include <dynamic-graph/command.h>
#include <dynamic-graph/linear-algebra.h>
#include <dynamic-graph/pool.h>
#include <dynamic-graph/value.h>
#include <iostream>
#include "dynamic-graph/python/convert-dg-to-py.hh"
#include "dynamic-graph/python/dynamic-graph-py.hh"
......@@ -38,7 +37,8 @@ namespace entity {
/// \param obj an Entity object
void addCommands(bp::object obj) {
Entity& entity = bp::extract<Entity&>(obj);
for (const auto& el : entity.getNewStyleCommandMap()) obj.attr(el.first.c_str()) = bp::object(bp::ptr(el.second));
for (const auto& el : entity.getNewStyleCommandMap())
obj.attr(el.first.c_str()) = bp::object(bp::ptr(el.second));
}
/// \param obj an Entity object
......@@ -57,16 +57,20 @@ void addSignals(bp::object obj) {
Entity* create(const char* className, const char* instanceName) {
Entity* obj = NULL;
/* Try to find if the corresponding object already exists. */
if (dynamicgraph::PoolStorage::getInstance()->existEntity(instanceName, obj)) {
if (dynamicgraph::PoolStorage::getInstance()->existEntity(instanceName,
obj)) {
if (obj->getClassName() != className) {
throw std::invalid_argument("Found an object named " + std::string(instanceName) +
throw std::invalid_argument("Found an object named " +
std::string(instanceName) +
",\n"
"but this object is of type " +
std::string(obj->getClassName()) + " and not " + std::string(className));
std::string(obj->getClassName()) +
" and not " + std::string(className));
}
} else /* If not, create a new object. */
{
obj = dynamicgraph::FactoryStorage::getInstance()->newEntity(std::string(className), std::string(instanceName));
obj = dynamicgraph::FactoryStorage::getInstance()->newEntity(
std::string(className), std::string(instanceName));
}
return obj;
......@@ -79,7 +83,8 @@ bp::object executeCmd(bp::tuple args, bp::dict) {
throw std::out_of_range("Wrong number of arguments");
std::vector<Value> values;
values.reserve(command.valueTypes().size());
for (int i = 1; i < bp::len(args); ++i) values.push_back(convert::toValue(args[i], command.valueTypes()[i - 1]));
for (int i = 1; i < bp::len(args); ++i)
values.push_back(convert::toValue(args[i], command.valueTypes()[i - 1]));
command.setParameterValues(values);
return convert::fromValue(command.execute());
}
......
......@@ -5,5 +5,5 @@
from __future__ import print_function
# for backward compat
from .wrap import LoggerVerbosity as VerbosityLevel
from .wrap import Entity
from .wrap import LoggerVerbosity as VerbosityLevel # noqa
from .wrap import Entity # noqa
// Copyright 2010, Florent Lamiraux, Thomas Moulard, LAAS-CNRS.
#include <iostream>
#include <dynamic-graph/factory.h>
#include <iostream>
#include "dynamic-graph/python/dynamic-graph-py.hh"
using dynamicgraph::Entity;
......
// Copyright 2011, 2012, Florent Lamiraux, LAAS-CNRS.
#include <dynamic-graph/pool.h>
#include <dynamic-graph/entity.h>
#include <dynamic-graph/pool.h>
#include <vector>
#include "dynamic-graph/python/dynamic-graph-py.hh"
......@@ -11,9 +12,13 @@ namespace python {
namespace pool {
void writeGraph(const char* filename) { PoolStorage::getInstance()->writeGraph(filename); }
void writeGraph(const char* filename) {
PoolStorage::getInstance()->writeGraph(filename);
}
const std::map<std::string, Entity*>* getEntityMap() { return &PoolStorage::getInstance()->getEntityMap(); }
const std::map<std::string, Entity*>* getEntityMap() {
return &PoolStorage::getInstance()->getEntityMap();
}
/**
\brief Get list of entities
......@@ -21,7 +26,8 @@ const std::map<std::string, Entity*>* getEntityMap() { return &PoolStorage::getI
bp::list getEntityList() {
std::vector<std::string> entityNames;
bp::list res;
const PoolStorage::Entities& listOfEntities = PoolStorage::getInstance()->getEntityMap();
const PoolStorage::Entities& listOfEntities =
PoolStorage::getInstance()->getEntityMap();
for (const auto& el : listOfEntities) res.append(el.second->getName());
return res;
......
......@@ -14,16 +14,15 @@ from __future__ import print_function
import sys
from .entity import Entity
from .matlab import matlab
from .signal_base import SignalBase
# Enables shortcut "name"
def sig_short_name(self):
return self.getName().split(':')[-1]
return self.getName().split(":")[-1]
setattr(SignalBase, 'name', property(sig_short_name))
setattr(SignalBase, "name", property(sig_short_name))
# Enables shortcuts "m"
......@@ -39,7 +38,7 @@ class PrettySignalPrint:
self.sig = sig
def __str__(self):
return self.sig.name + " = " + str(matlab(self.sig.value))
return self.sig.name + " = " + str(self.sig.value)
def __repr__(self):
return str(self)
......@@ -57,14 +56,12 @@ def sigMatPrint(sig):
return PrettySignalPrint(sig)
setattr(SignalBase, 'm', property(PrettySignalPrint))
# print('Pretty matlab print set')
setattr(SignalBase, "m", property(PrettySignalPrint))
# Enable the same as 'm', but directly on the signal object.
def sigRepr(self):
return self.name + ' = ' + str(matlab(self.value))
return self.name + " = " + str(self.value)
def sigCall(sig, iter):
......@@ -77,9 +74,9 @@ def sigTimeIncr(sig, iter):
print(sigRepr(sig))
setattr(SignalBase, '__repr__', sigRepr)
setattr(SignalBase, '__call__', sigCall)
setattr(SignalBase, '__add__', sigTimeIncr)
setattr(SignalBase, "__repr__", sigRepr)
setattr(SignalBase, "__call__", sigCall)
setattr(SignalBase, "__add__", sigTimeIncr)
# Enables shortcut "deps"
......@@ -100,12 +97,12 @@ class SignalDepPrint:
return self
setattr(SignalBase, 'deps', property(SignalDepPrint))
setattr(SignalBase, "deps", property(SignalDepPrint))
setattr(Entity, 'sigs', property(Entity.displaySignals))
setattr(Entity, '__repr__', Entity.__str__)
setattr(Entity, "sigs", property(Entity.displaySignals))
setattr(Entity, "__repr__", Entity.__str__)
sys.ps1 = '% '
sys.ps1 = "% "
# Enable function that can be call without()def optionalparentheses(f):
......@@ -119,7 +116,7 @@ def optionalparentheses(f):
if isinstance(res, str):
return res
else:
return ''
return ""
def __call__(self, *arg):
return self.functor(*arg)
......
// Copyright 2010, Florent Lamiraux, Thomas Moulard, LAAS-CNRS.
#include <iostream>
#include <sstream>
#include <boost/python.hpp>
#include "dynamic-graph/python/signal.hh"
#include <dynamic-graph/linear-algebra.h>
#include <dynamic-graph/signal-base.h>
#include <dynamic-graph/signal.h>
#include <dynamic-graph/signal-ptr.h>
#include <dynamic-graph/signal-time-dependent.h>
#include <dynamic-graph/linear-algebra.h>
#include <dynamic-graph/signal.h>
#include <dynamic-graph/value.h>
#include <boost/python.hpp>
#include <iostream>
#include <sstream>
#include "dynamic-graph/python/dynamic-graph-py.hh"
#include "dynamic-graph/python/signal-wrapper.hh"
#include "dynamic-graph/python/signal.hh"
using dynamicgraph::SignalBase;
......@@ -43,52 +41,68 @@ template <typename Time>
void exposeSignalBase(const char* name) {
typedef SignalBase<Time> S_t;
bp::class_<S_t, boost::noncopyable>(name, bp::no_init)
.add_property("time", bp::make_function(&S_t::getTime, bp::return_value_policy<bp::copy_const_reference>()),
.add_property("time",
bp::make_function(
&S_t::getTime,
bp::return_value_policy<bp::copy_const_reference>()),
&S_t::setTime)
.add_property("name", bp::make_function(&S_t::getName, bp::return_value_policy<bp::copy_const_reference>()))
.def("getName", &S_t::getName, bp::return_value_policy<bp::copy_const_reference>())
.def("getClassName",
+[](const S_t& s) -> std::string {
std::string ret;
s.getClassName(ret);
return ret;
})
.add_property("name",
bp::make_function(
&S_t::getName,
bp::return_value_policy<bp::copy_const_reference>()))
.def("getName", &S_t::getName,
bp::return_value_policy<bp::copy_const_reference>())
.def(
"getClassName",
+[](const S_t& s) -> std::string {
std::string ret;
s.getClassName(ret);
return ret;
})
.def("plug", &S_t::plug, "Plug the signal to another signal")
.def("unplug", &S_t::unplug, "Unplug the signal")
.def("isPlugged", &S_t::isPlugged, "Whether the signal is plugged")
.def("getPlugged", &S_t::getPluged, bp::return_value_policy<bp::reference_existing_object>(),
.def("getPlugged", &S_t::getPluged,
bp::return_value_policy<bp::reference_existing_object>(),
"To which signal the signal is plugged")
.def("recompute", &S_t::recompute, "Recompute the signal at given time")
.def("__str__",
+[](const S_t& s) -> std::string {
std::ostringstream oss;
s.display(oss);
return oss.str();
})
.def("displayDependencies",
+[](const S_t& s, int time) -> std::string {
std::ostringstream oss;
s.displayDependencies(oss, time);
return oss.str();
},
"Print the signal dependencies in a string");
.def(
"__str__",
+[](const S_t& s) -> std::string {
std::ostringstream oss;
s.display(oss);
return oss.str();
})
.def(
"displayDependencies",
+[](const S_t& s, int time) -> std::string {
std::ostringstream oss;
s.displayDependencies(oss, time);
return oss.str();
},
"Print the signal dependencies in a string");
}
template <>
auto exposeSignal<MatrixHomogeneous, time_type>(const std::string& name) {
typedef Signal<MatrixHomogeneous, time_type> S_t;
bp::class_<S_t, bp::bases<SignalBase<time_type> >, boost::noncopyable> obj(name.c_str(), bp::init<std::string>());
obj.add_property("value", +[](const S_t& signal) -> Matrix4 { return signal.accessCopy().matrix(); },
+[](S_t& signal, const Matrix4& v) {
// TODO it isn't hard to support pinocchio::SE3 type here.
// However, this adds a dependency to pinocchio.
signal.setConstant(MatrixHomogeneous(v));
},
"the signal value.");
bp::class_<S_t, bp::bases<SignalBase<time_type> >, boost::noncopyable> obj(
name.c_str(), bp::init<std::string>());
obj.add_property(
"value",
+[](const S_t& signal) -> Matrix4 {
return signal.accessCopy().matrix();
},
+[](S_t& signal, const Matrix4& v) {
// TODO it isn't hard to support pinocchio::SE3 type here.
// However, this adds a dependency to pinocchio.
signal.setConstant(MatrixHomogeneous(v));
},
"the signal value.");
return obj;
}
......@@ -115,7 +129,8 @@ void exposeSignals() {
namespace signalBase {
template <class T>
SignalWrapper<T, int>* createSignalWrapperTpl(const char* name, bp::object o, std::string& error) {
SignalWrapper<T, int>* createSignalWrapperTpl(const char* name, bp::object o,
std::string& error) {
typedef SignalWrapper<T, int> SignalWrapper_t;
if (!SignalWrapper_t::checkCallable(o, error)) {
return NULL;
......@@ -138,7 +153,8 @@ PythonSignalContainer* getPythonSignalContainer() {
/**
\brief Create an instance of SignalWrapper
*/
SignalBase<int>* createSignalWrapper(const char* name, const char* type, bp::object object) {
SignalBase<int>* createSignalWrapper(const char* name, const char* type,
bp::object object) {
PythonSignalContainer* psc = getPythonSignalContainer();
if (psc == NULL) return NULL;
......
// Copyright (c) 2018, Joseph Mirabel
// Authors: Joseph Mirabel (joseph.mirabel@laas.fr)
#include <dynamic-graph/factory.h>
#include <dynamic-graph/command-bind.h>
#include "dynamic-graph/python/signal-wrapper.hh"
#include <dynamic-graph/command-bind.h>
#include <dynamic-graph/factory.h>
namespace dynamicgraph {
namespace python {
void PythonSignalContainer::signalRegistration(const SignalArray<int>& signals) {
void PythonSignalContainer::signalRegistration(
const SignalArray<int>& signals) {
Entity::signalRegistration(signals);
}
void PythonSignalContainer::rmSignal(const std::string& name) { Entity::signalDeregistration(name); }
void PythonSignalContainer::rmSignal(const std::string& name) {
Entity::signalDeregistration(name);
}
DYNAMICGRAPH_FACTORY_ENTITY_PLUGIN(PythonSignalContainer, "PythonSignalContainer");
DYNAMICGRAPH_FACTORY_ENTITY_PLUGIN(PythonSignalContainer,
"PythonSignalContainer");
template <class T, class Time>
bool SignalWrapper<T, Time>::checkCallable(pyobject c, std::string& error) {
......
......@@ -4,28 +4,35 @@
from __future__ import print_function
from .wrap import SignalBase, create_signal_wrapper as SignalWrapper
# I kept what follows for backward compatibility but I think it should be
# removed
import re
from .wrap import SignalBase # noqa
from .wrap import create_signal_wrapper as SignalWrapper # noqa
def stringToTuple(vector):
"""
Transform a string of format '[n](x_1,x_2,...,x_n)' into a tuple of numbers.
"""
# Find vector length
a = re.match(r'\[(\d+)\]', vector)
a = re.match(r"\[(\d+)\]", vector)
size = int(a.group(1))
# remove '[n]' prefix
vector = vector[len(a.group(0)):]
vector = vector[len(a.group(0)) :]
# remove '(' and ')' at beginning and end
vector = vector.lstrip('(').rstrip(')\n')
vector = vector.lstrip("(").rstrip(")\n")
# split string by ','
vector = vector.split(',')
vector = vector.split(",")
# check size
if len(vector) != size:
raise TypeError('displayed size ' + str(size) + ' of vector does not fit actual size: ' + str(len(vector)))
raise TypeError(
"displayed size "
+ str(size)
+ " of vector does not fit actual size: "
+ str(len(vector))
)
res = map(float, vector)
return tuple(res)
......@@ -35,10 +42,10 @@ def tupleToString(vector):
Transform a tuple of numbers into a string of format
'[n](x_1, x_2, ..., x_n)'
"""
string = '[%d](' % len(vector)
string = "[%d](" % len(vector)
for x in vector[:-1]:
string += '%f,' % x
string += '%f)' % vector[-1]
string += "%f," % x
string += "%f)" % vector[-1]
return string
......@@ -49,20 +56,30 @@ def stringToMatrix(string):
of tuple of numbers.
"""
# Find matrix size
a = re.search(r'\[(\d+),(\d+)]', string)
a = re.search(r"\[(\d+),(\d+)]", string)
nRows = int(a.group(1))
nCols = int(a.group(2))
# Remove '[n,m]' prefix
string = string[len(a.group(0)):]
rows = string.split('),(')
string = string[len(a.group(0)) :]
rows = string.split("),(")
if len(rows) != nRows:
raise TypeError('displayed nb rows ' + nRows + ' of matrix does not fit actual nb rows: ' + str(len(rows)))
raise TypeError(
"displayed nb rows "
+ nRows
+ " of matrix does not fit actual nb rows: "
+ str(len(rows))
)
m = []
for rstr in rows:
rstr = rstr.lstrip('(').rstrip(')\n')
r = map(float, rstr.split(','))
rstr = rstr.lstrip("(").rstrip(")\n")
r = map(float, rstr.split(","))
if len(r) != nCols:
raise TypeError('one row length ' + len(r) + ' of matrix does not fit displayed nb cols: ' + nCols)
raise TypeError(
"one row length "
+ len(r)
+ " of matrix does not fit displayed nb cols: "
+ nCols
)
m.append(tuple(r))
return tuple(m)
......@@ -74,19 +91,19 @@ def matrixToString(matrix):
"""
nRows = len(matrix)
if nRows == 0:
return '[0,0](())'
return "[0,0](())"
nCols = len(matrix[0])
string = '[%d,%d](' % (nRows, nCols)
string = "[%d,%d](" % (nRows, nCols)
for r in range(nRows):
string += '('
string += "("
for c in range(nCols):
string += str(float(matrix[r][c]))
if c != nCols - 1:
string += ','
string += ')'
string += ","
string += ")"
if r != nRows - 1:
string += ','
string += ')'
string += ","
string += ")"
return string
......@@ -100,18 +117,18 @@ def objectToString(obj):
- an integer,
- a boolean,
"""
if (hasattr(obj, "__iter__")):
if hasattr(obj, "__iter__"):
# matrix or vector
if len(obj) == 0:
return ""
else:
if (hasattr(obj[0], "__iter__")):
if hasattr(obj[0], "__iter__"):
# matrix
return matrixToString(obj)
else:
# vector
return tupleToString(obj)
elif hasattr(obj, 'name'):
elif hasattr(obj, "name"):
return obj.name
else:
return str(obj)
......
......@@ -8,8 +8,8 @@ def addTrace(robot, trace, entityName, signalName, autoRecompute=True):
"""
Add a signal to a tracer and recompute it automatically if necessary.
"""
signal = '{0}.{1}'.format(entityName, signalName)
filename = '{0}-{1}'.format(entityName, signalName)
signal = "{0}.{1}".format(entityName, signalName)
filename = "{0}-{1}".format(entityName, signalName).replace("/", "_")
trace.add(signal, filename)
if autoRecompute:
robot.device.after.addSignal(signal)
#include "dynamic-graph/python/module.hh"
#include <dynamic-graph/tracer.h>
#include "dynamic-graph/python/module.hh"
BOOST_PYTHON_MODULE(wrap) {
using dynamicgraph::Tracer;
bp::import("dynamic_graph");
dynamicgraph::python::exposeEntity<Tracer>().def("addSignal", &Tracer::addSignalToTrace);
dynamicgraph::python::exposeEntity<Tracer>().def("addSignal",
&Tracer::addSignalToTrace);
}
#include "dynamic-graph/python/module.hh"
#include <dynamic-graph/tracer-real-time.h>
#include "dynamic-graph/python/module.hh"
BOOST_PYTHON_MODULE(wrap) {
using dynamicgraph::Tracer;
using dynamicgraph::TracerRealTime;
......