Commit db1c58f5 authored by Guilhem Saurel's avatar Guilhem Saurel

Merge branch 'coverage' into 'devel'

Merge Coverage into devel

See merge request !2
parents 982a0e0e 6bde0edb
Pipeline #5288 passed with stage
in 7 minutes and 48 seconds
......@@ -4,7 +4,7 @@
They are several ways to perform debugging in dynamic-graph depending on your needs or situation:
- Programmatically inside the entity in C++ will write inside a buffer in a different thread and output in a stream
(either std::cout or a file). It is detailed in \subpage subp_debug_rt_logger.
- Programmatically inside the entity in C++ using a member of the entities and the previous real-time mechanism.
- Programmatically inside the entity in C++ using a member of the entities and the previous real-time mechanism.
It provides 4 levels of messags :(DEBUG,INFO, WARNING, ERROR). It is described in details here:
\subpage subp_logger
- Programmatically in C++ to avoid overhead with macros and handling level as an int: \subpage subp_dbg_trace
......
......@@ -66,7 +66,7 @@ Here is some example on how to display or record some information.
logger_.countdown();
\endcode
Specifying the file with __FILE__ and the line inside the file by __LINE__ are necessary for the
STREAM messages. Indeed they are indexed using the two values. As the default value are "" and 0
Specifying the file with __FILE__ and the line inside the file by __LINE__ are necessary for the
STREAM messages. Indeed they are indexed using the two values. As the default value are "" and 0
the counting will be confused.
*/
/**
/**
\page subp_debug_rt_logger Real-time Logger
It is intended to be used like this:
\code
#define ENABLE_RT_LOG
#include <dynamic-graph/real-time-logger.h>
// Somewhere in the main function of your executable
int main (int argc, char** argv) {
dgADD_OSTREAM_TO_RTLOG (std::cout);
}
// Somewhere in your library
dgRTLOG() << "your message. Prefer to use \n than std::endl."
\endcode
\note Thread safety. This class expects to have:
- only one reader: the one who take the log entries and write them somewhere.
- one writer at a time. Writing to the logs is **never** a blocking
......
......@@ -2,9 +2,9 @@
\page subp_dbg_trace Debugging with macros and level
\section subp_dbg_trace_intro Introduction
The idea of this class and collection of MACROS is to specify
a level for a message, and record the message in a stream according to this level.
In addition there are mechanisms allowing that no time
The idea of this class and collection of MACROS is to specify
a level for a message, and record the message in a stream according to this level.
In addition there are mechanisms allowing that no time
is wasted in condition test. You can therefore let the debugging messages
inside the code without impact on performances.
......@@ -42,7 +42,7 @@ It will generate the following output:
\code
/path_to/dynamic-graph/tests/debug-trace.cpp: testDebugTrace(#46) :# In {
\endcode
The output displays the name of the source file, the name of the method,
The output displays the name of the source file, the name of the method,
the line where is the macro, and the message itself.
When going out of the method:
......
......@@ -6,27 +6,25 @@
\image html entity.png
Despite the fact that it looks very similar to a ROS node or a CORBA/OpenRTM server, an entity is simply a C++ object.
The main idea is that this entity is providing mostly a data-driven functionnality working at very high rate (\f$ 200 Hz\f$ or \f$ 1 kHz \f$)
and should have a minimal computational time foot-print.
For this \subpage subp_signals (or ports to use a more classical terminology) are providing a time dependency between data.
To implement this, an output signal is linked with a method of the entity. The method calls input signals or use other means
to get the needed data.
It might be provided by the connection with remote computers through a middleware, or specific protocols,
but in general the external data is based upon the sensor values provided by a "Device" entity.
For this reason the signal evaluations are realized through the cascade of dependencies and start from the evaluation of an input
signal of a periodic node (in general the device). This is realized inside a \b real-time thread.
To add flexibility to a node, it is possible to add command with arguments to modify the internal behavior of the entity
or get information from the entity.
As a command is in general asynchronous and rare with respect to the data-flow scheme for the signals the command is in general
executed in a \b none-real-time thread.
The main idea is that this entity is providing mostly a data-driven functionnality working at very high rate (\f$ 200
Hz\f$ or \f$ 1 kHz \f$) and should have a minimal computational time foot-print.
For this \subpage subp_signals (or ports to use a more classical terminology) are providing a time dependency between
data. To implement this, an output signal is linked with a method of the entity. The method calls input signals or use
other means to get the needed data. It might be provided by the connection with remote computers through a middleware,
or specific protocols, but in general the external data is based upon the sensor values provided by a "Device" entity.
For this reason the signal evaluations are realized through the cascade of dependencies and start from the evaluation
of an input signal of a periodic node (in general the device). This is realized inside a \b real-time thread.
To add flexibility to a node, it is possible to add command with arguments to modify the internal behavior of the
entity or get information from the entity. As a command is in general asynchronous and rare with respect to the
data-flow scheme for the signals the command is in general executed in a \b none-real-time thread.
\subsection entity_classes Entity class
Entities are implemented as C++ classes and compiled as dynamic libraries. They can be loaded and instancied dynamically.
It is therefore necessary to specify the location of their dynamical libraries.
However given the time it might take to load the library, it is not advised to do that during a control-law computation.
Entity instanciation also implies memory allocation which is also time consuming and thus not advised inside a real-time thread.
Entities are implemented as C++ classes and compiled as dynamic libraries. They can be loaded and instancied
dynamically. It is therefore necessary to specify the location of their dynamical libraries. However given the time it
might take to load the library, it is not advised to do that during a control-law computation. Entity instanciation
also implies memory allocation which is also time consuming and thus not advised inside a real-time thread.
The entities will be placed in ${PREFIX}/lib/plugin (since this may change, it is advised to
check the install log or the CMakeLists.txt file to check the installation path).
......@@ -42,9 +40,10 @@ enable creation of this entity through the factory.
\subsection specific_semantics Specific semantics with entities
It is possible to derive classes and apply specific semantic for the entities. In our case we are interested in specific control semantics:
\li Tasks (more information <a href="http://stack-of-tasks.github.io/sot-core/doxygen/HEAD/a00089.html">here</a>)
\li Features (more information <a href="http://stack-of-tasks.github.io/sot-core/doxygen/HEAD/a00030.html">here</a>)
\li Solver (more information <a href="http://stack-of-tasks.github.io/sot-core/doxygen/HEAD/a00078.html">here</a>)
It is possible to derive classes and apply specific semantic for the entities. In our case we are interested in
specific control semantics: \li Tasks (more information <a
href="http://stack-of-tasks.github.io/sot-core/doxygen/HEAD/a00089.html">here</a>) \li Features (more information <a
href="http://stack-of-tasks.github.io/sot-core/doxygen/HEAD/a00030.html">here</a>) \li Solver (more information <a
href="http://stack-of-tasks.github.io/sot-core/doxygen/HEAD/a00078.html">here</a>)
*/
......@@ -11,8 +11,8 @@ Objects, which are derived from Entities (base class dynamicgraph::Entity), can
declared within the code and compiled as shared libraries (.so/.dll files).
These libraries can be loaded at run-time using the PluginLoader methods,
and at the same time register their class names to the Factory (see the
examples in the <a href="http://projects.laas.fr/gepetto/doc/stack-of-tasks/sot-core/master/doxygen-html">sot-core documentation</a>
for advanced control examples).
examples in the <a href="http://projects.laas.fr/gepetto/doc/stack-of-tasks/sot-core/master/doxygen-html">sot-core
documentation</a> for advanced control examples).
The Factory can then create instances of these objects and subsequently
register them in the Pool. From the pool they can be listed, accessed, and acted upon
......@@ -40,19 +40,19 @@ When writing entities you might use some macros which are very useful to write y
\subsection subsec_howto_typedef Entity helpers
The header <b>entity-helper.h</b> is defining a type called EntityClassName
The header <b>entity-helper.h</b> is defining a type called EntityClassName
\section sec_howto_macros_helpers Macro helpers
\subsection subsec_howto_macros_helpers_ent Preprocessing macros for entities
<ul>
<ul>
<li> <b>DYNAMIC_GRAPH_ENTITY_DECL()</b>:
This macro creates a method <b>getClassName()</b> which returns the class name.</li>
This macro <b>should</b> be used in the declaration of the class.
</li>
</li>
<li> <b>DYNAMICGRAPH_FACTORY_ENTITY_PLUGIN(classtype,classname)</b>
This macros creates the methods necessary to have a factory building the C++ class
This macros creates the methods necessary to have a factory building the C++ class
<b>classtype</b> from the string <b>classname</b>.
This macro <b>should</b> be used in the implementation of the class.
</li>
......@@ -101,7 +101,7 @@ The header <b>entity-helper.h</b> is defining a type called EntityClassName
<li> <b>DEFINE_SIGNAL_OUT_FUNCTION(signal_name, type)</b>:
This macro is used when implementing the method specific to the output signal.
It is used in the main body of the entity class to declare the header of the method
It is used in the main body of the entity class to declare the header of the method
with the following pattern:
\code
type EntityClassName::signal_nameSOUT_function(type &, int iter)
......@@ -109,7 +109,7 @@ The header <b>entity-helper.h</b> is defining a type called EntityClassName
</li>
</ul>
<li>
<li>
</li> Inner signals
<ul>
<li> <b> DECLARE_SIGNAL_INNER(signal_name,type)</b>
......@@ -123,8 +123,8 @@ The header <b>entity-helper.h</b> is defining a type called EntityClassName
type & EntityClassName::nameSINNER_function(signal_name)(type &, int)
\endcode
</li>
<li> <b>DEFINE_SIGNAL_INNER_FUNCTION(signal_name,type)</b>
This macro is used to implement the method related to signal_name. More precisely
<li> <b>DEFINE_SIGNAL_INNER_FUNCTION(signal_name,type)</b>
This macro is used to implement the method related to signal_name. More precisely
it provides the header of the member function(i.e. method) declaration.
</li>
<li><b>DECLARE_SIGNAL_INNER_FUNCTION(signal_name,type)</b>
......
......@@ -2,5 +2,6 @@
\page subp_factory Factory
\section sec_factory Factory
The class \ref dynamicgraph::FactoryStorage is a singleton which register the entity classes and which is allowing the instancation of such classes.
The class \ref dynamicgraph::FactoryStorage is a singleton which register the entity classes and which is allowing the
instancation of such classes.
*/
......@@ -7,10 +7,11 @@ In this package, the graph considered are directed graphs.
In dynamic-graph a graph is build with:
- computational nodes which are entities \subpage subpage_entities.
- directed edges which are created by connecting input and output signals \subpage subp_signals.
- managing the nodes is done through a factory \subpage subp_factory providing classes and a way to create instances from this list of classes.
- managing the nodes is done through a factory \subpage subp_factory providing classes and a way to create instances
from this list of classes.
- the instances of node are handled through a pool \subpage subp_pool
We strongly recommend to use a scripting language such as Python to
We strongly recommend to use a scripting language such as Python to
manage the graph.
See <c>dynamic-graph-python</c> for more information on binding dynamic-graph with Python.
......
......@@ -2,7 +2,7 @@
\page subp_pool Pool
\section pool Pool
The class \ref dynamicgraph::PoolStorage keeps track of the entities instanciated with the factory.
The entities are the graph nodes. Signals are constructed during the class instanciation, they do not live independently
from the entities. Signals are the directed edges of the graph.
The pool can write a file representing the graph of entities.
The entities are the graph nodes. Signals are constructed during the class instanciation, they do not live
independently from the entities. Signals are the directed edges of the graph. The pool can write a file representing
the graph of entities.
*/
/**
/**
\page subp_references References
\section sec_refer References
......@@ -7,7 +7,8 @@ Please when referencing the Stack-Of-Tasks use the following reference:
\anchor Mansard2009
<b> <a href="https://hal-lirmm.ccsd.cnrs.fr/lirmm-00796736/document">
"A versatile Generalized Inverted Kinematics implementation for collaborative working humanoid robots: The Stack Of Tasks"</a>
"A versatile Generalized Inverted Kinematics implementation for collaborative working humanoid robots: The Stack Of
Tasks"</a>
</b>,
<em>N. Mansard, O. Stasse, P. Evrard, A. Kheddar,</em>
Int. Conf. on Autonomous Robots, ICAR, 2009
......
......@@ -4,7 +4,7 @@
//
#ifndef DYNAMIC_GRAPH_ALL_COMMANDS_H
# define DYNAMIC_GRAPH_ALL_COMMANDS_H
#define DYNAMIC_GRAPH_ALL_COMMANDS_H
// Utility header files including all commands headers
......@@ -15,4 +15,4 @@
#include <dynamic-graph/command.h>
#include <dynamic-graph/command-setter.h>
#endif //! DYNAMIC_GRAPH_ALL_COMMANDS_H
#endif //! DYNAMIC_GRAPH_ALL_COMMANDS_H
......@@ -4,12 +4,12 @@
//
#ifndef DYNAMIC_GRAPH_ALL_SIGNALS_H
# define DYNAMIC_GRAPH_ALL_SIGNALS_H
#define DYNAMIC_GRAPH_ALL_SIGNALS_H
// Utility header files including all signal headers
# include <dynamic-graph/signal.h>
# include <dynamic-graph/signal-ptr.h>
# include <dynamic-graph/signal-time-dependent.h>
#include <dynamic-graph/signal.h>
#include <dynamic-graph/signal-ptr.h>
#include <dynamic-graph/signal-time-dependent.h>
#endif //! DYNAMIC_GRAPH_ALL_SIGNALS_H
#endif //! DYNAMIC_GRAPH_ALL_SIGNALS_H
This diff is collapsed.
......@@ -20,42 +20,35 @@
/* --- GETTER --------------------------------------------------------- */
namespace dynamicgraph {
namespace command {
template <class E, typename T>
class DirectGetter
: public Command
{
public:
/// Pointer to method that sets parameter of type T
typedef T (E::*GetterMethod) () const;
/// Constructor
DirectGetter(E& entity,T* ptr,
const std::string& docString)
: Command(entity, std::vector<Value::Type>(), docString),
T_ptr(ptr) {}
protected:
virtual Value doExecute() { return Value(*T_ptr); }
private:
T* T_ptr;
};
template <class E, typename T>
DirectGetter<E,T>*
makeDirectGetter( E& entity,T* ptr,
const std::string& docString)
{ return new DirectGetter<E,T>(entity,ptr,docString); }
inline std::string docDirectGetter( const std::string& name,
const std::string& type )
{
return std::string("\nGet the ")+name+".\n\nNo input.\nReturn an "+type+".\n\n";
}
} // namespace command
} // namespace dynamicgraph
#endif // __dg_command_direct_getter_h__
namespace command {
template <class E, typename T>
class DirectGetter : public Command {
public:
/// Pointer to method that sets parameter of type T
typedef T (E::*GetterMethod)() const;
/// Constructor
DirectGetter(E& entity, T* ptr, const std::string& docString)
: Command(entity, std::vector<Value::Type>(), docString), T_ptr(ptr) {}
protected:
virtual Value doExecute() { return Value(*T_ptr); }
private:
T* T_ptr;
};
template <class E, typename T>
DirectGetter<E, T>* makeDirectGetter(E& entity, T* ptr, const std::string& docString) {
return new DirectGetter<E, T>(entity, ptr, docString);
}
inline std::string docDirectGetter(const std::string& name, const std::string& type) {
return std::string("\nGet the ") + name + ".\n\nNo input.\nReturn an " + type + ".\n\n";
}
} // namespace command
} // namespace dynamicgraph
#endif // __dg_command_direct_getter_h__
......@@ -20,45 +20,36 @@
/* --- SETTER --------------------------------------------------------- */
namespace dynamicgraph {
namespace command {
template <class E, typename T>
class DirectSetter
: public Command
{
public:
DirectSetter(E& entity,T* ptr,const std::string& docString)
:Command(entity, boost::assign::list_of(ValueHelper<T>::TypeID), docString)
,T_ptr(ptr)
{}
protected:
virtual Value doExecute()
{
const std::vector<Value>& values = getParameterValues();
T val = values[0].value();
(*T_ptr) = val;
return Value(); // void
}
private:
T* T_ptr;
};
template <class E, typename T>
DirectSetter<E,T>*
makeDirectSetter( E& entity,T* ptr,
const std::string& docString)
{ return new DirectSetter<E,T>(entity,ptr,docString); }
inline std::string docDirectSetter( const std::string& name,
const std::string& type )
{
return std::string("\nSet the ")+name+".\n\nInput:\n - a "
+type+".\nVoid return.\n\n";
}
} // namespace command
} // namespace dynamicgraph
#endif // __dg_command_direct_setter_h__
namespace command {
template <class E, typename T>
class DirectSetter : public Command {
public:
DirectSetter(E& entity, T* ptr, const std::string& docString)
: Command(entity, boost::assign::list_of(ValueHelper<T>::TypeID), docString), T_ptr(ptr) {}
protected:
virtual Value doExecute() {
const std::vector<Value>& values = getParameterValues();
T val = values[0].value();
(*T_ptr) = val;
return Value(); // void
}
private:
T* T_ptr;
};
template <class E, typename T>
DirectSetter<E, T>* makeDirectSetter(E& entity, T* ptr, const std::string& docString) {
return new DirectSetter<E, T>(entity, ptr, docString);
}
inline std::string docDirectSetter(const std::string& name, const std::string& type) {
return std::string("\nSet the ") + name + ".\n\nInput:\n - a " + type + ".\nVoid return.\n\n";
}
} // namespace command
} // namespace dynamicgraph
#endif // __dg_command_direct_setter_h__
......@@ -10,54 +10,53 @@
#include "dynamic-graph/command.h"
namespace dynamicgraph {
namespace command {
namespace command {
///
/// Command that calls a parameter getter function
///
/// This class is templated by a type E deriving from entity and
/// a type T of data.
///
/// Let us assume that class E has a private member of type T and a
/// public getter function for this member:
/// \code
/// class E : public Entity
/// {
/// public:
/// E (const std::string& inName) : Entity(inName) {}
/// T getParameter() const {return parameter_;}
/// private:
/// T parameter_;
/// };
/// \endcode
/// Then the command defined by:
/// \code
/// E entity("MyEntity");
/// Getter<E,T> command(entity, &E::getParameter)
/// \endcode
/// returns the value of <c>entity.parameter_</c> upon invocation.
///
/// \note
/// \li T should be a type supported by class Value,
/// \li prototype of E::getParameter should be exactly as specified in this
/// example.
template <class E, typename T>
class Getter : public Command {
public:
/// Pointer to method that sets parameter of type T
typedef T (E::*GetterMethod) () const;
/// Constructor
Getter(E& entity, GetterMethod getterMethod,
const std::string& docString);
///
/// Command that calls a parameter getter function
///
/// This class is templated by a type E deriving from entity and
/// a type T of data.
///
/// Let us assume that class E has a private member of type T and a
/// public getter function for this member:
/// \code
/// class E : public Entity
/// {
/// public:
/// E (const std::string& inName) : Entity(inName) {}
/// T getParameter() const {return parameter_;}
/// private:
/// T parameter_;
/// };
/// \endcode
/// Then the command defined by:
/// \code
/// E entity("MyEntity");
/// Getter<E,T> command(entity, &E::getParameter)
/// \endcode
/// returns the value of <c>entity.parameter_</c> upon invocation.
///
/// \note
/// \li T should be a type supported by class Value,
/// \li prototype of E::getParameter should be exactly as specified in this
/// example.
template <class E, typename T>
class Getter : public Command {
public:
/// Pointer to method that sets parameter of type T
typedef T (E::*GetterMethod)() const;
/// Constructor
Getter(E& entity, GetterMethod getterMethod, const std::string& docString);
protected:
virtual Value doExecute();
protected:
virtual Value doExecute();
private:
GetterMethod getterMethod_;
};
} // namespace command
} // namespace dynamicgraph
private:
GetterMethod getterMethod_;
};
} // namespace command
} // namespace dynamicgraph
#include "dynamic-graph/command-getter.t.cpp"
#endif //DYNAMIC_GRAPH_COMMAND_GETTER_H
#endif // DYNAMIC_GRAPH_COMMAND_GETTER_H
......@@ -10,25 +10,20 @@
#include <sstream>
namespace dynamicgraph {
class Entity;
namespace command {
class Entity;
namespace command {
template <class E, typename T>
Getter<E, T>::Getter(E& entity, GetterMethod getterMethod,
const std::string& docstring) :
Command(entity, std::vector<Value::Type>(), docstring),
getterMethod_(getterMethod)
{
}
template <class E, typename T>
Getter<E, T>::Getter(E& entity, GetterMethod getterMethod, const std::string& docstring)
: Command(entity, std::vector<Value::Type>(), docstring), getterMethod_(getterMethod) {}
template <class E, typename T>
Value Getter<E, T>::doExecute()
{
E& entity = static_cast<E&>(owner());
T value = (entity.*getterMethod_)();
return Value(value);
}
} // namespace command
} // namespace dynamicgraph
template <class E, typename T>
Value Getter<E, T>::doExecute() {
E& entity = static_cast<E&>(owner());
T value = (entity.*getterMethod_)();
return Value(value);
}
} // namespace command
} // namespace dynamicgraph
#endif // DYNAMIC_GRAPH_COMMAND_GETTER_T_CPP
#endif // DYNAMIC_GRAPH_COMMAND_GETTER_T_CPP
......@@ -10,54 +10,53 @@
#include "dynamic-graph/command.h"
namespace dynamicgraph {
namespace command {
namespace command {
///
/// Command that calls a parameter setter function
///
/// This class is templated by a type E deriving from entity and
/// a type T of data.
///
/// Let us assume that class E has a private member of type T and a
/// public setter function for this member:
/// \code
/// class E : public Entity
/// {
/// public:
/// E (const std::string& inName) : Entity(inName) {}
/// void setParameter(const T& parameter) {parameter_ = parameter;}
/// private:
/// T parameter_;
/// };
/// \endcode
/// Then the command defined by:
/// \code
/// E entity("MyEntity");
/// Setter<E,T> command(entity, &E::getParameter)
/// \endcode
/// sets the value of <c>entity.parameter_</c> upon invocation.
///
/// \note
/// \li T should be a type supported by class Value,
/// \li prototype of E::setParameter should be exactly as specified in this
/// example.
template <class E, typename T>
class Setter : public Command {
public:
/// Pointer to method that sets parameter of type T
typedef void (E::*SetterMethod) (const T&);