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 689 additions and 443 deletions
// Copyright 2010, Florent Lamiraux, Thomas Moulard, LAAS-CNRS.
//
// This file is part of dynamic-graph-python.
// dynamic-graph-python is free software: you can redistribute it
// and/or modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation, either
// version 3 of the License, or (at your option) any later version.
//
// dynamic-graph-python is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Lesser Public License for more details. You should
// have received a copy of the GNU Lesser General Public License along
// with dynamic-graph. If not, see <http://www.gnu.org/licenses/>.
#include <Python.h>
#include <iostream>
#include <dynamic-graph/factory.h>
using dynamicgraph::Entity;
using dynamicgraph::ExceptionAbstract;
namespace dynamicgraph {
namespace python {
extern PyObject* error;
namespace factory {
/**
\brief Get name of entity
*/
PyObject* getEntityClassList(PyObject* /*self*/, PyObject* args)
{
if (!PyArg_ParseTuple(args, ""))
return NULL;
std::vector <std::string> classNames;
dynamicgraph::g_factory.listEntities(classNames);
unsigned int classNumber = classNames.size();
// Build a tuple object
PyObject* classTuple = PyTuple_New(classNumber);
for (unsigned int iEntity = 0; iEntity < classNames.size(); iEntity++) {
PyObject* className = Py_BuildValue("s", classNames[iEntity].c_str());
PyTuple_SetItem(classTuple, iEntity, className);
}
return Py_BuildValue("O", classTuple);
}
} // namespace factory
} // namespace python
} // namespace dynamicgraph
// -*- mode: c++ -*-
// Copyright 2011, Florent Lamiraux, CNRS.
//
// This file is part of dynamic-graph-python.
// dynamic-graph is free software: you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public License
// as published by the Free Software Foundation, either version 3 of
// the License, or (at your option) any later version.
//
// dynamic-graph is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Lesser Public License for more details. You should have
// received a copy of the GNU Lesser General Public License along with
// dynamic-graph. If not, see <http://www.gnu.org/licenses/>.
#ifdef WIN32
#include <Windows.h>
#else
#include <dlfcn.h>
#endif
#include <iostream>
#include "dynamic-graph/debug.h"
#include "dynamic-graph/python/interpreter.hh"
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[5] = {
"import sys\n",
"import traceback\n",
"if '' not in sys.path: sys.path.append('')\n",
"sys.argv = ['']\n",
"def display(s): return str(s) if not s is None else None"
};
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"};
bool HandleErr(std::string& err, PyObject* globals_, int PythonInputType) {
dgDEBUGIN(15);
err = "";
bool lres = false;
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_);
err = obj_to_str(stderr_obj);
Py_DECREF(stderr_obj);
// Here if there is a syntax error and
// and the interpreter input is set to Py_eval_input,
// it is maybe a statement instead of an expression.
// Therefore we indicate to re-evaluate the command.
if (is_syntax_error && PythonInputType == Py_eval_input) {
dgDEBUG(15) << "Detected a syntax error " << std::endl;
lres = false;
} else
lres = true;
PyErr_Clear();
} else {
dgDEBUG(15) << "no object generated but no error occured." << std::endl;
}
return lres;
}
using dynamicgraph::python::Interpreter;
Interpreter::Interpreter()
{
Interpreter::Interpreter() {
// load python dynamic library
// this is silly, but required to be able to import dl module.
#ifndef WIN32
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_);
......@@ -45,73 +86,168 @@ Interpreter::Interpreter()
PyRun_SimpleString(pythonPrefix[2].c_str());
PyRun_SimpleString(pythonPrefix[3].c_str());
PyRun_SimpleString(pythonPrefix[4].c_str());
traceback_format_exception_ = PyDict_GetItemString
(PyModule_GetDict(PyImport_AddModule("traceback")), "format_exception");
assert(PyCallable_Check(traceback_format_exception_));
Py_INCREF(traceback_format_exception_);
}
PyRun_SimpleString(pythonPrefix[5].c_str());
PyRun_SimpleString(pythonPrefix[6].c_str());
PyRun_SimpleString(pythonPrefix[7].c_str());
PyRun_SimpleString("import linecache");
Interpreter::~Interpreter()
{
//Py_DECREF(mainmod_);
//Py_DECREF(globals_);
//Py_DECREF(traceback_format_exception_);
Py_Finalize();
// Allow threads
_pyState = PyEval_SaveThread();
}
std::string Interpreter::python( const std::string& command )
{
PyObject* result = PyRun_String(command.c_str(), Py_eval_input, globals_,
globals_);
if (!result) {
PyErr_Clear();
result = PyRun_String(command.c_str(), Py_single_input, globals_,
globals_);
}
if (result == NULL) {
if (PyErr_Occurred()) {
PyObject *ptype, *pvalue, *ptraceback;
PyErr_Fetch(&ptype, &pvalue, &ptraceback);
if (ptraceback == NULL) {
ptraceback = Py_None;
}
PyObject* args = PyTuple_New(3);
PyTuple_SET_ITEM(args, 0, ptype);
PyTuple_SET_ITEM(args, 1, pvalue);
PyTuple_SET_ITEM(args, 2, ptraceback);
result = PyObject_CallObject(traceback_format_exception_, args);
assert(PyList_Check(result));
unsigned int size = PyList_GET_SIZE(result);
std::string stringRes;
for (unsigned int i=0; i<size; i++) {
stringRes += std::string(PyString_AsString(PyList_GET_ITEM(result, i)));
Interpreter::~Interpreter() {
PyEval_RestoreThread(_pyState);
// 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
{
PyObject* poAttrList = PyObject_Dir(mainmod_);
PyObject* poAttrIter = PyObject_GetIter(poAttrList);
PyObject* poAttrName;
while ((poAttrName = PyIter_Next(poAttrIter)) != NULL) {
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) {
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);
Py_DECREF(poAttr);
}
result = PyString_FromString(stringRes.c_str());
PyErr_Clear();
} else {
std::cout << "Result is NULL but no error occurred." << std::endl;
Py_DECREF(poAttrName);
}
Py_DECREF(poAttrIter);
Py_DECREF(poAttrList);
}
Py_DECREF(mainmod_);
Py_DECREF(globals_);
// Py_Finalize();
}
std::string Interpreter::python(const std::string& command) {
std::string lerr(""), lout(""), lres("");
python(command, lres, lout, lerr);
return lres;
}
void Interpreter::python(const std::string& command, std::string& res,
std::string& out, std::string& err) {
res = "";
out = "";
err = "";
// Check if the command is not a python comment or empty.
std::string::size_type iFirstNonWhite = command.find_first_not_of(" \t");
// Empty command
if (iFirstNonWhite == std::string::npos) return;
// Command is a comment. Ignore it.
if (command[iFirstNonWhite] == '#') return;
PyEval_RestoreThread(_pyState);
std::cout << command.c_str() << std::endl;
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_);
// 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.
else
err = "";
} else
dgDEBUG(15) << "Do not try a second time." << std::endl;
}
PyObject* stdout_obj = 0;
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)
if (out.size() != 0) std::cout << "Output:" << out << std::endl;
if (err.size() != 0) std::cout << "Error:" << err << std::endl;
// If python cannot build a string representation of result
// then results is equal to NULL. This will trigger a SEGV
dgDEBUG(15) << "For command: " << command << std::endl;
if (result != NULL) {
res = obj_to_str(result);
dgDEBUG(15) << "Result is: " << res << std::endl;
Py_DECREF(result);
} else {
result = PyObject_Str(result);
dgDEBUG(15) << "Result is: empty" << std::endl;
}
std::string value = PyString_AsString(result);
return value;
dgDEBUG(15) << "Out is: " << out << std::endl;
dgDEBUG(15) << "Err is :" << err << std::endl;
_pyState = PyEval_SaveThread();
return;
}
void Interpreter::runPythonFile( std::string filename )
{
Py_Finalize();
Py_Initialize();
PyRun_SimpleString(pythonPrefix[0].c_str());
PyRun_SimpleString(pythonPrefix[1].c_str());
PyRun_SimpleString(pythonPrefix[2].c_str());
PyRun_SimpleString(pythonPrefix[4].c_str());
PyRun_SimpleFile(NULL, filename.c_str());
PyObject* Interpreter::globals() { return globals_; }
void Interpreter::runPythonFile(std::string filename) {
std::string err = "";
runPythonFile(filename, err);
}
void Interpreter::runPythonFile(std::string filename, std::string& err) {
FILE* pFile = fopen(filename.c_str(), "r");
if (pFile == 0x0) {
err = filename + " cannot be open";
return;
}
PyEval_RestoreThread(_pyState);
err = "";
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;
}
Py_DecRef(run);
_pyState = PyEval_SaveThread();
fclose(pFile);
}
std::string Interpreter::processStream(std::istream& stream, std::ostream& os)
{
char line[10000]; sprintf(line, "%s", "\n");
void Interpreter::runMain(void) {
PyEval_RestoreThread(_pyState);
#if PY_MAJOR_VERSION >= 3
const Py_UNICODE* argv[] = {L"dg-embedded-pysh"};
Py_Main(1, const_cast<Py_UNICODE**>(argv));
#else
const char* argv[] = {"dg-embedded-pysh"};
Py_Main(1, const_cast<char**>(argv));
#endif
_pyState = PyEval_SaveThread();
}
std::string Interpreter::processStream(std::istream& stream, std::ostream& os) {
char line[10000];
sprintf(line, "%s", "\n");
std::string command;
std::streamsize maxSize = 10000;
#if 0
......@@ -126,3 +262,6 @@ std::string Interpreter::processStream(std::istream& stream, std::ostream& os)
#endif
return command;
}
} // namespace python
} // namespace dynamicgraph
// Copyright 2010, Florent Lamiraux, Thomas Moulard, LAAS-CNRS.
//
// This file is part of dynamic-graph-python.
// dynamic-graph-python is free software: you can redistribute it
// and/or modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation, either
// version 3 of the License, or (at your option) any later version.
//
// dynamic-graph-python is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Lesser Public License for more details. You should
// have received a copy of the GNU Lesser General Public License along
// with dynamic-graph. If not, see <http://www.gnu.org/licenses/>.
#include <Python.h>
#include <iostream>
#include <sstream>
#include <dynamic-graph/signal-base.h>
#include <dynamic-graph/signal.h>
#include <dynamic-graph/signal-caster.h>
#include <dynamic-graph/linear-algebra.h>
#include <../src/convert-dg-to-py.hh>
using dynamicgraph::SignalBase;
namespace dynamicgraph {
namespace python {
extern PyObject* error;
using namespace convert;
namespace signalBase {
static void destroy (void* self);
/**
\brief Create an instance of SignalBase
*/
PyObject* create(PyObject* /*self*/, PyObject* args)
{
char *name = NULL;
if (!PyArg_ParseTuple(args, "s", &name))
return NULL;
SignalBase<int>* obj = NULL;
obj = new SignalBase<int>(std::string(name));
// Return the pointer
return PyCObject_FromVoidPtr((void*)obj, destroy);
}
/**
\brief Destroy an instance of InvertedPendulum
*/
static void destroy (void* 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 (!PyCObject_Check(object))
return NULL;
pointer = PyCObject_AsVoidPtr(object);
SignalBase<int>* obj = (SignalBase<int>*)pointer;
int time = obj->getTime();
return Py_BuildValue("i", time);
}
PyObject* display(PyObject* /*self*/, PyObject* args)
{
void* pointer = NULL;
PyObject* object = NULL;
if (!PyArg_ParseTuple(args,"O", &object))
return NULL;
if (!PyCObject_Check(object))
return NULL;
pointer = PyCObject_AsVoidPtr(object);
SignalBase<int>* obj = (SignalBase<int>*)pointer;
std::ostringstream oss;
try {
obj->display(oss);
} catch (std::exception& exc) {
PyErr_SetString(error, exc.what());
return NULL;
}
return Py_BuildValue("s", oss.str().c_str());
}
PyObject* getValue(PyObject* /*self*/, PyObject* args)
{
void* pointer = NULL;
PyObject* object = NULL;
if (!PyArg_ParseTuple(args,"O", &object))
return NULL;
if (!PyCObject_Check(object))
return NULL;
pointer = PyCObject_AsVoidPtr(object);
SignalBase<int>* signal = (SignalBase<int>*)pointer;
/* Temptative for specific signal type. */
Signal<dynamicgraph::Vector,int> * sigvec
= dynamic_cast< Signal<dynamicgraph::Vector,int>* >( signal );
if( NULL!= sigvec )
{
return vectorToPython( sigvec->accessCopy() );
}
Signal<dynamicgraph::Matrix,int> * sigmat
= dynamic_cast< Signal<dynamicgraph::Matrix,int>* >( signal );
if( NULL!= sigmat )
{
return matrixToPython( sigmat->accessCopy() );
}
Signal<double,int> * sigdouble
= dynamic_cast< Signal<double,int>* >( signal );
if( NULL!= sigdouble )
{
return Py_BuildValue("d", sigdouble->accessCopy() );
}
/* Non specific signal: use a generic way. */
std::ostringstream value;
try {
signal->get(value);
} catch (const dynamicgraph::ExceptionAbstract& exc) {
PyErr_SetString(error, exc.getStringMessage().c_str());
return NULL;
} catch (const std::exception& exc) {
PyErr_SetString(error, exc.what());
} catch (...) {
PyErr_SetString(error, "Unknown exception");
return NULL;
}
std::string valueString = value.str();
return Py_BuildValue("s", valueString.c_str());
}
PyObject* getName(PyObject* /*self*/, PyObject* args)
{
void* pointer = NULL;
PyObject* object = NULL;
if (!PyArg_ParseTuple(args,"O", &object))
return NULL;
if (!PyCObject_Check(object))
return NULL;
pointer = PyCObject_AsVoidPtr(object);
SignalBase<int>* signal = (SignalBase<int>*)pointer;
std::string name;
try {
name = signal->getName();
} catch (const dynamicgraph::ExceptionAbstract& exc) {
PyErr_SetString(error, exc.getStringMessage().c_str());
return NULL;
} catch (const std::exception& exc) {
PyErr_SetString(error, exc.what());
} catch (...) {
PyErr_SetString(error, "Unknown exception");
return NULL;
}
return Py_BuildValue("s", name.c_str());
}
PyObject* setValue(PyObject* /*self*/, PyObject* args)
{
void * pointer = NULL;
PyObject* object = NULL;
char* valueString = NULL;
if (!PyArg_ParseTuple(args,"Os", &object, &valueString))
return NULL;
if (!PyCObject_Check(object))
return NULL;
pointer = PyCObject_AsVoidPtr(object);
SignalBase<int>* signal = (SignalBase<int>*)pointer;
std::ostringstream os;
os << valueString;
std::istringstream value(os.str());
try {
signal->set(value);
} catch (const dynamicgraph::ExceptionAbstract& exc) {
PyErr_SetString(error, exc.getStringMessage().c_str());
return NULL;
} catch (const std::exception& exc) {
PyErr_SetString(error, exc.what());
return NULL;
} catch (...) {
PyErr_SetString(error, "Unknown exception");
return NULL;
}
return Py_BuildValue("");
}
PyObject* recompute(PyObject* /*self*/, PyObject* args)
{
void * pointer = NULL;
PyObject* object = NULL;
unsigned int time;
if (!PyArg_ParseTuple(args,"OI", &object, &time))
return NULL;
if (!PyCObject_Check(object))
return NULL;
pointer = PyCObject_AsVoidPtr(object);
SignalBase<int>* signal = (SignalBase<int>*)pointer;
try {
signal->recompute(time);
} catch (const std::exception& exc) {
PyErr_SetString(error, exc.what());
}
return Py_BuildValue("");
}
PyObject* unplug(PyObject* /*self*/, PyObject* args)
{
void * pointer = NULL;
PyObject* object = NULL;
if (!PyArg_ParseTuple(args,"O", &object))
return NULL;
if (!PyCObject_Check(object))
return NULL;
pointer = PyCObject_AsVoidPtr(object);
SignalBase<int>* signal = (SignalBase<int>*)pointer;
try {
signal->unplug();
} catch (const std::exception& exc) {
PyErr_SetString(error, exc.what());
}
return Py_BuildValue("");
}
}
}
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/* 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;
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
# flake8: noqa
hello world