GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: src/dynamic_graph/signal-base-py.cc Lines: 31 71 43.7 %
Date: 2022-09-30 08:22:45 Branches: 39 168 23.2 %

Line Branch Exec Source
1
// Copyright 2010, Florent Lamiraux, Thomas Moulard, LAAS-CNRS.
2
3
#include <dynamic-graph/linear-algebra.h>
4
#include <dynamic-graph/signal-base.h>
5
#include <dynamic-graph/signal-ptr.h>
6
#include <dynamic-graph/signal-time-dependent.h>
7
#include <dynamic-graph/signal.h>
8
#include <dynamic-graph/value.h>
9
10
#include <boost/python.hpp>
11
#include <iostream>
12
#include <sstream>
13
14
#include "dynamic-graph/python/dynamic-graph-py.hh"
15
#include "dynamic-graph/python/signal-wrapper.hh"
16
#include "dynamic-graph/python/signal.hh"
17
18
using dynamicgraph::SignalBase;
19
20
namespace bp = boost::python;
21
22
namespace dynamicgraph {
23
namespace python {
24
25
typedef int time_type;
26
27
typedef Eigen::AngleAxis<double> VectorUTheta;
28
typedef Eigen::Quaternion<double> Quaternion;
29
30
typedef Eigen::VectorXd Vector;
31
typedef Eigen::Vector3d Vector3;
32
typedef Eigen::Matrix<double, 7, 1> Vector7;
33
34
typedef Eigen::MatrixXd Matrix;
35
typedef Eigen::Matrix<double, 3, 3> MatrixRotation;
36
typedef Eigen::Matrix<double, 4, 4> Matrix4;
37
typedef Eigen::Transform<double, 3, Eigen::Affine> MatrixHomogeneous;
38
typedef Eigen::Matrix<double, 6, 6> MatrixTwist;
39
40
template <typename Time>
41
2
void exposeSignalBase(const char* name) {
42
  typedef SignalBase<Time> S_t;
43
2
  bp::class_<S_t, boost::noncopyable>(name, bp::no_init)
44
      .add_property("time",
45
                    bp::make_function(
46
                        &S_t::getTime,
47
                        bp::return_value_policy<bp::copy_const_reference>()),
48
                    &S_t::setTime)
49
6
      .add_property("name",
50
                    bp::make_function(
51
                        &S_t::getName,
52
                        bp::return_value_policy<bp::copy_const_reference>()))
53
54

6
      .def("getName", &S_t::getName,
55
           bp::return_value_policy<bp::copy_const_reference>())
56
      .def(
57
          "getClassName",
58
          +[](const S_t& s) -> std::string {
59
            std::string ret;
60
            s.getClassName(ret);
61
            return ret;
62
          })
63
64

2
      .def("plug", &S_t::plug, "Plug the signal to another signal")
65
4
      .def("unplug", &S_t::unplug, "Unplug the signal")
66
2
      .def("isPlugged", &S_t::isPlugged, "Whether the signal is plugged")
67
2
      .def("getPlugged", &S_t::getPluged,
68
           bp::return_value_policy<bp::reference_existing_object>(),
69
           "To which signal the signal is plugged")
70
71
2
      .def("recompute", &S_t::recompute, "Recompute the signal at given time")
72
73
2
      .def(
74
          "__str__",
75
          +[](const S_t& s) -> std::string {
76
            std::ostringstream oss;
77
            s.display(oss);
78
            return oss.str();
79
          })
80

4
      .def(
81
          "displayDependencies",
82
          +[](const S_t& s, int time) -> std::string {
83
            std::ostringstream oss;
84
            s.displayDependencies(oss, time);
85
            return oss.str();
86
          },
87
          "Print the signal dependencies in a string");
88
2
}
89
90
template <>
91
2
auto exposeSignal<MatrixHomogeneous, time_type>(const std::string& name) {
92
  typedef Signal<MatrixHomogeneous, time_type> S_t;
93
  bp::class_<S_t, bp::bases<SignalBase<time_type> >, boost::noncopyable> obj(
94
2
      name.c_str(), bp::init<std::string>());
95
  obj.add_property(
96
      "value",
97
      +[](const S_t& signal) -> Matrix4 {
98
        return signal.accessCopy().matrix();
99
      },
100
      +[](S_t& signal, const Matrix4& v) {
101
        // TODO it isn't hard to support pinocchio::SE3 type here.
102
        // However, this adds a dependency to pinocchio.
103
        signal.setConstant(MatrixHomogeneous(v));
104
      },
105
2
      "the signal value.");
106
2
  return obj;
107
}
108
109
2
void exposeSignals() {
110
2
  exposeSignalBase<time_type>("SignalBase");
111
112

2
  exposeSignalsOfType<bool, time_type>("Bool");
113

2
  exposeSignalsOfType<int, time_type>("Int");
114

2
  exposeSignalsOfType<double, time_type>("Double");
115
116

2
  exposeSignalsOfType<Vector, time_type>("Vector");
117

2
  exposeSignalsOfType<Vector3, time_type>("Vector3");
118

2
  exposeSignalsOfType<Vector7, time_type>("Vector7");
119
120

2
  exposeSignalsOfType<Matrix, time_type>("Matrix");
121

2
  exposeSignalsOfType<MatrixRotation, time_type>("MatrixRotation");
122

2
  exposeSignalsOfType<MatrixHomogeneous, time_type>("MatrixHomogeneous");
123

2
  exposeSignalsOfType<MatrixTwist, time_type>("MatrixTwist");
124
125

2
  exposeSignalsOfType<Quaternion, time_type>("Quaternion");
126

2
  exposeSignalsOfType<VectorUTheta, time_type>("VectorUTheta");
127
2
}
128
129
namespace signalBase {
130
131
template <class T>
132
SignalWrapper<T, int>* createSignalWrapperTpl(const char* name, bp::object o,
133
                                              std::string& error) {
134
  typedef SignalWrapper<T, int> SignalWrapper_t;
135
  if (!SignalWrapper_t::checkCallable(o, error)) {
136
    return NULL;
137
  }
138
139
  SignalWrapper_t* obj = new SignalWrapper_t(name, o);
140
  return obj;
141
}
142
143
PythonSignalContainer* getPythonSignalContainer() {
144
  Entity* obj = entity::create("PythonSignalContainer", "python_signals");
145
  return dynamic_cast<PythonSignalContainer*>(obj);
146
}
147
148
#define SIGNAL_WRAPPER_TYPE(IF, Enum, Type)                               \
149
  IF(command::Value::typeName(command::Value::Enum).compare(type) == 0) { \
150
    obj = createSignalWrapperTpl<Type>(name, object, error);              \
151
  }
152
153
/**
154
   \brief Create an instance of SignalWrapper
155
*/
156
SignalBase<int>* createSignalWrapper(const char* name, const char* type,
157
                                     bp::object object) {
158
  PythonSignalContainer* psc = getPythonSignalContainer();
159
  if (psc == NULL) return NULL;
160
161
  SignalBase<int>* obj = NULL;
162
  std::string error;
163
  SIGNAL_WRAPPER_TYPE(if, BOOL, bool)
164
  // SIGNAL_WRAPPER_TYPE(else if, UNSIGNED ,bool)
165
  SIGNAL_WRAPPER_TYPE(else if, INT, int)
166
  SIGNAL_WRAPPER_TYPE(else if, FLOAT, float)
167
  SIGNAL_WRAPPER_TYPE(else if, DOUBLE, double)
168
  // SIGNAL_WRAPPER_TYPE(else if, STRING   ,bool)
169
  SIGNAL_WRAPPER_TYPE(else if, VECTOR, Vector)
170
  // SIGNAL_WRAPPER_TYPE(else if, MATRIX   ,bool)
171
  // SIGNAL_WRAPPER_TYPE(else if, MATRIX4D ,bool)
172
  else {
173
    error = "Type not understood";
174
  }
175
176
  if (obj == NULL) throw std::runtime_error(error);
177
  // Register signal into the python signal container
178
  psc->signalRegistration(*obj);
179
180
  // Return the pointer
181
  return obj;
182
}
183
184
}  // namespace signalBase
185
}  // namespace python
186
}  // namespace dynamicgraph