Commit 4729f7e5 authored by Guilhem Saurel's avatar Guilhem Saurel
Browse files

Format

parent 3f9b9bc6
......@@ -74,7 +74,7 @@ Setters and getters will enable us later to control parameters through commands.
double getPendulumLength () const {
return pendulumLength_;
}
}
\endcode
The name of the class is stored as a static member
......@@ -160,14 +160,14 @@ We set input and output signal as constant with a given value
\endcode
The following lines of code define and register commands into the entity.
A \ref dynamicgraph::command::Command "command" is created by calling a constructor with
A \ref dynamicgraph::command::Command "command" is created by calling a constructor with
\li a string: the name of the command,
\li a pointer to a newly created command and
\li a string documenting the command:
\code
std::string docstring;
// Incr
docstring =
"\n"
......@@ -182,34 +182,35 @@ A \ref dynamicgraph::command::Command "command" is created by calling a construc
In this example, command::Increment is a command specific to our class
InvertedPendulum. This new command is explained in page \ref dg_tutorial_inverted_pendulum_command.
Setter and getter commands are available through classes templated by the type of entity using the command and the type of the parameter. Be aware that only a prespecified set of types are supported for commands, see class dynamicgraph::command::Value.
\code
docstring =
Setter and getter commands are available through classes templated by the type of entity using the command and the type
of the parameter. Be aware that only a prespecified set of types are supported for commands, see class
dynamicgraph::command::Value. \code docstring =
"\n"
" Set cart mass\n"
"\n";
addCommand(std::string("setCartMass"),
new ::dynamicgraph::command::Setter<InvertedPendulum, double>
(*this, &InvertedPendulum::setCartMass, docstring));
new ::dynamicgraph::command::Setter<InvertedPendulum, double>
(*this, &InvertedPendulum::setCartMass, docstring));
docstring =
"\n"
" Get cart mass\n"
"\n";
addCommand(std::string("getCartMass"),
new ::dynamicgraph::command::Getter<InvertedPendulum, double>
(*this, &InvertedPendulum::getCartMass, docstring));
new ::dynamicgraph::command::Getter<InvertedPendulum, double>
(*this, &InvertedPendulum::getCartMass, docstring));
\endcode
\note
It is important to notice that
\li commands passed to method Entity::addCommand will be destroyed automatically by Entity class destructor. The user should therefore not destroy them,
\li commands should be defined and registered in the class constructor. Commands defined later on will not be reachable by python bindings.
\li commands passed to method Entity::addCommand will be destroyed automatically by Entity class destructor. The user
should therefore not destroy them, \li commands should be defined and registered in the class constructor. Commands
defined later on will not be reachable by python bindings.
\subsection dg_tutorial_inverted_pendulum_cxx_implementation_newtypes Registering new types: advanced feature
Signals are templated by the type of data they convey. In this example, we hae defined our own class of vectors InvertedPendulum::Vector. In order to be able to create signals with this type, we need to register the new type:
\code
Signals are templated by the type of data they convey. In this example, we hae defined our own class of vectors
InvertedPendulum::Vector. In order to be able to create signals with this type, we need to register the new type: \code
dynamicgraph::DefaultCastRegisterer<InvertedPendulum::Vector> IPVectorCast;
\endcode
......
......@@ -6,7 +6,7 @@
Command (dynamicgraph::command::Command) are objects that encapsulate an
action to be performed on an entity.
In this page, we define a new command that will call method
In this page, we define a new command that will call method
InvertedPendulum::incr. The source code is in
<c>src/command-increment.hh</c>.
......@@ -25,12 +25,11 @@ The constructor takes
\li a reference to a InvertedPendulum and calls parent class,
\li a vector a types specifying the number and types of input arguments of the command and
\li a string documenting the command.
In this case, there is only one argument of type <c>double</c>. Note the use of <c>boost::assign::list_of</c> to build a vector in one command line:
\code
Increment(InvertedPendulum& entity, const std::string& docstring) :
Command(entity, boost::assign::list_of(Value::DOUBLE), docstring)
{
}
In this case, there is only one argument of type <c>double</c>. Note the use of <c>boost::assign::list_of</c> to build
a vector in one command line: \code Increment(InvertedPendulum& entity, const std::string& docstring) : Command(entity,
boost::assign::list_of(Value::DOUBLE), docstring)
{
}
\endcode
We then define the action of the command in virtual method <c>doExecute</c>.
......@@ -38,7 +37,7 @@ We need to get a reference to the object on which the command will act. Note
that we can straightfowardly statically cast in <c>InvertedPendulum</c> the
Entity object returned by method <c>owner</c>:
\code
virtual Value doExecute()
virtual Value doExecute()
{
Entity& entity = owner();
InvertedPendulum& ip = static_cast<InvertedPendulum&>(entity);
......
......@@ -3,15 +3,15 @@
\section dg_tutorial_inverted_pendulum_python_intro Introduction
Generating python bindings for new Entity classes is straightforward. We only need to add the following lines into file <c>src/CMakeLists.txt</c>:
Generating python bindings for new Entity classes is straightforward. We only need to add the following lines into file
<c>src/CMakeLists.txt</c>:
<code>
DYNAMIC_GRAPH_PYTHON_MODULE("tutorial" ${LIBRARY_NAME} wrap)
</code>
This will create and install a python module called <c>dynamic_graph.tutorial</c>, linked with library <c>${LIBRARY_NAME} (libdynamic-graph-tutorial.so)</c>.
When importing this module, two new python classes deriving from <c>Entity</c> are created:
\li InvertedPendulum, and
\li FeedbackController.
\sa <c>src/simu.py</c> for an example python script.
This will create and install a python module called <c>dynamic_graph.tutorial</c>, linked with library
<c>${LIBRARY_NAME} (libdynamic-graph-tutorial.so)</c>. When importing this module, two new python classes deriving from
<c>Entity</c> are created: \li InvertedPendulum, and \li FeedbackController. \sa <c>src/simu.py</c> for an example
python script.
*/
......@@ -3,9 +3,10 @@
\section intro_dg_tutorial Introduction
This tutorial implements a simple application of the dynamic-graph package with two entities represented by the following classes:
\li dynamicgraph::tutorial::InvertedPendulum: that implements the dynamics of a pendulum on a cart and
\li dynamicgraph::tutorial::FeedbackController: that implements a closed-loop control loop that stabilizes the pendulum.
This tutorial implements a simple application of the dynamic-graph package with two entities represented by the
following classes: \li dynamicgraph::tutorial::InvertedPendulum: that implements the dynamics of a pendulum on a cart
and \li dynamicgraph::tutorial::FeedbackController: that implements a closed-loop control loop that stabilizes the
pendulum.
\section dg_tutorial_inverted_pendulum_ Prerequisite
......@@ -17,8 +18,8 @@ This tutorial requires prior installation of packages:
This tutorial show:
\li how to \ref dg_tutorial_inverted_pendulum_cxx "create a new entity" with signals and commands,
\li how to \ref dg_tutorial_inverted_pendulum_python "build a python module" to create and control this entity in a python
interpreter.
\li how to \ref dg_tutorial_inverted_pendulum_python "build a python module" to create and control this entity in a
python interpreter.
*/
......@@ -13,80 +13,72 @@
#include <dynamic-graph/linear-algebra.h>
namespace dynamicgraph {
namespace tutorial {
/**
\brief Feedback controller for an inverted pendulum
namespace tutorial {
/**
\brief Feedback controller for an inverted pendulum
This class implements a feedback control for the inverted pendulum
represented by class InvertedPendulum
*/
class FeedbackController : public Entity
{
public:
/**
\brief Constructor by name
*/
FeedbackController(const std::string& inName);
This class implements a feedback control for the inverted pendulum
represented by class InvertedPendulum
*/
class FeedbackController : public Entity {
public:
/**
\brief Constructor by name
*/
FeedbackController(const std::string& inName);
~FeedbackController();
~FeedbackController();
/// Each entity should provide the name of the class it belongs to
virtual const std::string& getClassName (void) const {
return CLASS_NAME;
}
/// Each entity should provide the name of the class it belongs to
virtual const std::string& getClassName(void) const { return CLASS_NAME; }
/// Header documentation of the python class
virtual std::string getDocString () const {
return
"Feedback controller aimed at maintaining the pendulum vertical\n";
}
/**
\name Parameters
@{
*/
/**
\brief Get feedback gain
*/
void setGain (const ::dynamicgraph::Matrix& inGain) {
gain_ = inGain;
}
/// Header documentation of the python class
virtual std::string getDocString() const {
return "Feedback controller aimed at maintaining the pendulum vertical\n";
}
/**
\name Parameters
@{
*/
/**
\brief Get feedback gain
*/
void setGain(const ::dynamicgraph::Matrix& inGain) { gain_ = inGain; }
/**
\brief Get feedback gain
*/
::dynamicgraph::Matrix getGain () const {
return gain_;
}
/**
\brief Get feedback gain
*/
::dynamicgraph::Matrix getGain() const { return gain_; }
/**
@}
*/
/**
@}
*/
protected:
/*
\brief Class name
*/
static const std::string CLASS_NAME;
protected:
/*
\brief Class name
*/
static const std::string CLASS_NAME;
private:
/**
Compute the control law
*/
double& computeForceFeedback(double& force, const int& inTime);
private:
/**
Compute the control law
*/
double& computeForceFeedback(double& force, const int& inTime);
/**
\brief State of the inverted pendulum
*/
SignalPtr < ::dynamicgraph::Vector, int> stateSIN;
/**
\brief Force computed by the control law
*/
SignalTimeDependent < double, int > forceSOUT;
/**
\brief State of the inverted pendulum
*/
SignalPtr< ::dynamicgraph::Vector, int> stateSIN;
/**
\brief Force computed by the control law
*/
SignalTimeDependent<double, int> forceSOUT;
/// \brief Gain of the controller
::dynamicgraph::Matrix gain_;
};
} // namespace tutorial
} // namespace dynamicgraph
/// \brief Gain of the controller
::dynamicgraph::Matrix gain_;
};
} // namespace tutorial
} // namespace dynamicgraph
#endif //DG_TUTORIAL_FEEDBACK_CONTROLLER_HH
#endif // DG_TUTORIAL_FEEDBACK_CONTROLLER_HH
......@@ -14,167 +14,148 @@
#include <dynamic-graph/linear-algebra.h>
namespace dynamicgraph {
namespace tutorial {
/**
\brief Inverted Pendulum on a cart
This class represents the classical inverted pendulum on a cart.
The equation of motion is:
\f{eqnarray*}{
\left ( M + m \right ) \ddot x - m l \ddot \theta \cos \theta + m l \dot \theta^2 \sin \theta &=& F\\
m l (-g \sin \theta - \ddot x \cos \theta + l \ddot \theta) &=& 0
\f}
where
\li the state is a vector of dimension 4
\f$(x,\theta,\dot{x},\dot{\theta})\f$ represented by signal
stateSOUT,
\li \f$x\f$ is the position of the cart on an horizontal axis,
\f$\theta\f$ is the angle of the pendulum with respect to the
vertical axis,
\li the input is a vector of dimension 1 \f$(F)\f$ reprensented by signal
forceSIN,
\li m, M and l are respectively the mass of the pendulum, the mass of the
cart and the length of the pendulum.
A more natural form of the above equation for roboticists is
\f[
\textbf{M}(\textbf{q})\ddot{\textbf{q}} +
\textbf{N}(\textbf{q},\dot{\textbf{q}})\dot{\textbf{q}} +
\textbf{G}(\textbf{q}) = \textbf{F}
\f]
where
\f{eqnarray*}
\textbf{q} &=& (x, \theta) \\
\textbf{M}(\textbf{q}) &=& \left( \begin{array}{cc}
M + m & -m\ l\ \cos\theta \\
-m\ l\ \cos\theta & m\ l^2 \end{array}\right) \\
\textbf{N}(\textbf{q},\dot{\textbf{q}}) &=& \left( \begin{array}{cc}
0 & m\ l\ \dot{\theta} \sin\theta \\
0 & 0 \end{array}\right)\\
\textbf{G}(\textbf{q}) &=& \left( \begin{array}{c}
0 \\ -m\ l\ g\ \sin\theta \end{array}\right)\\
\textbf{F} &=& \left( \begin{array}{c}
F \\ 0 \end{array}\right)
\f}
In order to make the system intrinsically stable, we add some viscosity
by rewriting:
\f{eqnarray*}
\textbf{N}(\textbf{q},\dot{\textbf{q}}) &=& \left( \begin{array}{cc}
\lambda & m\ l\ \dot{\theta} \sin\theta\\
0 & \lambda \end{array}\right)
\f}
where \f$\lambda\f$ is a positive coefficient.
*/
class InvertedPendulum : public Entity
{
public:
/**
\brief Constructor by name
*/
InvertedPendulum(const std::string& inName);
~InvertedPendulum();
/// Each entity should provide the name of the class it belongs to
virtual const std::string& getClassName (void) const {
return CLASS_NAME;
}
/// Header documentation of the python class
virtual std::string getDocString () const {
return
"Classical inverted pendulum dynamic model\n";
}
/// Integrate equation of motion over time step given as input
void incr(double inTimeStep);
/**
\name Parameters
@{
*/
/**
\brief Set the mass of the cart
*/
void setCartMass (const double& inMass) {
cartMass_ = inMass;
}
/**
\brief Get the mass of the cart
*/
double getCartMass () const {
return cartMass_;
}
/**
\brief Set the mass of the cart
*/
void setPendulumMass (const double& inMass) {
pendulumMass_ = inMass;
}
/**
\brief Get the mass of the pendulum
*/
double getPendulumMass () const {
return pendulumMass_;
}
/**
\brief Set the length of the cart
*/
void setPendulumLength (const double& inLength) {
pendulumLength_ = inLength;
}
/**
\brief Get the length of the pendulum
*/
double getPendulumLength () const {
return pendulumLength_;
}
/**
@}
*/
protected:
/*
\brief Class name
*/
static const std::string CLASS_NAME;
private:
/**
\brief Input force acting on the inverted pendulum
*/
SignalPtr< double, int > forceSIN;
/**
\brief State of the inverted pendulum
*/
Signal< ::dynamicgraph::Vector, int> stateSOUT;
/// \brief Mass of the cart
double cartMass_;
/// \brief Mass of the pendulum
double pendulumMass_;
/// \brief Length of the pendulum
double pendulumLength_;
/// \brief Viscosity coefficient
double viscosity_;
/**
\brief Compute the evolution of the state of the pendulum
*/
::dynamicgraph::Vector
computeDynamics(const ::dynamicgraph::Vector& inState,
const double& inControl, double inTimeStep);
};
} // namespace tutorial
} // namespace dynamicgraph
namespace tutorial {
/**
\brief Inverted Pendulum on a cart
This class represents the classical inverted pendulum on a cart.
The equation of motion is:
\f{eqnarray*}{
\left ( M + m \right ) \ddot x - m l \ddot \theta \cos \theta + m l \dot \theta^2 \sin \theta &=& F\\
m l (-g \sin \theta - \ddot x \cos \theta + l \ddot \theta) &=& 0
\f}
where
\li the state is a vector of dimension 4
\f$(x,\theta,\dot{x},\dot{\theta})\f$ represented by signal
stateSOUT,
\li \f$x\f$ is the position of the cart on an horizontal axis,
\f$\theta\f$ is the angle of the pendulum with respect to the
vertical axis,
\li the input is a vector of dimension 1 \f$(F)\f$ reprensented by signal
forceSIN,
\li m, M and l are respectively the mass of the pendulum, the mass of the
cart and the length of the pendulum.
A more natural form of the above equation for roboticists is
\f[
\textbf{M}(\textbf{q})\ddot{\textbf{q}} +
\textbf{N}(\textbf{q},\dot{\textbf{q}})\dot{\textbf{q}} +
\textbf{G}(\textbf{q}) = \textbf{F}
\f]
where
\f{eqnarray*}
\textbf{q} &=& (x, \theta) \\
\textbf{M}(\textbf{q}) &=& \left( \begin{array}{cc}
M + m & -m\ l\ \cos\theta \\
-m\ l\ \cos\theta & m\ l^2 \end{array}\right) \\
\textbf{N}(\textbf{q},\dot{\textbf{q}}) &=& \left( \begin{array}{cc}
0 & m\ l\ \dot{\theta} \sin\theta \\
0 & 0 \end{array}\right)\\
\textbf{G}(\textbf{q}) &=& \left( \begin{array}{c}
0 \\ -m\ l\ g\ \sin\theta \end{array}\right)\\
\textbf{F} &=& \left( \begin{array}{c}
F \\ 0 \end{array}\right)
\f}
In order to make the system intrinsically stable, we add some viscosity
by rewriting:
\f{eqnarray*}
\textbf{N}(\textbf{q},\dot{\textbf{q}}) &=& \left( \begin{array}{cc}
\lambda & m\ l\ \dot{\theta} \sin\theta\\
0 & \lambda \end{array}\right)
\f}
where \f$\lambda\f$ is a positive coefficient.
*/
class InvertedPendulum : public Entity {
public:
/**
\brief Constructor by name
*/
InvertedPendulum(const std::string& inName);
~InvertedPendulum();
/// Each entity should provide the name of the class it belongs to
virtual const std::string& getClassName(void) const { return CLASS_NAME; }
/// Header documentation of the python class
virtual std::string getDocString() const { return "Classical inverted pendulum dynamic model\n"; }
/// Integrate equation of motion over time step given as input
void incr(double inTimeStep);
/**
\name Parameters
@{
*/
/**
\brief Set the mass of the cart
*/
void setCartMass(const double& inMass) { cartMass_ = inMass; }
/**
\brief Get the mass of the cart
*/
double getCartMass() const { return cartMass_; }
/**
\brief Set the mass of the cart
*/
void setPendulumMass(const double& inMass) { pendulumMass_ = inMass; }
/**
\brief Get the mass of the pendulum
*/
double getPendulumMass() const { return pendulumMass_; }
/**
\brief Set the length of the cart
*/
void setPendulumLength(const double& inLength) { pendulumLength_ = inLength; }
/**
\brief Get the length of the pendulum
*/
double getPendulumLength() const { return pendulumLength_; }
/**
@}
*/
protected:
/*
\brief Class name
*/
static const std::string CLASS_NAME;
private:
/**
\brief Input force acting on the inverted pendulum
*/
SignalPtr<double, int> forceSIN;
/**
\brief State of the inverted pendulum
*/
Signal< ::dynamicgraph::Vector, int> stateSOUT;
/// \brief Mass of the cart
double cartMass_;
/// \brief Mass of the pendulum
double pendulumMass_;
/// \brief Length of the pendulum
double pendulumLength_;
/// \brief Viscosity coefficient
double viscosity_;
/**
\brief Compute the evolution of the state of the pendulum
*/
::dynamicgraph::Vector computeDynamics(const ::dynamicgraph::Vector& inState, const double& inControl,
double inTimeStep);
};
} // namespace tutorial
} // namespace dynamicgraph
#endif
......@@ -10,32 +10,28 @@
#include <boost/assign/list_of.hpp>
namespace dynamicgraph {
namespace tutorial {
namespace command {
using ::dynamicgraph::command::Command;