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 1083 additions and 1712 deletions
// Copyright 2019, Olivier Stasse, LAAS-CNRS.
//
// See LICENSE
#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 <vector>
#include "dynamic-graph/python/dynamic-graph-py.hh"
typedef boost::shared_ptr<std::ofstream> ofstreamShrPtr;
namespace dynamicgraph {
namespace python {
namespace debug {
std::map<std::string, ofstreamShrPtr> mapOfFiles_;
void addLoggerFileOutputStream(const char* filename) {
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_[filename] = ofs_shrptr;
}
void closeLoggerFileOutputStream() {
for (const auto& el : mapOfFiles_) el.second->close();
}
void addLoggerCoutOutputStream() { dgADD_OSTREAM_TO_RTLOG(std::cout); }
void realTimeLoggerDestroy() { RealTimeLogger::destroy(); }
void realTimeLoggerSpinOnce() { RealTimeLogger::instance().spinOnce(); }
void realTimeLoggerInstance() { RealTimeLogger::instance(); }
} // namespace debug
} // namespace python
} // namespace dynamicgraph
// Copyright 2010, Florent Lamiraux, Thomas Moulard, LAAS-CNRS.
#include "dynamic-graph/python/dynamic-graph-py.hh"
#include <dynamic-graph/command.h>
#include <dynamic-graph/debug.h>
#include <dynamic-graph/entity.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 <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 {
/**
\brief plug a signal into another one.
*/
void plug(SignalBase<int>* signalOut, SignalBase<int>* signalIn) {
signalIn->plug(signalOut);
}
void enableTrace(bool enable, const char* filename) {
if (enable)
DebugTrace::openFile(filename);
else
DebugTrace::closeFile(filename);
}
} // namespace python
} // namespace dynamicgraph
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 dg::PoolStorage::Entities MapOfEntities;
struct MapOfEntitiesPairToPythonConverter {
static PyObject* convert(const MapOfEntities::value_type& pair) {
return bp::incref(bp::make_tuple(pair.first, bp::ptr(pair.second)).ptr());
}
};
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);
}
class PythonEntity : public dg::Entity {
DYNAMIC_GRAPH_ENTITY_DECL();
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);
}
};
DYNAMICGRAPH_FACTORY_ENTITY_PLUGIN(PythonEntity, "PythonEntity");
void exposeEntityBase() {
using namespace dynamicgraph;
bp::enum_<LoggerVerbosity>("LoggerVerbosity")
.value("VERBOSITY_ALL", VERBOSITY_ALL)
.value("VERBOSITY_INFO_WARNING_ERROR", VERBOSITY_INFO_WARNING_ERROR)
.value("VERBOSITY_WARNING_ERROR", VERBOSITY_WARNING_ERROR)
.value("VERBOSITY_ERROR", VERBOSITY_ERROR)
.value("VERBOSITY_NONE", VERBOSITY_NONE)
.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("className",
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,
"the verbosity level of the entity")
.def("setTimeSample", &Entity::setTimeSample)
.def("getTimeSample", &Entity::getTimeSample)
.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,
"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); },
// 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("__getattr__", +[](Entity& e, const std::string &name) ->
SignalBase<int>* { return &e.getSignal(name); },
reference_existing_object())
def __getattr__(self, name):
try:
return self.signal(name)
except Exception:
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')
*/
/*
.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)
})
*/
/* 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.
"""
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 backward compat
.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"));
}
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")
.add_property("__doc__", &Command::getDocstring);
}
void exposeOldAPI() {
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");
// Signals
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,
"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,
"add a output file stream to the logger by filename");
bp::def("addLoggerCoutOutputStream",
dynamicgraph::python::debug::addLoggerCoutOutputStream,
"add std::cout as output stream to the logger");
bp::def("closeLoggerFileOutputStream",
dynamicgraph::python::debug::closeLoggerFileOutputStream,
"close all the loggers file output streams.");
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,
"Destroy the real time logger.");
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();
eigenpy::enableEigenPySpecific<Eigen::Matrix4d>();
}
BOOST_PYTHON_MODULE(wrap) {
enableEigenPy();
exposeOldAPI();
dg::python::exposeSignals();
exposeEntityBase();
exposeCommand();
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),
reference_existing_object())
.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>();
}
// Copyright 2010, Florent Lamiraux, Thomas Moulard, LAAS-CNRS.
#include <dynamic-graph/command.h>
#include <dynamic-graph/entity.h>
#include <dynamic-graph/factory.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"
// Ignore "dereferencing type-punned pointer will break strict-aliasing rules"
// warnings on gcc caused by Py_RETURN_TRUE and Py_RETURN_FALSE.
#if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2))
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
#endif
namespace bp = boost::python;
using dynamicgraph::Entity;
using dynamicgraph::Matrix;
using dynamicgraph::SignalBase;
using dynamicgraph::Vector;
using dynamicgraph::command::Command;
using dynamicgraph::command::Value;
namespace dynamicgraph {
namespace python {
using namespace convert;
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));
}
/// \param obj an Entity object
void addSignals(bp::object obj) {
Entity& entity = bp::extract<Entity&>(obj);
for (const auto& el : entity.getSignalMap())
// obj.attr(el.first.c_str()) = bp::make_function(
//+[&entity,el]() { return &entity.getSignal(el.first); },
// bp::return_value_policy<bp::reference_existing_object>());
obj.attr(el.first.c_str()) = bp::object(bp::ptr(el.second));
}
/**
\brief Create an instance of Entity
*/
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 (obj->getClassName() != className) {
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));
}
} else /* If not, create a new object. */
{
obj = dynamicgraph::FactoryStorage::getInstance()->newEntity(
std::string(className), std::string(instanceName));
}
return obj;
}
bp::object executeCmd(bp::tuple args, bp::dict) {
Command& command = bp::template extract<Command&>(args[0]);
if (bp::len(args) != int(command.valueTypes().size() + 1))
// TODO Put expected and given number of args
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]));
command.setParameterValues(values);
return convert::fromValue(command.execute());
}
} // namespace entity
} // namespace python
} // namespace dynamicgraph
"""
Copyright (C) 2010 CNRS
# Copyright (C) 2020 CNRS
#
# Author: Florent Lamiraux, Nicolas Mansard
Author: Florent Lamiraux, Nicolas Mansard
"""
import wrap, signal_base, new
from attrpath import setattrpath
from __future__ import print_function
if 'display' not in globals().keys():
def display(s):
print(s)
# --- FACTORY ------------------------------------------------------------------
# --- FACTORY ------------------------------------------------------------------
# --- FACTORY ------------------------------------------------------------------
class PyEntityFactoryClass(type):
"""
The class build dynamically a new class type, and return the reference
on the class-type object. The class type is not added to any context.
"""
def __new__(factory, className,bases=(), dict={} ):
if len(bases)==0:
# Initialize a basic Entity class
EntityClass = type.__new__(factory, className, (Entity,), dict)
EntityClass.className = className
EntityClass.__init__ = Entity.initEntity
else:
# Initialize a heritated class
EntityClass = type.__new__(factory, className, bases, dict)
for c in bases:
if issubclass(c,Entity):
EntityClass.className = c.className
break
EntityClass.commandCreated = False
return EntityClass
def PyEntityFactory( className, context ):
"""
Build a new class type by calling the factory, and add it
to the given context.
"""
EntityClass = PyEntityFactoryClass( className )
context[ className ] = EntityClass
return EntityClass
def updateEntityClasses(dictionary):
"""
For all c++entity types that are not in the pyentity class list
(entityClassNameList) run the factory and store the new type in the given
context (dictionary).
"""
cxx_entityList = wrap.factory_get_entity_class_list()
for e in filter(lambda x: not x in Entity.entityClassNameList, cxx_entityList):
# Store new class in dictionary with class name
PyEntityFactory( e,dictionary )
# Store class name in local list
Entity.entityClassNameList.append(e)
# --- ENTITY -------------------------------------------------------------------
# --- ENTITY -------------------------------------------------------------------
# --- ENTITY -------------------------------------------------------------------
from enum import Enum
class VerbosityLevel(Enum):
"""
Enum class for setVerbosityLevel
"""
VERBOSITY_ALL =0
VERBOSITY_INFO_WARNING_ERROR = 1
VERBOSITY_WARNING_ERROR = 2
VERBOSITY_ERROR = 3
VERBOSITY_NONE = 4
class Entity (object) :
"""
This class binds dynamicgraph::Entity C++ class
"""
obj = None
"""
Store list of entities created via python
"""
entities = dict ()
def __init__(self, className, instanceName):
"""
Constructor: if not called by a child class, create and store a pointer
to a C++ Entity object.
"""
object.__setattr__(self, 'obj', wrap.create_entity(className, instanceName) )
Entity.entities [instanceName] = self
@staticmethod
def initEntity(self, name):
"""
Common constructor of specialized Entity classes. This function is bound
by the factory to each new class derivated from the Entity class as the
constructor of the new class.
"""
Entity.__init__(self, self.className, name)
if not self.__class__.commandCreated:
self.boundClassCommands()
self.__class__.__doc__ = wrap.entity_get_docstring (self.obj)
self.__class__.commandCreated = True
@property
def name(self) :
return wrap.entity_get_name(self.obj)
@property
def className(self) :
return wrap.entity_get_class_name(self.obj)
def __str__(self) :
return wrap.display_entity(self.obj)
def signal (self, name) :
"""
Get a signal of the entity from signal name
"""
signalPt = wrap.entity_get_signal(self.obj, name)
return signal_base.SignalBase(name = "", obj = signalPt)
def hasSignal(self, name) :
"""
Indicates if a signal with the given name exists in the entity
"""
return wrap.entity_has_signal(self.obj, name)
def displaySignals(self) :
"""
Print the list of signals into standard output: temporary.
"""
signals = self.signals()
if len(signals) == 0:
display ("--- <" + self.name + "> has no signal")
else:
display ("--- <" + self.name + "> signal list: ")
for s in signals[:-1]:
display(" |-- <" + str(s))
display(" `-- <" + str(signals[-1]))
def signals(self) :
"""
Return the list of signals
"""
sl = wrap.entity_list_signals(self.obj)
return map(lambda pyObj: signal_base.SignalBase(obj=pyObj), sl)
def commands(self):
"""
Return the list of commands.
"""
return wrap.entity_list_commands(self.obj)
def globalHelp(self):
"""
Print a short description of each command.
"""
if self.__doc__ :
print self.__doc__
print "List of commands:"
print "-----------------"
for cstr in self.commands():
ctitle=cstr+':'
for i in range(len(cstr),15):
ctitle+=' '
for docstr in wrap.entity_get_command_docstring(self.obj,cstr).split('\n'):
if (len(docstr)>0) and (not docstr.isspace()):
display(ctitle+"\t"+docstr)
break
def help( self,comm=None ):
"""
With no arg, print the global help. With arg the name of
a specific command, print the help associated to the command.
"""
if comm is None:
self.globalHelp()
else:
display(comm+":\n"+wrap.entity_get_command_docstring(self.obj,comm))
def __getattr__(self, name):
try:
return self.signal(name)
except:
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')
def __setattr__(self, name, value):
if name in map(lambda s: s.getName().split(':')[-1],self.signals()):
raise NameError(name+" already designates a signal. "
"It is not advised to set a new attribute of the same name.")
object.__setattr__(self, name, value)
# --- COMMANDS BINDER -----------------------------------------------------
# List of all the entity classes from the c++ factory, that have been bound
# bind the py factory.
entityClassNameList = []
# This function dynamically create the function object that runs the command.
@staticmethod
def createCommandBind(name, docstring) :
def commandBind(self, *arg):
return wrap.entity_execute_command(self.obj, name, arg)
commandBind.__doc__ = docstring
return commandBind
def boundClassCommands(self):
"""
This static function has to be called from a class heritating from Entity.
It should be called only once. It parses the list of commands obtained from
c++, and bind each of them to a python class method.
"""
# Get list of commands of the Entity object
commands = wrap.entity_list_commands(self.obj)
# for each command, add a method with the name of the command
for cmdstr in commands:
docstr = wrap.entity_get_command_docstring(self.obj, cmdstr)
cmdpy = Entity.createCommandBind(cmdstr, docstr)
setattrpath(self.__class__, cmdstr, cmdpy)
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.
"""
if (cmdName in self.__dict__) | (cmdName in self.__class__.__dict__):
print("Warning: command ",cmdName," will overwrite an object attribute.")
docstring = wrap.entity_get_command_docstring(self.obj, cmdName)
cmd = Entity.createCommandBind(cmdName,docstring)
# Limitation (todo): does not handle for path attribute name (see setattrpath).
setattr(self,cmdName,new.instancemethod( cmd, self,self.__class__))
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.
"""
cmdList = wrap.entity_list_commands(self.obj)
cmdList = filter(lambda x: not x in self.__dict__, cmdList)
cmdList = filter(lambda x: not x in self.__class__.__dict__, cmdList)
for cmd in cmdList:
self.boundNewCommand( cmd )
def setLoggerVerbosityLevel(self,verbosity):
"""
Specify for the entity the verbosity level
"""
return wrap.entity_set_logger_verbosity(self.obj, verbosity)
def getLoggerVerbosityLevel(self):
"""
Returns the entity's verbosity level
"""
r=wrap.entity_get_logger_verbosity(self.obj)
if r==0:
return VerbosityLevel.VERBOSITY_ALL
elif r==1:
return VerbosityLevel.VERBOSITY_INFO_WARNING_ERROR
elif r==2:
return VerbosityLevel.VERBOSITY_WARNING_ERROR
elif r==3:
return VerbosityLevel.VERBOSITY_ERROR
return VerbosityLevel.VERBOSITY_NONE
def setTimeSample(self,timeSample):
"""
Specify for the entity the time at which call is counted.
"""
return wrap.entity_set_time_sample(self.obj, timeSample)
def getTimeSample(self):
"""
Returns for the entity the time at which call is counted.
"""
return wrap.entity_get_time_sample(self.obj)
def setStreamPrintPeriod(self,streamPrintPeriod):
"""
Specify for the entity the period at which debugging information is printed
"""
return wrap.entity_set_stream_print_period(self.obj, streamPrintPeriod)
def getStreamPrintPeriod(self):
"""
Returns for the entity the period at which debugging information is printed
"""
return wrap.entity_get_stream_print_period(self.obj)
# for backward compat
from .wrap import LoggerVerbosity as VerbosityLevel # noqa
from .wrap import Entity # noqa
// Copyright 2010, Florent Lamiraux, Thomas Moulard, LAAS-CNRS.
#include <dynamic-graph/factory.h>
#include <iostream>
#include "dynamic-graph/python/dynamic-graph-py.hh"
using dynamicgraph::Entity;
using dynamicgraph::ExceptionAbstract;
namespace dynamicgraph {
namespace python {
namespace factory {
/**
\brief Get name of entity
*/
bp::tuple getEntityClassList() {
std::vector<std::string> classNames;
dynamicgraph::FactoryStorage::getInstance()->listEntities(classNames);
return to_py_tuple(classNames.begin(), classNames.end());
}
} // namespace factory
} // namespace python
} // namespace dynamicgraph
# The matlab class is define to produce a nice rendering of vector and matrix
# signals. The class builds at construction a string from the display
# of the matrix/vector, and stores the string internally. The string can be recovered
# using the str() member.
# The statics prec, space and fullPrec can be used to modify the display.
def pseudozero(prec):
"""
Return a string with '0...' and enough space to fill prec cars.
"""
res='0...'
for i in range(2,prec):
res+=' '
return res
class matlab:
prec=12
space=2
fullPrec=1e-5
def __init__( self,obj ):
try:
return self.matlabFromMatrix(obj)
except:
pass
try:
return self.matlabFromVector(obj)
except:
pass
self.resstr = str(obj)
def __str__(self):
return self.resstr
def matlabFromMatrix(self,A):
nr=len(A)
nc=len(A[0]);
fm='%.'+str(self.prec)+'f'
maxstr=0
mstr=(())
for v in A:
lnstr=()
for x in v:
if (abs(x)<self.fullPrec*self.fullPrec):
curr='0'
else:
if (abs(x)<self.fullPrec):
curr=pseudozero(self.prec)
else:
curr= ' '+(fm % x)
if( maxstr<len(curr)):
maxstr=len(curr)
lnstr+=(curr,)
mstr+=(lnstr,)
maxstr+=self.space
resstr='[...\n'
first=True
for v in mstr:
if first:
first=False;
else:
resstr+=' ;\n'
firstC=True
for x in v:
if firstC:
firstC=False
else:
resstr+=','
for i in range(1,maxstr-len(x)):
resstr+=' '
resstr+=x
resstr+=' ];'
self.resstr = resstr
def matlabFromVector(self,v):
nr=len(v)
fm='%.'+str(self.prec)+'f'
maxstr=0
vstr=(())
for x in v:
if (abs(x)<self.fullPrec*self.fullPrec):
curr='0'
else:
if (abs(x)<self.fullPrec):
curr=pseudozero(self.prec)
else:
curr= ' '+(fm % x)
if( maxstr<len(curr)):
maxstr=len(curr)
vstr+=(curr,)
maxstr+=self.space
resstr='[ '
first=True
for x in vstr:
if first:
first=False;
else:
resstr+=','
for i in range(1,maxstr-len(x)):
resstr+=' '
resstr+=x
resstr+=' ]\';'
self.resstr = resstr
// Copyright 2011, 2012, Florent Lamiraux, LAAS-CNRS.
#include <dynamic-graph/entity.h>
#include <dynamic-graph/pool.h>
#include <vector>
#include "dynamic-graph/python/dynamic-graph-py.hh"
namespace dynamicgraph {
namespace python {
namespace pool {
void writeGraph(const char* filename) {
PoolStorage::getInstance()->writeGraph(filename);
}
const std::map<std::string, Entity*>* getEntityMap() {
return &PoolStorage::getInstance()->getEntityMap();
}
/**
\brief Get list of entities
*/
bp::list getEntityList() {
std::vector<std::string> entityNames;
bp::list res;
const PoolStorage::Entities& listOfEntities =
PoolStorage::getInstance()->getEntityMap();
for (const auto& el : listOfEntities) res.append(el.second->getName());
return res;
}
} // namespace pool
} // namespace python
} // namespace dynamicgraph
#include "dynamic-graph/python/python-compat.hh"
// Get any PyObject and get its str() representation as an std::string
std::string obj_to_str(PyObject* o) {
std::string ret;
PyObject* os;
#if PY_MAJOR_VERSION >= 3
os = PyObject_Str(o);
assert(os != NULL);
assert(PyUnicode_Check(os));
ret = PyUnicode_AsUTF8(os);
#else
os = PyObject_Unicode(o);
assert(os != NULL);
assert(PyUnicode_Check(os));
PyObject* oss = PyUnicode_AsUTF8String(os);
assert(oss != NULL);
ret = PyString_AsString(oss);
Py_DECREF(oss);
#endif
Py_DECREF(os);
return ret;
}
......@@ -8,17 +8,22 @@
# entity -> same as print(entity)
# change the prompt to be '%'
from __future__ import print_function
# Changing prompt
import sys
from .entity import Entity
from .signal_base import SignalBase
from dynamic_graph.signal_base import *
from dynamic_graph.entity import *
from matlab import matlab
# 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"
# This code implements a pseudo function 'm' in the class signal_base,
......@@ -28,40 +33,51 @@ setattr(SignalBase,'name',property(sig_short_name))
# - sig.m +time: recompute at <time> after current time, and display.
class PrettySignalPrint:
sig = None
def __init__(self,sig):
def __init__(self, sig):
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)
def __call__(self,iter):
def __call__(self, iter):
self.sig.recompute(iter)
return self
def __add__(self,iter):
self.sig.recompute( self.sig.time+iter )
def __add__(self, iter):
self.sig.recompute(self.sig.time + iter)
return self
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))
def sigRepr(self):
return self.name + " = " + str(self.value)
def sigCall( sig,iter ):
def sigCall(sig, iter):
sig.recompute(iter)
print(sigRepr(sig))
def sigTimeIncr( sig,iter ):
sig.recompute(sig.time+iter)
def sigTimeIncr(sig, iter):
sig.recompute(sig.time + 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"
# Implements the peudo function 'deps', that can be called without arg,
......@@ -69,31 +85,40 @@ setattr(SignalBase,'__add__',sigTimeIncr)
class SignalDepPrint:
defaultDepth = 2
sig = None
def __init__(self,sig):
self.sig=sig
def __init__(self, sig):
self.sig = sig
def __repr__(self):
return self.sig.displayDependencies(self.defaultDepth)
def __call__(self,depth):
def __call__(self, depth):
self.defaultDepth = depth
return self
setattr(SignalBase,'deps',property(SignalDepPrint))
setattr(Entity,'sigs',property(Entity.displaySignals))
setattr(Entity,'__repr__',Entity.__str__)
setattr(SignalBase, "deps", property(SignalDepPrint))
setattr(Entity, "sigs", property(Entity.displaySignals))
setattr(Entity, "__repr__", Entity.__str__)
sys.ps1 = "% "
# Changing prompt
import sys
sys.ps1 = '% '
# Enable function that can be call without()def optionalparentheses(f):
def optionalparentheses(f):
class decoclass:
def __init__(self,f): self.functor=f
def __init__(self, f):
self.functor = f
def __repr__(self):
res=self.functor()
if isinstance(res,str): return res
else: return ''
def __call__(self,*arg):
res = self.functor()
if isinstance(res, str):
return res
else:
return ""
def __call__(self, *arg):
return self.functor(*arg)
return decoclass(f)
// Copyright 2010, Florent Lamiraux, Thomas Moulard, LAAS-CNRS.
#include <dynamic-graph/linear-algebra.h>
#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 <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;
namespace bp = boost::python;
namespace dynamicgraph {
namespace python {
typedef int time_type;
typedef Eigen::AngleAxis<double> VectorUTheta;
typedef Eigen::Quaternion<double> Quaternion;
typedef Eigen::VectorXd Vector;
typedef Eigen::Vector3d Vector3;
typedef Eigen::Matrix<double, 7, 1> Vector7;
typedef Eigen::MatrixXd Matrix;
typedef Eigen::Matrix<double, 3, 3> MatrixRotation;
typedef Eigen::Matrix<double, 4, 4> Matrix4;
typedef Eigen::Transform<double, 3, Eigen::Affine> MatrixHomogeneous;
typedef Eigen::Matrix<double, 6, 6> MatrixTwist;
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>()),
&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;
})
.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>(),
"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");
}
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.");
return obj;
}
void exposeSignals() {
exposeSignalBase<time_type>("SignalBase");
exposeSignalsOfType<bool, time_type>("Bool");
exposeSignalsOfType<int, time_type>("Int");
exposeSignalsOfType<double, time_type>("Double");
exposeSignalsOfType<Vector, time_type>("Vector");
exposeSignalsOfType<Vector3, time_type>("Vector3");
exposeSignalsOfType<Vector7, time_type>("Vector7");
exposeSignalsOfType<Matrix, time_type>("Matrix");
exposeSignalsOfType<MatrixRotation, time_type>("MatrixRotation");
exposeSignalsOfType<MatrixHomogeneous, time_type>("MatrixHomogeneous");
exposeSignalsOfType<MatrixTwist, time_type>("MatrixTwist");
exposeSignalsOfType<Quaternion, time_type>("Quaternion");
exposeSignalsOfType<VectorUTheta, time_type>("VectorUTheta");
}
namespace signalBase {
template <class T>
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;
}
SignalWrapper_t* obj = new SignalWrapper_t(name, o);
return obj;
}
PythonSignalContainer* getPythonSignalContainer() {
Entity* obj = entity::create("PythonSignalContainer", "python_signals");
return dynamic_cast<PythonSignalContainer*>(obj);
}
#define SIGNAL_WRAPPER_TYPE(IF, Enum, Type) \
IF(command::Value::typeName(command::Value::Enum).compare(type) == 0) { \
obj = createSignalWrapperTpl<Type>(name, object, error); \
}
/**
\brief Create an instance of SignalWrapper
*/
SignalBase<int>* createSignalWrapper(const char* name, const char* type,
bp::object object) {
PythonSignalContainer* psc = getPythonSignalContainer();
if (psc == NULL) return NULL;
SignalBase<int>* obj = NULL;
std::string error;
SIGNAL_WRAPPER_TYPE(if, BOOL, bool)
// SIGNAL_WRAPPER_TYPE(else if, UNSIGNED ,bool)
SIGNAL_WRAPPER_TYPE(else if, INT, int)
SIGNAL_WRAPPER_TYPE(else if, FLOAT, float)
SIGNAL_WRAPPER_TYPE(else if, DOUBLE, double)
// SIGNAL_WRAPPER_TYPE(else if, STRING ,bool)
SIGNAL_WRAPPER_TYPE(else if, VECTOR, Vector)
// SIGNAL_WRAPPER_TYPE(else if, MATRIX ,bool)
// SIGNAL_WRAPPER_TYPE(else if, MATRIX4D ,bool)
else {
error = "Type not understood";
}
if (obj == NULL) throw std::runtime_error(error);
// Register signal into the python signal container
psc->signalRegistration(*obj);
// Return the pointer
return obj;
}
} // namespace signalBase
} // namespace python
} // namespace dynamicgraph
// Copyright (c) 2018, Joseph Mirabel
// Authors: Joseph Mirabel (joseph.mirabel@laas.fr)
#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) {
Entity::signalRegistration(signals);
}
void PythonSignalContainer::rmSignal(const std::string& name) {
Entity::signalDeregistration(name);
}
DYNAMICGRAPH_FACTORY_ENTITY_PLUGIN(PythonSignalContainer,
"PythonSignalContainer");
template <class T, class Time>
bool SignalWrapper<T, Time>::checkCallable(pyobject c, std::string& error) {
if (PyCallable_Check(c.ptr()) == 0) {
error = boost::python::extract<std::string>(c.attr("__str__")());
error += " is not callable";
return false;
}
return true;
}
template class SignalWrapper<bool, int>;
template class SignalWrapper<int, int>;
template class SignalWrapper<float, int>;
template class SignalWrapper<double, int>;
template class SignalWrapper<Vector, int>;
} // namespace python
} // namespace dynamicgraph
"""
Copyright (C) 2010 CNRS
# Copyright (C) 2020 CNRS
#
# Author: Joseph Mirabel
Author: Florent Lamiraux
"""
import wrap
import entity
from __future__ import print_function
# I kept what follows for backward compatibility but I think it should be
# removed
import re
import collections
def stringToTuple (vector) :
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('\[(\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)
return tuple(res)
def tupleToString (vector) :
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
def stringToMatrix (string) :
def stringToMatrix(string):
"""
Transform a string of format
'[n,m]((x_11,x_12,...,x_1m),...,(x_n1,x_n2,...,x_nm))' into a tuple
of tuple of numbers.
"""
# Find matrix size
a = re.search ('\[(\d+),(\d+)]', string)
nRows = int (a.group(1))
nCols = int (a.group(2))
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)
return tuple(m)
def matrixToString(matrix) :
def matrixToString(matrix):
"""
Transform a tuple of tuple of numbers into a string of format
'[n,m]((x_11,x_12,...,x_1m),...,(x_n1,x_n2,...,x_nm))'.
"""
nRows = len(matrix)
if nRows is 0 :
return '[0,0](())'
if nRows == 0:
return "[0,0](())"
nCols = len(matrix[0])
string = '[%d,%d](' % (nRows, nCols)
for r in range (nRows) :
string += '('
for c in range (nCols) :
string += str (float (matrix [r][c]))
if c != nCols-1 :
string += ','
string += ')'
if r != nRows -1 :
string += ','
string += ')'
string = "[%d,%d](" % (nRows, nCols)
for r in range(nRows):
string += "("
for c in range(nCols):
string += str(float(matrix[r][c]))
if c != nCols - 1:
string += ","
string += ")"
if r != nRows - 1:
string += ","
string += ")"
return string
def objectToString(obj) :
def objectToString(obj):
"""
Transform an object to a string. Object is either
- an entity (more precisely a sub-class named Feature)
......@@ -101,23 +117,24 @@ def objectToString(obj) :
- an integer,
- a boolean,
"""
if (hasattr (obj, "__iter__")) :
if hasattr(obj, "__iter__"):
# matrix or vector
if len(obj) is 0 :
if len(obj) == 0:
return ""
else :
if (hasattr(obj[0], "__iter__")) :
#matrix
else:
if hasattr(obj[0], "__iter__"):
# matrix
return matrixToString(obj)
else :
#vector
else:
# vector
return tupleToString(obj)
elif isinstance(obj, entity.Entity) :
elif hasattr(obj, "name"):
return obj.name
else :
else:
return str(obj)
def stringToObject(string) :
def stringToObject(string):
"""
Convert a string into one of the following types
- a matrix (tuple of tuple),
......@@ -127,150 +144,25 @@ def stringToObject(string) :
Successively attempts conversion in the above order and return
on success. If no conversion fits, the string is returned.
"""
if isinstance(string,float): return string
if isinstance(string,int): return string
if isinstance(string,tuple): return string
try :
if isinstance(string, float):
return string
if isinstance(string, int):
return string
if isinstance(string, tuple):
return string
try:
return stringToMatrix(string)
except :
except Exception:
pass
try :
try:
return stringToTuple(string)
except :
except Exception:
pass
try :
try:
return int(string)
except :
except Exception:
pass
try :
try:
return float(string)
except :
except Exception:
return string
class SignalBase (object) :
"""
This class binds dynamicgraph::SignalBase<int> C++ class
"""
obj = None
def __init__(self, name = "", obj = None) :
"""
Constructor: if not called by a child class, create and store a pointer
to a C++ SignalBase<int> object.
"""
if obj :
self.obj = obj
else :
raise RuntimeError(
"A pointer is required to create SignalBase object.")
if (obj==None):
self.className=self.getClassName()
self.name=self.getName()
@property
def time(self) :
"""
Get time of signal
"""
return wrap.signal_base_get_time(self.obj)
@time.setter
def time(self, val) :
"""
Set Time of signal
Input:
- an integer
"""
return wrap.signal_base_set_time(self.obj, val)
@property
def value(self) :
"""
Setter and getter for the value of a signal
Binds C++ SignalBase<int>::get() and set() methods. Values are passed
through string streams.
A string is interpreted as respectively:
* a matrix (tuple of tuple) if string fits '[n,m]((x_11,x_12,...,x_1m),...,(x_n1,x_n2,...,x_nm))' format where n and m are integers, x_ij are floating point numbers,
* a tuple if string fits '[n](x_1, x_2, ..., x_n)' format,
* an integer,
* a floating point number.
If string fits none of the above formats, no conversion is performed.
For instance, is s binds a signal of type vector,
>>> s.value = (2.5, .1, 1e2)
will call SignalBase<int>::set("[3](2.5,0.1,100.0)") and
>>> s.value
(2.5, 0.1, 100.0)
"""
string = wrap.signal_base_get_value(self.obj)
return stringToObject(string)
@value.setter
def value(self, val) :
"""
Set the signal as a constant signal with given value.
If the signal is plugged, it will be unplugged
"""
string = objectToString(val)
return wrap.signal_base_set_value(self.obj, string)
def getName(self):
"""
Get name of signal
"""
return wrap.signal_base_get_name(self.obj)
@property
def name (self) :
"""
Get name of signal
"""
return wrap.signal_base_get_name(self.obj)
def getClassName(self):
"""
Get class name of signal
"""
return wrap.signal_base_get_class_name(self.obj)
def recompute(self, time):
"""
Force signal to recompute the value at given time.
"""
return wrap.signal_base_recompute(self.obj, time)
def unplug(self):
"""
Unplug a PTR signal.
"""
return wrap.signal_base_unplug(self.obj)
def isPlugged(self):
"""
Return whether a signal is plugged.
"""
return wrap.signal_base_isPlugged(self.obj)
def getPlugged(self):
"""
Return the plugged signal.
"""
return SignalBase (obj = wrap.signal_base_getPlugged(self.obj))
def __str__(self):
"""
Print signal in a string
"""
return wrap.signal_base_display(self.obj)
def displayDependencies(self,iter):
"""
Print signal dependencies in a string
"""
return(wrap.signal_base_display_dependencies(self.obj,iter))
class SignalWrapper (SignalBase):
def __init__ (self, name, type, func):
super(SignalWrapper, self).__init__ (name,
wrap.create_signal_wrapper (name, type, func))
# -*- coding: utf-8 -*-
# Copyright 2011, Florent Lamiraux, Thomas Moulard, 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/>.
from __future__ import print_function
def addTrace(robot, trace, entityName, signalName, autoRecompute = True):
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/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);
}
#include <dynamic-graph/tracer-real-time.h>
#include "dynamic-graph/python/module.hh"
BOOST_PYTHON_MODULE(wrap) {
using dynamicgraph::Tracer;
using dynamicgraph::TracerRealTime;
bp::import("dynamic_graph.tracer");
dynamicgraph::python::exposeEntity<TracerRealTime, bp::bases<Tracer> >();
}
This diff is collapsed.
This diff is collapsed.
// 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/>.
#ifndef DYNAMIC_GRAPH_PYTHON_EXCEPTION
# define DYNAMIC_GRAPH_PYTHON_EXCEPTION
/// \brief Catch all exceptions which may be sent when C++ code is
/// called.
# define CATCH_ALL_EXCEPTIONS() \
catch (const std::exception& exc) \
{ \
PyErr_SetString(dgpyError, exc.what()); \
return NULL; \
} \
catch (const char* s) \
{ \
PyErr_SetString(dgpyError, s); \
return NULL; \
} catch (...) { \
PyErr_SetString(dgpyError, "Unknown exception"); \
return NULL; \
} struct e_n_d__w_i_t_h__s_e_m_i_c_o_l_o_n
#endif //! DYNAMIC_GRAPH_PYTHON_EXCEPTION
This diff is collapsed.
This diff is collapsed.