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 494 additions and 788 deletions
// 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;
......@@ -16,22 +17,10 @@ namespace factory {
/**
\brief Get name of entity
*/
PyObject* getEntityClassList(PyObject* /*self*/, PyObject* args) {
if (!PyArg_ParseTuple(args, "")) return NULL;
bp::tuple getEntityClassList() {
std::vector<std::string> classNames;
dynamicgraph::FactoryStorage::getInstance()->listEntities(classNames);
Py_ssize_t classNumber = classNames.size();
// Build a tuple object
PyObject* classTuple = PyTuple_New(classNumber);
for (Py_ssize_t iEntity = 0; iEntity < (Py_ssize_t)classNames.size(); ++iEntity) {
PyObject* className = Py_BuildValue("s", classNames[iEntity].c_str());
PyTuple_SetItem(classTuple, iEntity, className);
}
return Py_BuildValue("O", classTuple);
return to_py_tuple(classNames.begin(), classNames.end());
}
} // namespace factory
......
// 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/exception.hh"
#include "dynamic-graph/python/dynamic-graph-py.hh"
namespace dynamicgraph {
namespace python {
#if PY_MAJOR_VERSION == 2
extern PyObject* dgpyError;
# endif
namespace pool {
PyObject* writeGraph(
#if PY_MAJOR_VERSION >= 3
PyObject* m, PyObject* args
#else
PyObject*, PyObject* args
#endif
) {
char* filename;
if (!PyArg_ParseTuple(args, "s", &filename)) return NULL;
try {
PoolStorage::getInstance()->writeGraph(filename);
}
CATCH_ALL_EXCEPTIONS(m);
return Py_BuildValue("");
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
*/
PyObject* getEntityList(
#if PY_MAJOR_VERSION >= 3
PyObject* m, PyObject* args
#else
PyObject*, PyObject* args
#endif
) {
if (!PyArg_ParseTuple(args, "")) return NULL;
bp::list getEntityList() {
std::vector<std::string> entityNames;
try {
const PoolStorage::Entities& listOfEntities = dynamicgraph::PoolStorage::getInstance()->getEntityMap();
Py_ssize_t classNumber = listOfEntities.size();
// Build a tuple object
PyObject* classTuple = PyTuple_New(classNumber);
Py_ssize_t iEntity = 0;
for (PoolStorage::Entities::const_iterator entity_it = listOfEntities.begin(); entity_it != listOfEntities.end();
++entity_it) {
const std::string& aname = entity_it->second->getName();
bp::list res;
const PoolStorage::Entities& listOfEntities =
PoolStorage::getInstance()->getEntityMap();
PyObject* className = Py_BuildValue("s", aname.c_str());
PyTuple_SetItem(classTuple, iEntity, className);
iEntity++;
}
return Py_BuildValue("O", classTuple);
}
CATCH_ALL_EXCEPTIONS(m);
return NULL;
for (const auto& el : listOfEntities) res.append(el.second->getName());
return res;
}
} // namespace pool
......
......@@ -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 <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-caster.h>
#include <dynamic-graph/linear-algebra.h>
#include <dynamic-graph/pool.h>
#include <dynamic-graph/factory.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/convert-dg-to-py.hh"
#include "dynamic-graph/python/exception.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 {
#if PY_MAJOR_VERSION == 2
extern PyObject* dgpyError;
# endif
using namespace convert;
namespace signalBase {
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;
}
static void destroy(PyObject* self);
void exposeSignals() {
exposeSignalBase<time_type>("SignalBase");
/**
\brief Create an instance of SignalBase
*/
PyObject* create(PyObject* /*self*/, PyObject* args) {
char* name = NULL;
exposeSignalsOfType<bool, time_type>("Bool");
exposeSignalsOfType<int, time_type>("Int");
exposeSignalsOfType<double, time_type>("Double");
if (!PyArg_ParseTuple(args, "s", &name)) return NULL;
exposeSignalsOfType<Vector, time_type>("Vector");
exposeSignalsOfType<Vector3, time_type>("Vector3");
exposeSignalsOfType<Vector7, time_type>("Vector7");
SignalBase<int>* obj = NULL;
obj = new SignalBase<int>(std::string(name));
exposeSignalsOfType<Matrix, time_type>("Matrix");
exposeSignalsOfType<MatrixRotation, time_type>("MatrixRotation");
exposeSignalsOfType<MatrixHomogeneous, time_type>("MatrixHomogeneous");
exposeSignalsOfType<MatrixTwist, time_type>("MatrixTwist");
// Return the pointer
return PyCapsule_New((void*)obj, "dynamic_graph.Signal", destroy);
exposeSignalsOfType<Quaternion, time_type>("Quaternion");
exposeSignalsOfType<VectorUTheta, time_type>("VectorUTheta");
}
namespace signalBase {
template <class T>
SignalWrapper<T, int>* createSignalWrapperTpl(const char* name, PyObject* 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;
......@@ -58,27 +141,7 @@ SignalWrapper<T, int>* createSignalWrapperTpl(const char* name, PyObject* o, std
}
PythonSignalContainer* getPythonSignalContainer() {
const std::string instanceName = "python_signals";
const std::string className = "PythonSignalContainer";
Entity* obj;
#if PY_MAJOR_VERSION >= 3
PyObject* m = PyState_FindModule(&dynamicgraph::python::dynamicGraphModuleDef);
#endif
if (PoolStorage::getInstance()->existEntity(instanceName, obj)) {
if (obj->getClassName() != className) {
std::string msg("Found an object named " + std::string(instanceName) +
",\n"
"but this object is of type " +
std::string(obj->getClassName()) + " and not " + std::string(className));
PyErr_SetString(DGPYERROR(m), msg.c_str());
return NULL;
}
} else {
try {
obj = FactoryStorage::getInstance()->newEntity(std::string(className), std::string(instanceName));
}
CATCH_ALL_EXCEPTIONS(m);
}
Entity* obj = entity::create("PythonSignalContainer", "python_signals");
return dynamic_cast<PythonSignalContainer*>(obj);
}
......@@ -90,22 +153,11 @@ PythonSignalContainer* getPythonSignalContainer() {
/**
\brief Create an instance of SignalWrapper
*/
PyObject* createSignalWrapper(
#if PY_MAJOR_VERSION >= 3
PyObject* m, PyObject* args
#else
PyObject*, PyObject* args
#endif
) {
SignalBase<int>* createSignalWrapper(const char* name, const char* type,
bp::object object) {
PythonSignalContainer* psc = getPythonSignalContainer();
if (psc == NULL) return NULL;
char* name = NULL;
char* type = NULL;
PyObject* object = NULL;
if (!PyArg_ParseTuple(args, "ssO", &name, &type, &object)) return NULL;
SignalBase<int>* obj = NULL;
std::string error;
SIGNAL_WRAPPER_TYPE(if, BOOL, bool)
......@@ -121,380 +173,14 @@ PyObject* createSignalWrapper(
error = "Type not understood";
}
if (obj == NULL) {
PyErr_SetString(DGPYERROR(m), error.c_str());
return NULL;
}
if (obj == NULL) throw std::runtime_error(error);
// Register signal into the python signal container
psc->signalRegistration(*obj);
// Return the pointer
return PyCapsule_New((void*)obj, "dynamic_graph.SignalWrapper", destroy);
}
/**
\brief Destroy an instance of InvertedPendulum
*/
static void destroy(PyObject* self) {
SignalBase<int>* obj = (SignalBase<int>*)self;
delete obj;
}
PyObject* getTime(PyObject* /*self*/, PyObject* args) {
void* pointer = NULL;
PyObject* object = NULL;
if (!PyArg_ParseTuple(args, "O", &object)) return NULL;
if (!PyCapsule_CheckExact(object)) return NULL;
pointer = PyCapsule_GetPointer(object, "dynamic_graph.Signal");
SignalBase<int>* obj = (SignalBase<int>*)pointer;
int time = obj->getTime();
return Py_BuildValue("i", time);
}
PyObject* setTime(
#if PY_MAJOR_VERSION >= 3
PyObject* m, PyObject* args
#else
PyObject*, PyObject* args
#endif
) {
void* pointer = NULL;
PyObject* object = NULL;
int time;
if (!PyArg_ParseTuple(args, "Oi", &object, &time)) return NULL;
if (!PyCapsule_CheckExact(object)) {
PyErr_SetString(DGPYERROR(m), "object should be a C object");
return NULL;
}
pointer = PyCapsule_GetPointer(object, "dynamic_graph.Signal");
SignalBase<int>* obj = (SignalBase<int>*)pointer;
obj->setTime(time);
return Py_BuildValue("");
}
PyObject* display(
#if PY_MAJOR_VERSION >= 3
PyObject* m, PyObject* args
#else
PyObject*, PyObject* args
#endif
) {
void* pointer = NULL;
PyObject* object = NULL;
if (!PyArg_ParseTuple(args, "O", &object)) return NULL;
if (!PyCapsule_CheckExact(object)) return NULL;
pointer = PyCapsule_GetPointer(object, "dynamic_graph.Signal");
SignalBase<int>* obj = (SignalBase<int>*)pointer;
std::ostringstream oss;
try {
obj->display(oss);
}
CATCH_ALL_EXCEPTIONS(m);
return Py_BuildValue("s", oss.str().c_str());
}
PyObject* displayDependencies(
#if PY_MAJOR_VERSION >= 3
PyObject* m, PyObject* args
#else
PyObject*, PyObject* args
#endif
) {
void* pointer = NULL;
PyObject* object = NULL;
int time;
if (!PyArg_ParseTuple(args, "OI", &object, &time)) return NULL;
if (!PyCapsule_CheckExact(object)) return NULL;
pointer = PyCapsule_GetPointer(object, "dynamic_graph.Signal");
SignalBase<int>* obj = (SignalBase<int>*)pointer;
std::ostringstream oss;
try {
obj->displayDependencies(oss, time);
}
CATCH_ALL_EXCEPTIONS(m);
return Py_BuildValue("s", oss.str().c_str());
}
PyObject* getValue(
#if PY_MAJOR_VERSION >= 3
PyObject* m, PyObject* args
#else
PyObject*, PyObject* args
#endif
) {
void* pointer = NULL;
PyObject* object = NULL;
if (!PyArg_ParseTuple(args, "O", &object)) return NULL;
if (!PyCapsule_CheckExact(object)) return NULL;
pointer = PyCapsule_GetPointer(object, "dynamic_graph.Signal");
SignalBase<int>* signal = (SignalBase<int>*)pointer;
try {
{ // --- VECTOR SIGNALS -----------------
// Two cases: the signal embeds directly a vector, or embeds
// an object deriving from vector.In the first case,
// the signal is directly cast into sig<vector>.
// In the second case, the derived object can be access as a vector
// using the signal-ptr<vector> type.
Signal<dynamicgraph::Vector, int>* sigvec = dynamic_cast<Signal<dynamicgraph::Vector, int>*>(signal);
if (NULL != sigvec) {
return vectorToPython(sigvec->accessCopy());
}
// Extraction of object derinving from vector: plug signal into
// a vector signal and get the value from the signal-ptr instead
// of the original vector.
SignalPtr<dynamicgraph::Vector, int> sigptr(NULL, "vector-caster");
try {
sigptr.plug(signal);
return vectorToPython(sigptr.accessCopy());
} catch (dynamicgraph::ExceptionSignal& ex) {
if (ex.getCode() != dynamicgraph::ExceptionSignal::PLUG_IMPOSSIBLE) throw;
}
}
{ // --- MATRIX SIGNALS --------------------
// Two cases: the signal embeds directly a matrix, or embeds
// an object deriving from matrix.In the first case,
// the signal is directly cast into sig<matrix>.
// In the second case, the derived object can be access as a matrix
// using the signal-ptr<matrix> type.
Signal<dynamicgraph::Matrix, int>* sigmat = dynamic_cast<Signal<dynamicgraph::Matrix, int>*>(signal);
if (NULL != sigmat) {
return matrixToPython(sigmat->accessCopy());
}
SignalPtr<dynamicgraph::Matrix, int> sigptr(NULL, "matrix-caster");
try {
sigptr.plug(signal);
return matrixToPython(sigptr.accessCopy());
} catch (dynamicgraph::ExceptionSignal& ex) {
if (ex.getCode() != dynamicgraph::ExceptionSignal::PLUG_IMPOSSIBLE) throw;
}
}
{ // --- HOMOGENEOUS MATRIX SIGNALS --------------------
// Two cases: the signal embeds directly a matrix, or embeds
// an object deriving from matrix.In the first case,
// the signal is directly cast into sig<matrix>.
// In the second case, the derived object can be access as a matrix
// using the signal-ptr<matrix> type.
// TODO: See if matrix homogeneous can be properly put in linear-algebra.h
typedef Eigen::Transform<double, 3, Eigen::Affine> MatrixHomogeneous;
Signal<MatrixHomogeneous, int>* sigmat = dynamic_cast<Signal<MatrixHomogeneous, int>*>(signal);
if (NULL != sigmat) {
return matrixToPython(sigmat->accessCopy().matrix());
}
SignalPtr<Eigen::Transform<double, 3, Eigen::Affine>, int> sigptr(NULL, "matrix-caster");
try {
sigptr.plug(signal);
return matrixToPython(sigptr.accessCopy().matrix());
} catch (dynamicgraph::ExceptionSignal& ex) {
if (ex.getCode() != dynamicgraph::ExceptionSignal::PLUG_IMPOSSIBLE) throw;
}
}
Signal<double, int>* sigdouble = dynamic_cast<Signal<double, int>*>(signal);
if (NULL != sigdouble) {
return Py_BuildValue("d", sigdouble->accessCopy());
}
}
CATCH_ALL_EXCEPTIONS(m);
/* Non specific signal: use a generic way. */
std::ostringstream value;
try {
signal->get(value);
}
CATCH_ALL_EXCEPTIONS(m);
std::string valueString = value.str();
return Py_BuildValue("s", valueString.c_str());
}
PyObject* getName(
#if PY_MAJOR_VERSION >= 3
PyObject* m, PyObject* args
#else
PyObject*, PyObject* args
#endif
) {
void* pointer = NULL;
PyObject* object = NULL;
if (!PyArg_ParseTuple(args, "O", &object)) return NULL;
if (!PyCapsule_CheckExact(object)) return NULL;
pointer = PyCapsule_GetPointer(object, "dynamic_graph.Signal");
SignalBase<int>* signal = (SignalBase<int>*)pointer;
std::string name;
try {
name = signal->getName();
}
CATCH_ALL_EXCEPTIONS(m);
return Py_BuildValue("s", name.c_str());
}
PyObject* getClassName(
#if PY_MAJOR_VERSION >= 3
PyObject* m, PyObject* args
#else
PyObject*, PyObject* args
#endif
) {
void* pointer = NULL;
PyObject* object = NULL;
if (!PyArg_ParseTuple(args, "O", &object)) return NULL;
if (!PyCapsule_CheckExact(object)) return NULL;
pointer = PyCapsule_GetPointer(object, "dynamic_graph.Signal");
SignalBase<int>* signal = (SignalBase<int>*)pointer;
std::string name;
try {
signal->getClassName(name);
}
CATCH_ALL_EXCEPTIONS(m);
return Py_BuildValue("s", name.c_str());
}
PyObject* setValue(
#if PY_MAJOR_VERSION >= 3
PyObject* m, PyObject* args
#else
PyObject*, PyObject* args
#endif
) {
void* pointer = NULL;
PyObject* object = NULL;
char* valueString = NULL;
if (!PyArg_ParseTuple(args, "Os", &object, &valueString)) return NULL;
if (!PyCapsule_CheckExact(object)) return NULL;
pointer = PyCapsule_GetPointer(object, "dynamic_graph.Signal");
SignalBase<int>* signal = (SignalBase<int>*)pointer;
std::ostringstream os;
os << valueString;
std::istringstream value(os.str());
try {
signal->set(value);
}
CATCH_ALL_EXCEPTIONS(m);
return Py_BuildValue("");
}
PyObject* recompute(
#if PY_MAJOR_VERSION >= 3
PyObject* m, PyObject* args
#else
PyObject*, PyObject* args
#endif
) {
void* pointer = NULL;
PyObject* object = NULL;
unsigned int time;
if (!PyArg_ParseTuple(args, "OI", &object, &time)) return NULL;
if (!PyCapsule_CheckExact(object)) return NULL;
pointer = PyCapsule_GetPointer(object, "dynamic_graph.Signal");
SignalBase<int>* signal = (SignalBase<int>*)pointer;
try {
signal->recompute(time);
}
CATCH_ALL_EXCEPTIONS(m);
return Py_BuildValue("");
}
PyObject* unplug(
#if PY_MAJOR_VERSION >= 3
PyObject* m, PyObject* args
#else
PyObject*, PyObject* args
#endif
) {
void* pointer = NULL;
PyObject* object = NULL;
if (!PyArg_ParseTuple(args, "O", &object)) return NULL;
if (!PyCapsule_CheckExact(object)) return NULL;
pointer = PyCapsule_GetPointer(object, "dynamic_graph.Signal");
SignalBase<int>* signal = (SignalBase<int>*)pointer;
try {
signal->unplug();
}
CATCH_ALL_EXCEPTIONS(m);
return Py_BuildValue("");
}
PyObject* isPlugged(
#if PY_MAJOR_VERSION >= 3
PyObject* m, PyObject* args
#else
PyObject*, PyObject* args
#endif
) {
void* pointer = NULL;
PyObject* object = NULL;
if (!PyArg_ParseTuple(args, "O", &object)) return NULL;
if (!PyCapsule_CheckExact(object)) return NULL;
pointer = PyCapsule_GetPointer(object, "dynamic_graph.Signal");
SignalBase<int>* signal = (SignalBase<int>*)pointer;
bool plugged = false;
try {
plugged = signal->isPlugged();
}
CATCH_ALL_EXCEPTIONS(m);
if (plugged)
return PyBool_FromLong(1);
else
return PyBool_FromLong(0);
return obj;
}
PyObject* getPlugged(
#if PY_MAJOR_VERSION >= 3
PyObject* m, PyObject* args
#else
PyObject*, PyObject* args
#endif
) {
void* pointer = NULL;
PyObject* object = NULL;
if (!PyArg_ParseTuple(args, "O", &object)) return NULL;
if (!PyCapsule_CheckExact(object)) return NULL;
pointer = PyCapsule_GetPointer(object, "dynamic_graph.Signal");
SignalBase<int>* signal = (SignalBase<int>*)pointer;
SignalBase<int>* otherSignal = 0;
try {
bool plugged = signal->isPlugged();
otherSignal = signal->getPluged();
if (!plugged || otherSignal == 0) {
std::string msg = std::string("Signal ") + signal->getName() + std::string(" is not plugged.");
throw std::runtime_error(msg);
}
}
CATCH_ALL_EXCEPTIONS(m);
// Return the pointer to the signal without destructor since the signal
// is not owned by the calling object.
return PyCapsule_New((void*)otherSignal, "dynamic_graph.Signal", NULL);
}
} // namespace signalBase
} // namespace python
} // namespace dynamicgraph
// Copyright 2010, Florent Lamiraux, Thomas Moulard, LAAS-CNRS.
#include <iostream>
#include <sstream>
#include <dynamic-graph/signal-caster.h>
#include "dynamic-graph/python/dynamic-graph-py.hh"
namespace dynamicgraph {
namespace python {
namespace signalCaster {
PyObject* getSignalTypeList(PyObject* /*self*/, PyObject* args) {
if (!PyArg_ParseTuple(args, "")) return NULL;
std::vector<std::string> typeList = dynamicgraph::SignalCaster::getInstance()->listTypenames();
Py_ssize_t typeNumber = typeList.size();
// Build a tuple object
PyObject* typeTuple = PyTuple_New(typeNumber);
for (Py_ssize_t iType = 0; iType < typeNumber; ++iType) {
PyObject* className = Py_BuildValue("s", typeList[iType].c_str());
PyTuple_SetItem(typeTuple, iType, className);
}
return Py_BuildValue("O", typeTuple);
}
} // namespace signalCaster
} // namespace python
} // namespace dynamicgraph
// 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 {
namespace signalWrapper {
void convert(PyObject* o, bool& v) { v = (o == Py_True); }
void convert(PyObject* o, int& v) { v = (int)PyLong_AsLong(o); }
void convert(PyObject* o, float& v) { v = (float)PyFloat_AS_DOUBLE(o); }
void convert(PyObject* o, double& v) { v = PyFloat_AS_DOUBLE(o); }
void convert(PyObject* o, Vector& v) {
v.resize(PyTuple_Size(o));
for (int i = 0; i < v.size(); ++i) convert(PyTuple_GetItem(o, i), v[i]);
}
} // namespace signalWrapper
PythonSignalContainer::PythonSignalContainer(const std::string& name) : Entity(name) {
std::string docstring;
docstring =
" \n"
" Remove a signal\n"
" \n"
" Input:\n"
" - name of the signal\n"
" \n";
addCommand("rmSignal", command::makeCommandVoid1(*this, &PythonSignalContainer::rmSignal, docstring));
}
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) {
if (PyCallable_Check(c) == 0) {
PyObject* str = PyObject_Str(c);
error = obj_to_str(str);
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";
Py_DECREF(str);
return false;
}
return true;
......
"""
Copyright (C) 2010 CNRS
Author: Florent Lamiraux
"""
# Copyright (C) 2020 CNRS
#
# Author: Joseph Mirabel
from __future__ import print_function
# I kept what follows for backward compatibility but I think it should be
# removed
import re
from .wrap import (create_signal_wrapper, signal_base_display, signal_base_display_dependencies,
signal_base_get_class_name, signal_base_get_name, signal_base_get_time, signal_base_get_value,
signal_base_getPlugged, signal_base_isPlugged, signal_base_recompute, signal_base_set_time,
signal_base_set_value, signal_base_unplug)
from .wrap import SignalBase # noqa
from .wrap import create_signal_wrapper as SignalWrapper # noqa
def stringToTuple(vector):
......@@ -19,17 +17,22 @@ 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)
......@@ -39,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
......@@ -53,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)
......@@ -78,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
......@@ -104,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)
......@@ -153,136 +166,3 @@ def stringToObject(string):
return float(string)
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 is None:
self.className = self.getClassName()
self.name = self.getName()
@property
def time(self):
"""
Get time of signal
"""
return signal_base_get_time(self.obj)
@time.setter
def time(self, val):
"""
Set Time of signal
Input:
- an integer
"""
return 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 = 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 signal_base_set_value(self.obj, string)
def getName(self):
"""
Get name of signal
"""
return signal_base_get_name(self.obj)
@property
def name(self):
"""
Get name of signal
"""
return signal_base_get_name(self.obj)
def getClassName(self):
"""
Get class name of signal
"""
return signal_base_get_class_name(self.obj)
def recompute(self, time):
"""
Force signal to recompute the value at given time.
"""
return signal_base_recompute(self.obj, time)
def unplug(self):
"""
Unplug a PTR signal.
"""
return signal_base_unplug(self.obj)
def isPlugged(self):
"""
Return whether a signal is plugged.
"""
return signal_base_isPlugged(self.obj)
def getPlugged(self):
"""
Return the plugged signal.
"""
return SignalBase(obj=signal_base_getPlugged(self.obj))
def __str__(self):
"""
Print signal in a string
"""
return signal_base_display(self.obj)
def displayDependencies(self, iter):
"""
Print signal dependencies in a string
"""
return (signal_base_display_dependencies(self.obj, iter))
class SignalWrapper(SignalBase):
def __init__(self, name, type, func):
super(SignalWrapper, self).__init__(name, create_signal_wrapper(name, type, func))
......@@ -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/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> >();
}
// -*- mode: c++ -*-
// Copyright 2011, Florent Lamiraux, CNRS.
#ifdef WIN32
#include <Windows.h>
#else
#include <dlfcn.h>
#endif
#include <iostream>
#include "dynamic-graph/debug.h"
#include "dynamic-graph/python/interpreter.hh"
#include "dynamic-graph/python/link-to-python.hh"
std::ofstream dg_debugfile("/tmp/dynamic-graph-traces.txt", std::ios::trunc& std::ios::out);
std::ofstream dg_debugfile("/tmp/dynamic-graph-traces.txt",
std::ios::trunc& std::ios::out);
// Python initialization commands
namespace dynamicgraph {
namespace python {
static const std::string pythonPrefix[8] = {"from __future__ import print_function\n",
"import traceback\n",
"class StdoutCatcher:\n"
" def __init__(self):\n"
" self.data = ''\n"
" def write(self, stuff):\n"
" self.data = self.data + stuff\n"
" def fetch(self):\n"
" s = self.data[:]\n"
" self.data = ''\n"
" return s\n",
"stdout_catcher = StdoutCatcher()\n",
"stderr_catcher = StdoutCatcher()\n",
"import sys\n",
"sys.stdout = stdout_catcher",
"sys.stderr = stderr_catcher"};
static const std::string pythonPrefix[8] = {
"from __future__ import print_function\n",
"import traceback\n",
"class StdoutCatcher:\n"
" def __init__(self):\n"
" self.data = ''\n"
" def write(self, stuff):\n"
" self.data = self.data + stuff\n"
" def fetch(self):\n"
" s = self.data[:]\n"
" self.data = ''\n"
" return s\n",
"stdout_catcher = StdoutCatcher()\n",
"stderr_catcher = StdoutCatcher()\n",
"import sys\n",
"sys.stdout = stdout_catcher",
"sys.stderr = stderr_catcher"};
bool HandleErr(std::string& err, PyObject* globals_, int PythonInputType) {
dgDEBUGIN(15);
......@@ -36,7 +44,8 @@ bool HandleErr(std::string& err, PyObject* globals_, int PythonInputType) {
if (PyErr_Occurred() != NULL) {
bool is_syntax_error = PyErr_ExceptionMatches(PyExc_SyntaxError);
PyErr_Print();
PyObject* stderr_obj = PyRun_String("stderr_catcher.fetch()", Py_eval_input, globals_, globals_);
PyObject* stderr_obj = PyRun_String("stderr_catcher.fetch()", Py_eval_input,
globals_, globals_);
err = obj_to_str(stderr_obj);
Py_DECREF(stderr_obj);
......@@ -61,10 +70,12 @@ Interpreter::Interpreter() {
// load python dynamic library
// this is silly, but required to be able to import dl module.
#ifndef WIN32
dlopen(libpython.c_str(), RTLD_LAZY | RTLD_GLOBAL);
dlopen(PYTHON_LIBRARY, RTLD_LAZY | RTLD_GLOBAL);
#endif
Py_Initialize();
#if PY_MAJOR_VERSION < 3 || PY_MINOR_VERSION < 7
PyEval_InitThreads();
#endif
mainmod_ = PyImport_AddModule("__main__");
Py_INCREF(mainmod_);
globals_ = PyModule_GetDict(mainmod_);
......@@ -90,7 +101,8 @@ Interpreter::~Interpreter() {
// Ideally, we should call Py_Finalize but this is not really supported by
// Python.
// Instead, we merelly remove variables.
// Code was taken here: https://github.com/numpy/numpy/issues/8097#issuecomment-356683953
// Code was taken here:
// https://github.com/numpy/numpy/issues/8097#issuecomment-356683953
{
PyObject* poAttrList = PyObject_Dir(mainmod_);
PyObject* poAttrIter = PyObject_GetIter(poAttrList);
......@@ -100,11 +112,13 @@ Interpreter::~Interpreter() {
std::string oAttrName(obj_to_str(poAttrName));
// Make sure we don't delete any private objects.
if (oAttrName.compare(0, 2, "__") != 0 || oAttrName.compare(oAttrName.size() - 2, 2, "__") != 0) {
if (oAttrName.compare(0, 2, "__") != 0 ||
oAttrName.compare(oAttrName.size() - 2, 2, "__") != 0) {
PyObject* poAttr = PyObject_GetAttr(mainmod_, poAttrName);
// Make sure we don't delete any module objects.
if (poAttr && poAttr->ob_type != mainmod_->ob_type) PyObject_SetAttr(mainmod_, poAttrName, NULL);
if (poAttr && poAttr->ob_type != mainmod_->ob_type)
PyObject_SetAttr(mainmod_, poAttrName, NULL);
Py_DECREF(poAttr);
}
......@@ -127,7 +141,8 @@ std::string Interpreter::python(const std::string& command) {
return lres;
}
void Interpreter::python(const std::string& command, std::string& res, std::string& out, std::string& err) {
void Interpreter::python(const std::string& command, std::string& res,
std::string& out, std::string& err) {
res = "";
out = "";
err = "";
......@@ -142,18 +157,21 @@ void Interpreter::python(const std::string& command, std::string& res, std::stri
PyEval_RestoreThread(_pyState);
std::cout << command.c_str() << std::endl;
PyObject* result = PyRun_String(command.c_str(), Py_eval_input, globals_, globals_);
PyObject* result =
PyRun_String(command.c_str(), Py_eval_input, globals_, globals_);
// Check if the result is null.
if (result == NULL) {
// Test if this is a syntax error (due to the evaluation of an expression)
// else just output the problem.
if (!HandleErr(err, globals_, Py_eval_input)) {
// If this is a statement, re-parse the command.
result = PyRun_String(command.c_str(), Py_single_input, globals_, globals_);
result =
PyRun_String(command.c_str(), Py_single_input, globals_, globals_);
// If there is still an error build the appropriate err string.
if (result == NULL) HandleErr(err, globals_, Py_single_input);
// If there is no error, make sure that the previous error message is erased.
// If there is no error, make sure that the previous error message is
// erased.
else
err = "";
} else
......@@ -161,7 +179,8 @@ void Interpreter::python(const std::string& command, std::string& res, std::stri
}
PyObject* stdout_obj = 0;
stdout_obj = PyRun_String("stdout_catcher.fetch()", Py_eval_input, globals_, globals_);
stdout_obj =
PyRun_String("stdout_catcher.fetch()", Py_eval_input, globals_, globals_);
out = obj_to_str(stdout_obj);
Py_DECREF(stdout_obj);
// Local display for the robot (in debug mode or for the logs)
......@@ -202,7 +221,8 @@ void Interpreter::runPythonFile(std::string filename, std::string& err) {
PyEval_RestoreThread(_pyState);
err = "";
PyObject* run = PyRun_File(pFile, filename.c_str(), Py_file_input, globals_, globals_);
PyObject* run =
PyRun_File(pFile, filename.c_str(), Py_file_input, globals_, globals_);
if (run == NULL) {
HandleErr(err, globals_, Py_file_input);
std::cerr << err << std::endl;
......
# Copyright 2010-2020, Florent Lamiraux, Thomas Moulard, Olivier Stasse, Guilhem
# Saurel, JRL, CNRS/AIST, LAAS-CNRS
# Test the interpreter
add_unit_test(interpreter-test interpreter-test.cc)
target_link_libraries(interpreter-test PRIVATE ${PROJECT_NAME})
# Test runfile
add_unit_test(interpreter-test-runfile interpreter-test-runfile.cc)
target_link_libraries(interpreter-test-runfile PRIVATE ${PROJECT_NAME})
target_include_directories(interpreter-test-runfile
PRIVATE Boost::unit_test_framework)
target_compile_definitions(interpreter-test-runfile
PRIVATE PATH="${CMAKE_CURRENT_LIST_DIR}/")
# Test the module generation Create an entity
set(LIBRARY_NAME "custom_entity")
add_library(${LIBRARY_NAME} SHARED "${LIBRARY_NAME}.cpp")
if(SUFFIX_SO_VERSION)
set_target_properties(${LIBRARY_NAME} PROPERTIES SOVERSION ${PROJECT_VERSION})
endif(SUFFIX_SO_VERSION)
target_link_libraries(${LIBRARY_NAME} PRIVATE dynamic-graph::dynamic-graph)
# Create its bindings This mimics DYNAMIC_GRAPH_PYTHON_MODULE(${LIBRARY_NAME}
# ${LIBRARY_NAME} "${LIBRARY_NAME}-wrap")
configure_file(
${PROJECT_SOURCE_DIR}/cmake/dynamic_graph/submodule/__init__.py.cmake
${CMAKE_CURRENT_BINARY_DIR}/${LIBRARY_NAME}/__init__.py)
set(PYTHON_MODULE "${LIBRARY_NAME}-wrap")
set(DYNAMICGRAPH_MODULE_HEADER
"${CMAKE_SOURCE_DIR}/tests/custom_entity_module.h")
configure_file(${PROJECT_SOURCE_DIR}/cmake/dynamic_graph/python-module-py.cc.in
${CMAKE_CURRENT_BINARY_DIR}/python-module-py.cc @ONLY)
add_library(${PYTHON_MODULE} MODULE
${CMAKE_CURRENT_BINARY_DIR}/python-module-py.cc)
set_target_properties(${PYTHON_MODULE}
PROPERTIES PREFIX "" OUTPUT_NAME ${LIBRARY_NAME}/wrap)
if(UNIX AND NOT APPLE)
target_link_libraries(${PYTHON_MODULE} PRIVATE "-Wl,--no-as-needed")
endif(UNIX AND NOT APPLE)
target_link_libraries(${PYTHON_MODULE} PRIVATE ${LIBRARY_NAME} ${PROJECT_NAME})
# Test it
add_python_unit_test("test-custom-entity" "tests/test_custom_entity.py" src
tests)
# also test other bindings, using this custom entity
add_python_unit_test("test-bindings" "tests/test_bindings.py" src tests)
/* Copyright 2010-2019 LAAS, CNRS
* Thomas Moulard.
*
*/
#define ENABLE_RT_LOG
#include "custom_entity.h"
#include <dynamic-graph/command-bind.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/real-time-logger.h>
#include <dynamic-graph/signal-ptr.h>
#include <dynamic-graph/signal-time-dependent.h>
#include <boost/bind.hpp>
namespace dynamicgraph {
CustomEntity::CustomEntity(const std::string n)
: Entity(n),
m_sigdSIN(NULL, "CustomEntity(" + name + ")::input(double)::in_double"),
m_sigdTimeDepSOUT(boost::bind(&CustomEntity::update, this, _1, _2),
m_sigdSIN,
"CustomEntity(" + name + ")::input(double)::out_double")
{
addSignal();
using namespace dynamicgraph::command;
this->addCommand("act",
makeCommandVoid0(*this, &CustomEntity::act,
docCommandVoid0("act on input signal")));
}
void CustomEntity::addSignal() {
signalRegistration(m_sigdSIN << m_sigdTimeDepSOUT);
}
void CustomEntity::rmValidSignal() {
signalDeregistration("in_double");
signalDeregistration("out_double");
}
double &CustomEntity::update(double &res, const int &inTime) {
const double &aDouble = m_sigdSIN(inTime);
res = aDouble;
logger().stream(MSG_TYPE_ERROR) << "start update " << res << '\n';
DYNAMIC_GRAPH_ENTITY_DEBUG(*this)
<< "This is a message of level MSG_TYPE_DEBUG\n";
DYNAMIC_GRAPH_ENTITY_INFO(*this)
<< "This is a message of level MSG_TYPE_INFO\n";
DYNAMIC_GRAPH_ENTITY_WARNING(*this)
<< "This is a message of level MSG_TYPE_WARNING\n";
DYNAMIC_GRAPH_ENTITY_ERROR(*this)
<< "This is a message of level MSG_TYPE_ERROR\n";
DYNAMIC_GRAPH_ENTITY_DEBUG_STREAM(*this)
<< "This is a message of level MSG_TYPE_DEBUG_STREAM\n";
DYNAMIC_GRAPH_ENTITY_INFO_STREAM(*this)
<< "This is a message of level MSG_TYPE_INFO_STREAM\n";
DYNAMIC_GRAPH_ENTITY_WARNING_STREAM(*this)
<< "This is a message of level MSG_TYPE_WARNING_STREAM\n";
DYNAMIC_GRAPH_ENTITY_ERROR_STREAM(*this)
<< "This is a message of level MSG_TYPE_ERROR_STREAM\n";
logger().stream(MSG_TYPE_ERROR) << "end update\n";
return res;
}
void CustomEntity::act() { m_sigdSIN.accessCopy(); }
DYNAMICGRAPH_FACTORY_ENTITY_PLUGIN(CustomEntity, "CustomEntity");
} // namespace dynamicgraph
/* Copyright 2020 LAAS, CNRS
* Joseph Mirabel
*
*/
#define ENABLE_RT_LOG
#include <dynamic-graph/entity.h>
#include <dynamic-graph/signal-ptr.h>
#include <dynamic-graph/signal-time-dependent.h>
#include <sstream>
namespace dynamicgraph {
class CustomEntity : public Entity {
public:
dynamicgraph::SignalPtr<double, int> m_sigdSIN;
dynamicgraph::SignalTimeDependent<double, int> m_sigdTimeDepSOUT;
DYNAMIC_GRAPH_ENTITY_DECL();
CustomEntity(const std::string n);
void addSignal();
void rmValidSignal();
double &update(double &res, const int &inTime);
void act();
};
} // namespace dynamicgraph
#include "custom_entity.h"
typedef boost::mpl::vector<dynamicgraph::CustomEntity> entities_t;
......@@ -2,7 +2,10 @@
* Copyright
*/
#include <iostream>
#include "dynamic-graph-python-test.hh"
GraphTest::GraphTest() { std::cout << "Constructor of unitTesting object of class Graph." << std::endl; }
#include <iostream>
GraphTest::GraphTest() {
std::cout << "Constructor of unitTesting object of class Graph." << std::endl;
}
/*
* Copyright
*/
#include "dynamic-graph-python-test.hh"
#include <iostream>
GraphTest::GraphTest() {
std::cout << "Constructor of unitTesting object of class Graph." << std::endl;
}
// The purpose of this unit test is to check the interpreter::runPythonFile method
// The purpose of this unit test is to check the interpreter::runPythonFile
// method
#include <cstring>
#include <iostream>
#include "dynamic-graph/python/interpreter.hh"
bool testFile(const std::string& filename, const std::string& expectedOutput, int numTest) {
bool testFile(const std::string& filename, const std::string& expectedOutput,
int numTest) {
std::string err = "";
dynamicgraph::python::Interpreter interp;
for (int i = 0; i < numTest; ++i) {
interp.runPythonFile(filename, err);
if (err != expectedOutput) {
std::cerr << "At iteration " << i << ", the output was not the one expected:" << std::endl;
std::cerr << "At iteration " << i
<< ", the output was not the one expected:" << std::endl;
std::cerr << " expected: " << expectedOutput << std::endl;
std::cerr << " err: " << err << std::endl;
return false;
......@@ -19,7 +22,8 @@ bool testFile(const std::string& filename, const std::string& expectedOutput, in
return true;
}
bool testInterpreterDestructor(const std::string& filename, const std::string& expectedOutput) {
bool testInterpreterDestructor(const std::string& filename,
const std::string& expectedOutput) {
std::string err = "";
{
dynamicgraph::python::Interpreter interp;
......@@ -49,20 +53,27 @@ int main(int argc, char** argv) {
// This test succeeds only because it is launched before "test_python-ok.py"
// because re as been imported in a previous test and it is not
// safe to delete imported module...
res = testFile("test_python-name_error.py",
std::string("Traceback (most recent call last):\n"
" File \"test_python-name_error.py\", line 7, in <module>\n"
" pathList = re.split(':', pkgConfigPath) # noqa\n"
"NameError: name 're' is not defined\n"),
res = testFile(PATH "test_python-name_error.py",
std::string(
"Traceback (most recent call last):\n"
" File \"" PATH
"test_python-name_error.py\", line 7, in <module>\n"
" pathList = re.split(\":\", pkgConfigPath) # noqa\n"
"NameError: name 're' is not defined\n"),
numTest) &&
res;
res = testFile("test_python-ok.py", "", numTest) && res;
res = testFile("unexistant_file.py", "unexistant_file.py cannot be open", numTest) && res;
res = testFile("test_python-syntax_error.py",
std::string(" File \"test_python-syntax_error.py\", line 2\n"
res = testFile(PATH "test_python-ok.py", "", numTest) && res;
res = testFile(PATH "unexistant_file.py",
PATH "unexistant_file.py cannot be open", numTest) &&
res;
res = testFile(PATH "test_python-syntax_error.py",
std::string(" File \"" PATH
"test_python-syntax_error.py\", line 2\n"
" hello world\n"
#if PY_MINOR_VERSION >= 8
#if PY_MINOR_VERSION >= 10
" ^^^^^\n"
#elif PY_MINOR_VERSION >= 8
" ^\n"
#else
" ^\n"
......@@ -70,6 +81,8 @@ int main(int argc, char** argv) {
"SyntaxError: invalid syntax\n"),
numTest) &&
res;
res = testInterpreterDestructor("test_python-restart_interpreter.py", "") && res;
res = testInterpreterDestructor(PATH "test_python-restart_interpreter.py",
"") &&
res;
return (res ? 0 : 1);
}