From 4841a79edace7e47a311629cafbb4896a4077fe6 Mon Sep 17 00:00:00 2001 From: Mansard <nmansard@laas.fr> Date: Thu, 27 Jan 2011 19:27:30 +0100 Subject: [PATCH] IVIGIT. --- CMakeLists.txt | 1 + include/sot-dyninv/pseudo-robot-dynamic.h | 114 +++++++ src/dynamic_graph/sot/dyninv/__init__.py | 3 + src/pseudo-robot-dynamic.cpp | 358 ++++++++++++++++++++++ 4 files changed, 476 insertions(+) create mode 100644 include/sot-dyninv/pseudo-robot-dynamic.h create mode 100644 src/pseudo-robot-dynamic.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index ccc4428..c224612 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -51,6 +51,7 @@ SET(libs dynamic-integrator solver-op-space zmp-estimator + pseudo-robot-dynamic ) LIST(APPEND LOGGING_WATCHED_TARGETS ${libs}) diff --git a/include/sot-dyninv/pseudo-robot-dynamic.h b/include/sot-dyninv/pseudo-robot-dynamic.h new file mode 100644 index 0000000..a4ede95 --- /dev/null +++ b/include/sot-dyninv/pseudo-robot-dynamic.h @@ -0,0 +1,114 @@ +/* + * Copyright 2011, Nicolas Mansard, LAAS-CNRS + * + * This file is part of sot-dyninv. + * sot-dyninv 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. + * sot-dyninv 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 Lesser General Public License for more details. You should + * have received a copy of the GNU Lesser General Public License along + * with sot-dyninv. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef __sot_dyninv_PseudoRobotDynamic_H__ +#define __sot_dyninv_PseudoRobotDynamic_H__ +/* --------------------------------------------------------------------- */ +/* --- API ------------------------------------------------------------- */ +/* --------------------------------------------------------------------- */ + +#if defined (WIN32) +# if defined (pseudo_robot_dynamic_EXPORTS) +# define SOTPSEUDOROBOTDYNAMIC_EXPORT __declspec(dllexport) +# else +# define SOTPSEUDOROBOTDYNAMIC_EXPORT __declspec(dllimport) +# endif +#else +# define SOTPSEUDOROBOTDYNAMIC_EXPORT +#endif + +/* --------------------------------------------------------------------- */ +/* --- INCLUDE --------------------------------------------------------- */ +/* --------------------------------------------------------------------- */ + + +/* SOT */ +#include <sot-dyninv/signal-helper.h> +#include <sot-dyninv/entity-helper.h> +#include <sot-dyninv/dynamic-integrator.h> + +namespace sot { + namespace dyninv { + + /* --------------------------------------------------------------------- */ + /* --- CLASS ----------------------------------------------------------- */ + /* --------------------------------------------------------------------- */ + + /* Inside this entity is an integrator, taking position, velocity and + * acceleration at time t, and computing pos and vel at time t+1. Around + * this integrator, a wrapper is made to make the stuff take the place of + * the OpenHRP kinematic entity. it thus take a "control" signal, to triger + * the computations, and possesses all the functionnalities of the OpenHRP + * entity. Plus, it has the signals to feed the OpenHRP entity that + * wrappes the simulator. All the computations are triggered by computing + * the "qdot" signal. + */ + + class SOTPSEUDOROBOTDYNAMIC_EXPORT PseudoRobotDynamic + :public DynamicIntegrator + ,public ::dynamicgraph::EntityHelper<PseudoRobotDynamic> + { + + public: /* --- CONSTRUCTOR ---- */ + + PseudoRobotDynamic( const std::string & name ); + + public: /* --- ENTITY INHERITANCE --- */ + + static const std::string CLASS_NAME; + virtual void display( std::ostream& os ) const; + virtual const std::string& getClassName( void ) const { return CLASS_NAME; } + + virtual void commandLine( const std::string& cmdLine, + std::istringstream& cmdArgs, + std::ostream& os ); + + typedef ::dynamicgraph::EntityHelper<PseudoRobotDynamic>::EntityClassName + EntityClassName; + + public: /* --- SIGNALS --- */ + + DECLARE_SIGNAL_IN( control,ml::Vector ); + DECLARE_SIGNAL_OUT( qdot,ml::Vector ); + + DECLARE_SIGNAL(rotation,OUT,ml::Vector); + DECLARE_SIGNAL(translation,OUT,ml::Vector); + //sotSignal< ml::Vector,int > rotationSOUT; + //sotSignal< ml::Vector,int > translationSOUT; + ::dynamicgraph::SignalPtr< ml::Vector,int > stateSOUT; + + public: /* --- SIGNALS --- */ + + void replaceSimulatorEntity( const std::string& formerName, + const bool& plug = false ); + void setRoot( const ml::Matrix & M ); + + public: /* --- COMMAND --- */ + template< typename T1 > + void forwardVoidCommandToSimu( const std::string& cmdName, + const T1& arg1 ); + void addForward( const std::string& cmdName ); + + private: + ::dynamicgraph::Entity* formerOpenHRP; + + }; // class PseudoRobotDynamic + } // namespace dyninv +} // namespace sot + + + +#endif // #ifndef __sot_dyninv_PseudoRobotDynamic_H__ diff --git a/src/dynamic_graph/sot/dyninv/__init__.py b/src/dynamic_graph/sot/dyninv/__init__.py index 47a35d2..484dda0 100755 --- a/src/dynamic_graph/sot/dyninv/__init__.py +++ b/src/dynamic_graph/sot/dyninv/__init__.py @@ -7,6 +7,9 @@ TaskDynPD('') from dynamic_integrator import DynamicIntegrator DynamicIntegrator('') +from pseudo_robot_dynamic import PseudoRobotDynamic +PseudoRobotDynamic('') + from solver_op_space import SolverOpSpace SolverOpSpace('') diff --git a/src/pseudo-robot-dynamic.cpp b/src/pseudo-robot-dynamic.cpp new file mode 100644 index 0000000..93e8ca0 --- /dev/null +++ b/src/pseudo-robot-dynamic.cpp @@ -0,0 +1,358 @@ +/* + * Copyright 2011, Nicolas Mansard, LAAS-CNRS + * + * This file is part of sot-dyninv. + * sot-dyninv 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. + * sot-dyninv 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 Lesser General Public License for more details. You should + * have received a copy of the GNU Lesser General Public License along + * with sot-dyninv. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <sot-dyninv/pseudo-robot-dynamic.h> +#include <sot-core/debug.h> + +#include <dynamic-graph/factory.h> +#include <dynamic-graph/pool.h> + +#include <sot-dyninv/commands-helper.h> +#include <sot-dyninv/mal-to-eigen.h> + + +namespace sot +{ + namespace dyninv + { + + namespace dg = ::dynamicgraph; + using namespace dg; + + /* --- DG FACTORY ------------------------------------------------------- */ + DYNAMICGRAPH_FACTORY_ENTITY_PLUGIN(PseudoRobotDynamic,"PseudoRobotDynamic"); + + /* --- CONSTRUCTION ----------------------------------------------------- */ + /* --- CONSTRUCTION ----------------------------------------------------- */ + /* --- CONSTRUCTION ----------------------------------------------------- */ + PseudoRobotDynamic:: + PseudoRobotDynamic( const std::string & name ) + : DynamicIntegrator(name) + + ,CONSTRUCT_SIGNAL_IN(control,ml::Vector) + ,CONSTRUCT_SIGNAL_OUT(qdot,ml::Vector,controlSIN) + + ,CONSTRUCT_SIGNAL(rotation,OUT,ml::Vector) + ,CONSTRUCT_SIGNAL(translation,OUT,ml::Vector) + ,stateSOUT( &positionSOUT,getClassName()+"("+getName()+")::output(vector)::state" ) + + ,formerOpenHRP( NULL ) + { + Entity::signalRegistration( controlSIN << qdotSOUT + << rotationSOUT << translationSOUT + << stateSOUT ); + + /* --- COMMANDS --- */ + std::string doc + = docCommandVoid2("Replace in the pool a robot entity by this," + "and modify the plugs (if 2de arg is true).", + "string (entity name)","bool (plug)"); + addCommand("replace", + makeCommandVoid2(*this,&PseudoRobotDynamic::replaceSimulatorEntity, + doc)); + doc = docCommandVoid1("Set the root position, and forward to the real simulator.", + "matrix homogeneous"); + addCommand("setRoot", + makeCommandVoid1(*this,&PseudoRobotDynamic::setRoot, + doc)); + + doc = docCommandVoid1("Add to the current entity the command of the previous simu.", + "string (command name)"); + addCommand("addForward", + makeCommandVoid1(*this,&PseudoRobotDynamic::addForward, + doc)); + + } + + /* --- SIGNALS ---------------------------------------------------------- */ + /* --- SIGNALS ---------------------------------------------------------- */ + /* --- SIGNALS ---------------------------------------------------------- */ + + /* Force the recomputation of the DynInt::controlSIN, and one step + * of the integrator. Then, export the resulting joint velocity, + * along with the 6D position of the free floating through signals + * rotationSOUT and translationSOUT. + */ + ml::Vector& PseudoRobotDynamic:: + qdotSOUT_function( ml::Vector& mlqdot, int time ) + { + sotDEBUGIN(5); + + controlSIN(time); + integrateFromSignals(time); + + EIGEN_VECTOR_FROM_SIGNAL(v,velocity ); + EIGEN_VECTOR_FROM_VECTOR( qdot,mlqdot,v.size()-6 ); + qdot = v.tail(v.size()-6); + + EIGEN_VECTOR_FROM_SIGNAL(p,position ); + { + ml::Vector mlv3; + EIGEN_VECTOR_FROM_VECTOR( r,mlv3,3 ); + r = p.segment(3,3); + rotationSOUT = mlv3; + r = p.head(3); + translationSOUT = mlv3; + } + + sotDEBUGOUT(5); + return mlqdot; + } + + /* --- TOOLS ------------------------------------------------------------- */ + /* --- TOOLS ------------------------------------------------------------- */ + /* --- TOOLS ------------------------------------------------------------- */ + + namespace PseudoRobotDynamic_Static + { + using namespace Eigen; + + template< typename D1 > + Vector3d computeEulerFromRotationMatrix ( const MatrixBase<D1> & rotation ) + { + Vector3d euler; + + double rotationMatrix00 = rotation(0,0); + double rotationMatrix10 = rotation(1,0); + double rotationMatrix20 = rotation(2,0); + double rotationMatrix01 = rotation(0,1); + double rotationMatrix11 = rotation(1,1); + double rotationMatrix21 = rotation(2,1); + double rotationMatrix02 = rotation(0,2); + double rotationMatrix12 = rotation(1,2); + double rotationMatrix22 = rotation(2,2); + + double cosTheta = sqrt(0.5 * ( rotationMatrix00*rotationMatrix00 + + rotationMatrix10*rotationMatrix10 + + rotationMatrix21*rotationMatrix21 + + rotationMatrix22*rotationMatrix22 )); + double sinTheta = -rotationMatrix20; + euler[1] = atan2 (sinTheta, cosTheta); + + double cosTheta_cosPhi = 0.5 * (rotationMatrix22 * rotationMatrix11 + - rotationMatrix21 * rotationMatrix12); + double cosTheta_sinPhi = 0.5 * (rotationMatrix21 * rotationMatrix02 + - rotationMatrix22 * rotationMatrix01); + double cosTheta_cosPsi = 0.5 * (rotationMatrix00 * rotationMatrix11 + - rotationMatrix01 * rotationMatrix10); + double cosTheta_sinPsi = 0.5 * (rotationMatrix10 * rotationMatrix02 + - rotationMatrix00 * rotationMatrix12); + + //if cosTheta == 0 + if (fabs(cosTheta) < 1e-9 ) + { + if (sinTheta > 0.5) // sinTheta ~= 1 + { + //phi_psi = phi - psi + double phi_psi = atan2(- rotationMatrix10, rotationMatrix11); + double psi = euler[2]; + + double phi = phi_psi + psi; + euler[0] = phi; + } + else //sinTheta ~= -1 + { + //phi_psi = phi + psi + double phi_psi = atan2(- rotationMatrix10, rotationMatrix11); + + double psi = euler[2]; + + double phi = phi_psi; + euler[0] = phi - psi; + } + } + else + { + double cosPsi = cosTheta_cosPsi / cosTheta; + double sinPsi = cosTheta_sinPsi / cosTheta; + euler[0] = atan2 (sinPsi, cosPsi); + + double cosPhi = cosTheta_cosPhi / cosTheta; + double sinPhi = cosTheta_sinPhi / cosTheta; + euler[2] = atan2 (sinPhi, cosPhi); + } + + return euler; + } + + } // namespace PseudoRobotDynamic_Static + + /* --- COMMANDS ---------------------------------------------------------- */ + /* --- COMMANDS ---------------------------------------------------------- */ + /* --- COMMANDS ---------------------------------------------------------- */ + + + void PseudoRobotDynamic:: + replaceSimulatorEntity( const std::string& formerName, const bool & plug ) + { + assert( formerOpenHRP == NULL ); + formerOpenHRP = &dg::g_pool.getEntity( formerName ); + dg::g_pool.deregisterEntity( formerName ); + // former.name = formerName+".old"; + dg::g_pool.registerEntity( formerName+"-old",formerOpenHRP ); + + entityDeregistration(); name = formerName; entityRegistration(); + + if( plug ) + { + formerOpenHRP->getSignal("control").plug( & qdotSOUT ); + + try + { + formerOpenHRP->getSignal("attitudeIN").plug( & rotationSOUT ); + formerOpenHRP->getSignal("translation").plug( & translationSOUT ); + } + catch (...) {} + + const ml::Vector& pos + = dynamic_cast< dg::Signal<ml::Vector,int>& > + ( formerOpenHRP->getSignal("state") ).accessCopy(); + try + { + const ml::Vector& vel + = dynamic_cast< dg::Signal<ml::Vector,int>& > + ( formerOpenHRP->getSignal("velocity") ).accessCopy(); + setState(pos,vel); + } + catch (... ) + { + ml::Vector velzero( pos.size() ); velzero.setZero(); + setState(pos,velzero); + } + } + } + void PseudoRobotDynamic:: + setRoot( const ml::Matrix & mlM ) + { + sotDEBUG(15) << "Set root with " << mlM << std::endl; + using namespace Eigen; + using PseudoRobotDynamic_Static::computeEulerFromRotationMatrix; + + EIGEN_MATRIX_FROM_SIGNAL(M,mlM); + Vector3d r = computeEulerFromRotationMatrix( M.topLeftCorner(3,3) ); + EIGEN_VECTOR_FROM_SIGNAL( q,position ); + if( q.size()<6 ) + { + throw; // TODO + } + q.head(3) = M.col(3).head(3); + q.segment(3,3) = r; + + if( formerOpenHRP ) + try + { + forwardVoidCommandToSimu( "setRoot",mlM ); + } + catch(...) {} + } + + + /* --- FORWARD ---------------------------------------------------------- */ + + /* This function is a forward on the command on the former simu entity + * <formerOpenHRP>: when calling it, the parameters are send to the named + * command, that is executed. + */ + template< typename T1 > + void PseudoRobotDynamic:: + forwardVoidCommandToSimu( const std::string& cmdName, + const T1& arg1 ) + { + /* Forward to previous entity. */ + assert( formerOpenHRP ); + + using dg::command::Command; + using dg::command::Value; + + Command* command = formerOpenHRP->getNewStyleCommand(cmdName); + std::vector<Value> valuesArg; + valuesArg.push_back( Value( arg1 ) ); + command->setParameterValues(valuesArg); + command->execute(); + } + + /* Add the named command of the former simu entity <formerOpenHRP> to the + * commands of the entity. + */ + void PseudoRobotDynamic:: + addForward( const std::string& cmdName ) + { + assert( formerOpenHRP ); + addCommand(cmdName,formerOpenHRP->getNewStyleCommand(cmdName)); + } + + + /* --- ENTITY ----------------------------------------------------------- */ + /* --- ENTITY ----------------------------------------------------------- */ + /* --- ENTITY ----------------------------------------------------------- */ + + void PseudoRobotDynamic:: + display( std::ostream& os ) const + { + os << "PseudoRobotDynamic "<<getName() << ". " << std::endl; + } + + void PseudoRobotDynamic:: + commandLine( const std::string& cmdLine, + std::istringstream& cmdArgs, + std::ostream& os ) + { + sotDEBUGIN(15); + + if( cmdLine == "help" ) + { + os << "PseudoRobotDynamic:" << std::endl + << " - replace <OpenHRP> [plug]" << std::endl; + } + else if( cmdLine == "replace" ) + { + if( cmdArgs >> std::ws, cmdArgs.good() ) + { + std::string repName; cmdArgs >> repName >> std::ws; + bool plug = cmdArgs.good(); + replaceSimulatorEntity( repName,plug ); + } + } + else if( cmdLine=="sbs" || cmdLine=="play" || cmdLine =="withForces" + || cmdLine == "periodicCall" || cmdLine == "periodicCallBefore" + || cmdLine == "periodicCallAfter" ) + { + formerOpenHRP ->commandLine( cmdLine,cmdArgs,os ); + } + else if( cmdLine=="root" ) + { + if( cmdArgs >> std::ws, cmdArgs.good() ) + { + ml::Matrix M; cmdArgs >> M; setRoot(M); + std::ostringstream osback; + osback << M.accessToMotherLib(); cmdArgs.str(osback.str()); + formerOpenHRP ->commandLine( cmdLine,cmdArgs,os ); + } + else + { + os << "TODO" << std::endl; + } + } + else + { + Entity::commandLine( cmdLine,cmdArgs,os ); + } + sotDEBUGOUT(15); + } + + } // namespace dyninv +} // namespace sot + -- GitLab