RcsPySim
A robot control and simulation library
AMDynamicalSystemActivation.cpp
Go to the documentation of this file.
1 /*******************************************************************************
2  Copyright (c) 2020, Fabio Muratore, Honda Research Institute Europe GmbH, and
3  Technical University of Darmstadt.
4  All rights reserved.
5 
6  Redistribution and use in source and binary forms, with or without
7  modification, are permitted provided that the following conditions are met:
8  1. Redistributions of source code must retain the above copyright
9  notice, this list of conditions and the following disclaimer.
10  2. Redistributions in binary form must reproduce the above copyright
11  notice, this list of conditions and the following disclaimer in the
12  documentation and/or other materials provided with the distribution.
13  3. Neither the name of Fabio Muratore, Honda Research Institute Europe GmbH,
14  or Technical University of Darmstadt, nor the names of its contributors may
15  be used to endorse or promote products derived from this software without
16  specific prior written permission.
17 
18  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21  DISCLAIMED. IN NO EVENT SHALL FABIO MURATORE, HONDA RESEARCH INSTITUTE EUROPE GMBH,
22  OR TECHNICAL UNIVERSITY OF DARMSTADT BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25  OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
26  IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28  POSSIBILITY OF SUCH DAMAGE.
29 *******************************************************************************/
30 
32 #include "ActionModelIK.h"
33 #include "../util/eigen_matnd.h"
34 
35 #include <Rcs_macros.h>
36 
37 #include <utility>
38 
39 
40 namespace Rcs
41 {
42 
44  ActionModel* wrapped, std::vector<DynamicalSystem*> ds, TaskCombinationMethod tcm)
45  : ActionModel(wrapped->getGraph()), wrapped(wrapped), dynamicalSystems(std::move(ds)), taskCombinationMethod(tcm)
46 {
47  activation = MatNd_create((unsigned int) dynamicalSystems.size(), 1);
48 }
49 
51 {
52  delete wrapped;
53  MatNd_destroy(activation);
54  for (auto* ds : dynamicalSystems) {
55  delete ds;
56  }
57 }
58 
60 {
61  return (unsigned int) dynamicalSystems.size();
62 }
63 
64 void AMDynamicalSystemActivation::getMinMax(double* min, double* max) const
65 {
66  // All activations are between -1 and 1
67  for (unsigned int i = 0; i < getDim(); i++) {
68  min[i] = -1;
69  max[i] = 1;
70  }
71 }
72 
73 std::vector<std::string> AMDynamicalSystemActivation::getNames() const
74 {
75  std::vector<std::string> names;
76  for (unsigned int i = 0; i < getDim(); ++i) {
77  names.push_back("a_" + std::to_string(i));
78  }
79  return names;
80 }
81 
83  MatNd* q_des, MatNd* q_dot_des, MatNd* T_des, const MatNd* action, double dt)
84 {
85  RCHECK(action->n == 1); // actions are column vectors
86 
87  // Remember x_dot from last step as integration input.
88  Eigen::VectorXd x_dot_old = x_dot;
89  x_dot.setConstant(0);
90 
91  // Collect data from each DS
92  for (unsigned int i = 0; i < getDim(); ++i) {
93  // Fill a temp x_dot with the old x_dot
94  Eigen::VectorXd x_dot_ds = x_dot_old;
95 
96  // Step the DS
97  dynamicalSystems[i]->step(x_dot_ds, x, dt);
98  // Remember x_dot for OMDynamicalSystemDiscrepancy
99  dynamicalSystems[i]->x_dot_des = x_dot_ds;
100 
101  // Combine the individual x_dot of every DS
102  switch (taskCombinationMethod) {
105  x_dot += action->ele[i]*x_dot_ds;
106  MatNd_set(activation, i, 0, action->ele[i]);
107  break;
108  }
109 
111  MatNd* a = NULL;
112  MatNd_create2(a, action->m, action->n);
113  MatNd_softMax(a, action, action->m); // action->m is a neat heuristic for beta
114  x_dot += MatNd_get(a, i, 0)*x_dot_ds;
115 
116  MatNd_set(activation, i, 0, MatNd_get(a, i, 0));
117  MatNd_destroy(a);
118  break;
119  }
120 
122  // Create temp matrix
123  MatNd* otherActions = NULL; // other actions are all actions without the current
124  MatNd_clone2(otherActions, action);
125  MatNd_deleteRow(otherActions, i);
126 
127  // Treat the actions as probability of events and compute the probability that all other actions are false
128  double prod = 1; // 1 is the neutral element for multiplication
129  for (unsigned int idx = 0; idx < otherActions->m; idx++) {
130  REXEC(7) {
131  std::cout << "factor " << (1 - otherActions->ele[idx]) << std::endl;
132  }
133  // One part of the product is always 1
134  prod *= (1 - otherActions->ele[idx]);
135  }
136  REXEC(7) {
137  std::cout << "prod " << prod << std::endl;
138  }
139 
140  x_dot += action->ele[i]*prod*x_dot_ds;
141  MatNd_set(activation, i, 0, action->ele[i]*prod);
142 
143  MatNd_destroy(otherActions);
144  break;
145  }
146  }
147 
148  // Print if debug level is exceeded
149  REXEC(5) {
150  std::cout << "action DS " << i << " = " << action->ele[i] << std::endl;
151  std::cout << "x_dot DS " << i << " =" << std::endl << x_dot_ds << std::endl;
152  }
153  }
154 
156 
157  double normalizer = MatNd_getNormL1(action) + 1e-8;
158  x_dot /= normalizer;
159  MatNd_constMulSelf(activation, 1./normalizer);
160  }
161 
162  // Integrate to x
163  x += x_dot*dt;
164 
165  // Pass x to wrapped action model
166  MatNd x_rcs = viewEigen2MatNd(x);
167 
168  // Compute the joint angle positions (joint angle velocities, and torques)
169  wrapped->computeCommand(q_des, q_dot_des, T_des, &x_rcs, dt);
170 
171  // Print if debug level is exceeded
172  REXEC(5) {
173  std::cout << "x_dot (combined MP) =\n" << x_dot << std::endl;
174  std::cout << "x (combined MP) =\n" << x << std::endl;
175  }
176  REXEC(7) {
177  MatNd_printComment("q_des", q_des);
178  MatNd_printComment("q_dot_des", q_dot_des);
179  if (T_des) {
180  MatNd_printComment("T_des", T_des);
181  }
182  }
183 }
184 
186 {
187  wrapped->reset();
188  // Initialize shapes
189  x.setZero(wrapped->getDim());
190  x_dot.setZero(wrapped->getDim());
191 
192  // Obtain current stable action from wrapped action model
193  MatNd x_rcs = viewEigen2MatNd(x);
194  wrapped->getStableAction(&x_rcs);
195 }
196 
198 {
199  // All zero activations is stable
200  MatNd_setZero(action);
201 }
202 
203 Eigen::VectorXd AMDynamicalSystemActivation::getX() const
204 {
205  return x;
206 }
207 
209 {
210  return x_dot;
211 }
212 
214 {
215  return wrapped;
216 }
217 
218 const std::vector<DynamicalSystem*>& AMDynamicalSystemActivation::getDynamicalSystems() const
219 {
220  return dynamicalSystems;
221 }
222 
224 {
225  std::vector<DynamicalSystem*> dsvc;
226  for (auto ds : dynamicalSystems) {
227  dsvc.push_back(ds->clone());
228  }
229 
230  return new AMDynamicalSystemActivation(wrapped->clone(newGraph), dsvc, taskCombinationMethod);
231 }
232 
234 {
236  if (tcmName == "sum") {
238  }
239  else if (tcmName == "mean") {
241  }
242  else if (tcmName == "softmax") {
244  }
245  else if (tcmName == "product") {
247  }
248  else {
249  std::ostringstream os;
250  os << "Unsupported task combination method: " << tcmName << "! Supported methods: sum, mean, softmax, product.";
251  throw std::invalid_argument(os.str());
252  }
253  return tcm;
254 }
255 
257 {
259  return "sum";
260  }
262  return "mean";
263  }
265  return "softmax";
266  }
268  return "product";
269  }
270  else {
271  return nullptr;
272  }
273 }
274 
276 {
277  return activation;
278 }
279 
280 } /* namespace Rcs */
281 
virtual std::vector< std::string > getNames() const
virtual void getStableAction(MatNd *action) const
Eigen::VectorXd x
Current state in task space.
virtual unsigned int getDim() const
Get the number of DS, i.e. entries in the dynamicalSystems vector, owned by the action model...
virtual void computeCommand(MatNd *q_des, MatNd *q_dot_des, MatNd *T_des, const MatNd *action, double dt)=0
static TaskCombinationMethod checkTaskCombinationMethod(std::string tcmName)
TaskCombinationMethod taskCombinationMethod
Way to combine the tasks&#39; contribution.
TaskCombinationMethod
Definition: ActionModel.h:46
std::vector< DynamicalSystem * > dynamicalSystems
List of dynamical systems.
ActionModel * wrapped
Wrapped action model.
virtual ActionModel * getWrappedActionModel() const
MatNd * activation
The activation resulting from the action and the task combination method (used for logging) ...
virtual void computeCommand(MatNd *q_des, MatNd *q_dot_des, MatNd *T_des, const MatNd *action, double dt)
AMDynamicalSystemActivation(ActionModel *wrapped, std::vector< DynamicalSystem *> ds, TaskCombinationMethod tcm)
virtual void getMinMax(double *min, double *max) const
virtual void reset()
Definition: ActionModel.cpp:49
ActionModel * clone() const
Definition: ActionModel.h:72
Eigen::VectorXd x_dot
Current velocity in task space.
virtual unsigned int getDim() const =0
virtual void getStableAction(MatNd *action) const =0
const std::vector< DynamicalSystem * > & getDynamicalSystems() const
Get a vector of the owned dynamical systems.
MatNd viewEigen2MatNd(M &src)
Definition: eigen_matnd.h:48