Commit b52037ca authored by Olivier Stasse's avatar Olivier Stasse
Browse files

[entity/logger] Python bindings for set/getTimeSample set/getStreamPrintPeriod

parent 332fba6d
Pipeline #4068 failed with stage
in 4 minutes and 14 seconds
...@@ -54,16 +54,17 @@ INSTALL(TARGETS ${LIBRARY_NAME} ...@@ -54,16 +54,17 @@ INSTALL(TARGETS ${LIBRARY_NAME}
SET(PYTHON_MODULE wrap) SET(PYTHON_MODULE wrap)
ADD_LIBRARY(${PYTHON_MODULE} ADD_LIBRARY(${PYTHON_MODULE}
MODULE MODULE
exception-python.cc convert-dg-to-py.cc
convert-dg-to-py.cc debug-py.cc
dynamic-graph-py.cc dynamic-graph-py.cc
signal-base-py.cc entity-py.cc
entity-py.cc exception-python.cc
factory-py.cc factory-py.cc
pool-py.cc pool-py.cc
signal-caster-py.cc signal-base-py.cc
signal-wrapper.cc signal-caster-py.cc
signal-wrapper.cc
) )
# Remove prefix lib # Remove prefix lib
...@@ -117,5 +118,3 @@ ELSE(WIN32) ...@@ -117,5 +118,3 @@ ELSE(WIN32)
SET(TRACERREALTIME_PLUGIN ${DYNAMIC_GRAPH_PLUGINDIR}/tracer-real-time${CMAKE_SHARED_LIBRARY_SUFFIX}) SET(TRACERREALTIME_PLUGIN ${DYNAMIC_GRAPH_PLUGINDIR}/tracer-real-time${CMAKE_SHARED_LIBRARY_SUFFIX})
ENDIF(WIN32) ENDIF(WIN32)
DYNAMIC_GRAPH_PYTHON_MODULE("tracer_real_time" ${TRACERREALTIME_PLUGIN} tracer_real_time-wrap) DYNAMIC_GRAPH_PYTHON_MODULE("tracer_real_time" ${TRACERREALTIME_PLUGIN} tracer_real_time-wrap)
// Copyright 2019, Olivier Stasse, LAAS-CNRS.
//
// See LICENSE
#include <iostream>
#define ENABLE_RT_LOG
#include <dynamic-graph/real-time-logger.h>
#include <map>
#include <Python.h>
#include <dynamic-graph/pool.h>
#include <dynamic-graph/entity.h>
#include <vector>
#include "exception.hh"
#include <boost/shared_ptr.hpp>
typedef boost::shared_ptr<std::ofstream> ofstreamShrPtr;
namespace dynamicgraph {
namespace python {
extern PyObject* dgpyError;
namespace debug {
std::map<std::string, ofstreamShrPtr > mapOfFiles_;
PyObject* addLoggerFileOutputStream (PyObject* /*self*/, PyObject* args)
{
char* filename;
if (!PyArg_ParseTuple(args, "s", &filename))
return NULL;
std::string sfilename(filename);
try {
std::ofstream *aofs = new std::ofstream;
ofstreamShrPtr ofs_shrptr = boost::shared_ptr<std::ofstream>(aofs);
aofs->open(filename,
std::ofstream::out);
dynamicgraph::RealTimeLogger::instance();
dgADD_OSTREAM_TO_RTLOG(*aofs);
dgRTLOG() << "Added " << filename << " as an output stream \n";
mapOfFiles_[sfilename]= ofs_shrptr;
} CATCH_ALL_EXCEPTIONS();
return Py_BuildValue ("");
}
PyObject* closeLoggerFileOutputStream (PyObject* /*self*/, PyObject* /*args */)
{
try {
for (std::map<std::string,ofstreamShrPtr>::iterator
it=mapOfFiles_.begin();
it!=mapOfFiles_.end(); ++it)
{
it->second->close();
}
} CATCH_ALL_EXCEPTIONS();
return Py_BuildValue ("");
}
PyObject* addLoggerCoutOutputStream (PyObject* /*self*/, PyObject* /*args*/)
{
try {
dgADD_OSTREAM_TO_RTLOG(std::cout);
} CATCH_ALL_EXCEPTIONS();
return Py_BuildValue ("");
}
PyObject* realTimeLoggerDestroy (PyObject* /*self*/, PyObject* /*args*/)
{
try {
RealTimeLogger::destroy();
} CATCH_ALL_EXCEPTIONS();
return Py_BuildValue ("");
}
PyObject* realTimeLoggerSpinOnce (PyObject* /*self*/, PyObject* /*args*/)
{
try {
RealTimeLogger::instance().spinOnce();
} CATCH_ALL_EXCEPTIONS();
return Py_BuildValue ("");
}
PyObject* realTimeLoggerInstance (PyObject* /*self*/, PyObject* /*args*/)
{
try {
RealTimeLogger::instance();
} CATCH_ALL_EXCEPTIONS();
return Py_BuildValue ("");
}
} // python
} // namespace debug
} // dynamicgraph
...@@ -60,6 +60,10 @@ namespace dynamicgraph { ...@@ -60,6 +60,10 @@ namespace dynamicgraph {
extern PyObject* getDocString(PyObject* self, PyObject* args); extern PyObject* getDocString(PyObject* self, PyObject* args);
extern PyObject* setLoggerVerbosityLevel(PyObject*self, PyObject *args); extern PyObject* setLoggerVerbosityLevel(PyObject*self, PyObject *args);
extern PyObject* getLoggerVerbosityLevel(PyObject *self, PyObject *args); extern PyObject* getLoggerVerbosityLevel(PyObject *self, PyObject *args);
extern PyObject* setTimeSample(PyObject*self, PyObject *args);
extern PyObject* getTimeSample(PyObject *self, PyObject *args);
extern PyObject* setStreamPrintPeriod(PyObject*self, PyObject *args);
extern PyObject* getStreamPrintPeriod(PyObject *self, PyObject *args);
} }
namespace factory { namespace factory {
...@@ -72,6 +76,15 @@ namespace dynamicgraph { ...@@ -72,6 +76,15 @@ namespace dynamicgraph {
extern PyObject* writeGraph (PyObject* self, PyObject* args); extern PyObject* writeGraph (PyObject* self, PyObject* args);
extern PyObject* getEntityList(PyObject* self, PyObject* args); extern PyObject* getEntityList(PyObject* self, PyObject* args);
} }
namespace debug {
extern PyObject* addLoggerFileOutputStream(PyObject* self, PyObject* args);
extern PyObject* addLoggerCoutOutputStream(PyObject* self, PyObject* args);
extern PyObject* closeLoggerFileOutputStream(PyObject* self, PyObject* args);
extern PyObject* realTimeLoggerSpinOnce(PyObject* self, PyObject* args);
extern PyObject* realTimeLoggerDestroy(PyObject* self, PyObject* args);
extern PyObject* realTimeLoggerInstance(PyObject* self, PyObject* args);
}
PyObject* dgpyError; PyObject* dgpyError;
...@@ -237,6 +250,46 @@ static PyMethodDef dynamicGraphMethods[] = { ...@@ -237,6 +250,46 @@ static PyMethodDef dynamicGraphMethods[] = {
dynamicgraph::python::entity::getLoggerVerbosityLevel, dynamicgraph::python::entity::getLoggerVerbosityLevel,
METH_VARARGS, METH_VARARGS,
"get the verbosity level of the entity"}, "get the verbosity level of the entity"},
{"addLoggerFileOutputStream",
dynamicgraph::python::debug::addLoggerFileOutputStream,
METH_VARARGS,
"add a output file stream to the logger by filename"},
{"addLoggerCoutOutputStream",
dynamicgraph::python::debug::addLoggerCoutOutputStream,
METH_VARARGS,
"add std::cout as output stream to the logger"},
{"closeLoggerFileOutputStream",
dynamicgraph::python::debug::closeLoggerFileOutputStream,
METH_VARARGS,
"close all the loggers file output streams."},
{"entity_set_time_sample",
dynamicgraph::python::entity::setTimeSample,
METH_VARARGS,
"set the time sample for printing debugging information"},
{"entity_get_time_sample",
dynamicgraph::python::entity::getTimeSample,
METH_VARARGS,
"get the time sample for printing debugging information"},
{"entity_set_stream_print_period",
dynamicgraph::python::entity::setStreamPrintPeriod,
METH_VARARGS,
"set the period at which debugging information are printed"},
{"entity_get_stream_print_period",
dynamicgraph::python::entity::getStreamPrintPeriod,
METH_VARARGS,
"get the period at which debugging information are printed"},
{"real_time_logger_destroy",
dynamicgraph::python::debug::realTimeLoggerDestroy,
METH_VARARGS,
"Destroy the real time logger."},
{"real_time_logger_spin_once",
dynamicgraph::python::debug::realTimeLoggerSpinOnce,
METH_VARARGS,
"Destroy the real time logger."},
{"real_time_logger_instance",
dynamicgraph::python::debug::realTimeLoggerInstance,
METH_VARARGS,
"Starts the real time logger."},
{NULL, NULL, 0, NULL} /* Sentinel */ {NULL, NULL, 0, NULL} /* Sentinel */
}; };
......
...@@ -63,13 +63,13 @@ def updateEntityClasses(dictionary): ...@@ -63,13 +63,13 @@ def updateEntityClasses(dictionary):
from enum import Enum from enum import Enum
class VerbosityLevel(Enum): class VerbosityLevel(Enum):
""" """
Enum class for setVerbosityLevel Enum class for setVerbosityLevel
""" """
VERBOSITY_ALL =0 VERBOSITY_ALL =0
VERBOSITY_INFO_WARNING_ERROR = 1 VERBOSITY_INFO_WARNING_ERROR = 1
VERBOSITY_WARNING_ERROR = 2 VERBOSITY_WARNING_ERROR = 2
VERBOSITY_ERROR = 3 VERBOSITY_ERROR = 3
VERBOSITY_NONE = 4 VERBOSITY_NONE = 4
class Entity (object) : class Entity (object) :
...@@ -84,7 +84,7 @@ class Entity (object) : ...@@ -84,7 +84,7 @@ class Entity (object) :
entities = dict () entities = dict ()
def __init__(self, className, instanceName): def __init__(self, className, instanceName):
""" """
Constructor: if not called by a child class, create and store a pointer Constructor: if not called by a child class, create and store a pointer
...@@ -257,13 +257,13 @@ class Entity (object) : ...@@ -257,13 +257,13 @@ class Entity (object) :
self.boundNewCommand( cmd ) self.boundNewCommand( cmd )
def setLoggerVerbosityLevel(self,verbosity): def setLoggerVerbosityLevel(self,verbosity):
""" """
Specify for the entity the verbosity level Specify for the entity the verbosity level
""" """
return wrap.entity_set_logger_verbosity(self.obj, verbosity) return wrap.entity_set_logger_verbosity(self.obj, verbosity)
def getLoggerVerbosityLevel(self): def getLoggerVerbosityLevel(self):
""" """
Returns the entity's verbosity level Returns the entity's verbosity level
""" """
r=wrap.entity_get_logger_verbosity(self.obj) r=wrap.entity_get_logger_verbosity(self.obj)
...@@ -276,3 +276,27 @@ class Entity (object) : ...@@ -276,3 +276,27 @@ class Entity (object) :
elif r==3: elif r==3:
return VerbosityLevel.VERBOSITY_ERROR return VerbosityLevel.VERBOSITY_ERROR
return VerbosityLevel.VERBOSITY_NONE 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)
...@@ -437,7 +437,7 @@ namespace dynamicgraph { ...@@ -437,7 +437,7 @@ namespace dynamicgraph {
// Retrieve object verbosity level // Retrieve object verbosity level
PyObject* valueOfVerbosityLevel = PyObject_GetAttrString(objectVerbosityLevel, "value"); PyObject* valueOfVerbosityLevel = PyObject_GetAttrString(objectVerbosityLevel, "value");
long verbosityLevel = PyLong_AsLong(valueOfVerbosityLevel);//*((int*) lpointer); long verbosityLevel = PyLong_AsLong(valueOfVerbosityLevel);
try { try {
switch(verbosityLevel) switch(verbosityLevel)
...@@ -457,11 +457,11 @@ namespace dynamicgraph { ...@@ -457,11 +457,11 @@ namespace dynamicgraph {
PyErr_SetString(dgpyError, exc.what()); PyErr_SetString(dgpyError, exc.what());
return NULL; return NULL;
} catch (const char* s) { } catch (const char* s) {
PyErr_SetString(dgpyError, s); PyErr_SetString(dgpyError, s);
return NULL; return NULL;
} catch (...) { } catch (...) {
PyErr_SetString(dgpyError, "Unknown exception"); PyErr_SetString(dgpyError, "Unknown exception");
return NULL; return NULL;
} }
return Py_BuildValue(""); return Py_BuildValue("");
...@@ -495,6 +495,136 @@ namespace dynamicgraph { ...@@ -495,6 +495,136 @@ namespace dynamicgraph {
return Py_BuildValue("i",ares); return Py_BuildValue("i",ares);
} }
/**
\brief Get stream print period
*/
PyObject* getStreamPrintPeriod(PyObject* /*self*/, PyObject* args)
{
PyObject* object = NULL;
if (!PyArg_ParseTuple(args, "O", &object))
return NULL;
// Retrieve the entity instance
if (!PyCObject_Check(object)) {
PyErr_SetString(PyExc_TypeError,
"first argument is not an object");
return NULL;
}
void *pointer = PyCObject_AsVoidPtr(object);
Entity* entity = (Entity*)pointer;
double r ;
try {
r = entity->getStreamPrintPeriod();
} CATCH_ALL_EXCEPTIONS();
return Py_BuildValue("d",r);
}
/**
\brief Set print period
*/
PyObject* setStreamPrintPeriod(PyObject* /*self*/, PyObject* args )
{
PyObject* object = NULL;
double streamPrintPeriod=0;
if (!PyArg_ParseTuple(args, "Od", &object,&streamPrintPeriod))
return NULL;
// Retrieve the entity instance
if (!PyCObject_Check(object)) {
PyErr_SetString(PyExc_TypeError,
"First argument should be an object");
return NULL;
}
void *pointer = PyCObject_AsVoidPtr(object);
Entity* entity = (Entity*)pointer;
try {
entity->setStreamPrintPeriod(streamPrintPeriod);
} 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;
}
return Py_BuildValue("");
}
/**
\brief Get stream print period
*/
PyObject* getTimeSample(PyObject* /*self*/, PyObject* args)
{
PyObject* object = NULL;
if (!PyArg_ParseTuple(args, "O", &object))
return NULL;
// Retrieve the entity instance
if (!PyCObject_Check(object)) {
PyErr_SetString(PyExc_TypeError,
"first argument is not an object");
return NULL;
}
void *pointer = PyCObject_AsVoidPtr(object);
Entity* entity = (Entity*)pointer;
double r ;
try {
r = entity->getTimeSample();
} CATCH_ALL_EXCEPTIONS();
return Py_BuildValue("d",r);
}
/**
\brief Set time sample
*/
PyObject* setTimeSample(PyObject* /*self*/, PyObject* args )
{
PyObject* object = NULL;
double timeSample;
if (!PyArg_ParseTuple(args, "Od", &object,&timeSample))
return NULL;
// Retrieve the entity instance
if (!PyCObject_Check(object)) {
PyErr_SetString(PyExc_TypeError,
"First argument should be an object");
return NULL;
}
void *pointer = PyCObject_AsVoidPtr(object);
Entity* entity = (Entity*)pointer;
try {
entity->setTimeSample(timeSample);
} 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;
}
return Py_BuildValue("");
}
} }
} }
......
...@@ -24,6 +24,7 @@ namespace dynamicgraph { ...@@ -24,6 +24,7 @@ namespace dynamicgraph {
extern PyObject* dgpyError; extern PyObject* dgpyError;
namespace pool { namespace pool {
PyObject* writeGraph (PyObject* /*self*/, PyObject* args) PyObject* writeGraph (PyObject* /*self*/, PyObject* args)
{ {
char* filename; char* filename;
...@@ -52,16 +53,16 @@ namespace dynamicgraph { ...@@ -52,16 +53,16 @@ namespace dynamicgraph {
Py_ssize_t classNumber = listOfEntities.size(); Py_ssize_t classNumber = listOfEntities.size();
// Build a tuple object // Build a tuple object
PyObject* classTuple = PyTuple_New(classNumber); PyObject* classTuple = PyTuple_New(classNumber);
Py_ssize_t iEntity = 0; Py_ssize_t iEntity = 0;
for (PoolStorage::Entities::const_iterator entity_it = for (PoolStorage::Entities::const_iterator entity_it =
listOfEntities.begin(); listOfEntities.begin();
entity_it != listOfEntities.end(); entity_it != listOfEntities.end();
++entity_it) ++entity_it)
{ {
const std::string & aname = entity_it->second->getName(); const std::string & aname = entity_it->second->getName();
PyObject* className = PyObject* className =
Py_BuildValue("s", aname.c_str()); Py_BuildValue("s", aname.c_str());
PyTuple_SetItem(classTuple, iEntity, className); PyTuple_SetItem(classTuple, iEntity, className);
iEntity++; iEntity++;
...@@ -71,6 +72,7 @@ namespace dynamicgraph { ...@@ -71,6 +72,7 @@ namespace dynamicgraph {
return NULL; return NULL;
} }
} // python } // python
} // dynamicgraph } // namespace pool
} // namespace pool } // dynamicgraph
...@@ -36,6 +36,7 @@ namespace dynamicgraph ...@@ -36,6 +36,7 @@ namespace dynamicgraph
"CustomEntity("+name+")::input(double)::out_double") "CustomEntity("+name+")::input(double)::out_double")
{ {
addSignal();
} }
void addSignal() void addSignal()
...@@ -53,6 +54,18 @@ namespace dynamicgraph ...@@ -53,6 +54,18 @@ namespace dynamicgraph
{ {
const double &aDouble = m_sigdSIN(inTime); const double &aDouble = m_sigdSIN(inTime);
res = aDouble; res = aDouble;
std::ostringstream oss;
oss << "start update " << res;
sendMsg(oss.str().c_str(),MSG_TYPE_ERROR);
sendMsg("This is a message of level MSG_TYPE_DEBUG",MSG_TYPE_DEBUG);
sendMsg("This is a message of level MSG_TYPE_INFO",MSG_TYPE_INFO);
sendMsg("This is a message of level MSG_TYPE_WARNING",MSG_TYPE_WARNING);
sendMsg("This is a message of level MSG_TYPE_ERROR",MSG_TYPE_ERROR);
sendMsg("This is a message of level MSG_TYPE_DEBUG_STREAM",MSG_TYPE_DEBUG_STREAM);
sendMsg("This is a message of level MSG_TYPE_INFO_STREAM",MSG_TYPE_INFO_STREAM);
sendMsg("This is a message of level MSG_TYPE_WARNING_STREAM",MSG_TYPE_WARNING_STREAM);
sendMsg("This is a message of level MSG_TYPE_ERROR_STREAM",MSG_TYPE_ERROR_STREAM);
sendMsg("end update",MSG_TYPE_ERROR);
return res; return res;
} }
......
# Olivier Stasse # Olivier Stasse
# 2019 CNRS # 2019 CNRS
# #
import sys, os import sys, os
import time
# Put local python module at first priority # Put local python module at first priority
sys.path.insert(0,os.getcwd()+'/../src') sys.path.insert(0,os.getcwd()+'/../src')
sys.path.insert(0,os.getcwd()) sys.path.insert(0,os.getcwd())
...@@ -9,18 +11,63 @@ sys.path.insert(0,os.getcwd()) ...@@ -9,18 +11,63 @@ sys.path.insert(0,os.getcwd())
print(os.getcwd()) print(os.getcwd())
from dynamic_graph_tests.custom_entity import * from dynamic_graph_tests.custom_entity import *
from dynamic_graph.entity import VerbosityLevel from dynamic_graph.entity import VerbosityLevel
from dynamic_graph import addLoggerFileOutputStream, addLoggerCoutOutputStream, closeLoggerFileOutputStream
from dynamic_graph import real_time_logger_instance, real_time_logger_spin_once, real_time_logger_destroy
# Starts the real time logger instance
real_time_logger_instance()
aCustomEntity = CustomEntity("a_custom_entity") aCustomEntity = CustomEntity("a_custom_entity")
print(dir(aCustomEntity))
addLoggerFileOutputStream("/tmp/output.dat")
aCustomEntity.signals() aCustomEntity.signals()
aCustomEntity.setTimeSample(0.001)
print(aCustomEntity.getTimeSample())
aCustomEntity.setStreamPrintPeriod(0.002)
print(aCustomEntity.getStreamPrintPeriod())
aCustomEntity.setLoggerVerbosityLevel(VerbosityLevel.VERBOSITY_INFO_WARNING_ERROR) aCustomEntity.setLoggerVerbosityLevel(VerbosityLevel.VERBOSITY_INFO_WARNING_ERROR)
print(aCustomEntity.getLoggerVerbosityLevel())