NTRT Simulator  v1.1
 All Classes Namespaces Files Functions Variables Typedefs Friends Pages
LearningSpineSine.cpp
1 /*
2  * Copyright © 2012, United States Government, as represented by the
3  * Administrator of the National Aeronautics and Space Administration.
4  * All rights reserved.
5  *
6  * The NASA Tensegrity Robotics Toolkit (NTRT) v1 platform is licensed
7  * under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  * http://www.apache.org/licenses/LICENSE-2.0.
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
15  * either express or implied. See the License for the specific language
16  * governing permissions and limitations under the License.
17 */
18 
28 #include "LearningSpineSine.h"
29 
30 #include <string>
31 
32 
33 // Should include tgString, but compiler complains since its been
34 // included from TetraSpineLearningModel. Perhaps we should move things
35 // to a cpp over there
37 #include "core/tgBasicActuator.h"
39 
42 
43 #include "tgSineStringControl.h"
44 
45 using namespace std;
46 
53  std::string args,
54  std::string ec,
55  std::string nc) :
56 BaseSpineCPGControl(config, args)
57 
58 {
59 }
60 
62 {
63  //Initialize the Learning Adapters
64  nodeAdapter.initialize(&nodeEvolution,
65  nodeLearning,
66  nodeConfigData);
67  edgeAdapter.initialize(&edgeEvolution,
68  edgeLearning,
69  edgeConfigData);
70  /* Empty vector signifying no state information
71  * All parameters are stateless parameters, so we can get away with
72  * only doing this once
73  */
74  std::vector<double> state;
75  double dt = 0;
76 
77  array_2D edgeParams = scalePhaseActions(edgeAdapter.step(dt, state));
78  array_2D nodeParams = scaleNodeActions(nodeAdapter.step(dt, state));
79 
80  setupWaves(subject, nodeParams, edgeParams);
81 
82  initConditions = subject.getSegmentCOM(m_config.segmentNumber);
83 #if (0) // Conditional compile for data logging
84  m_dataObserver.onSetup(subject);
85 #endif
86 
87 
88  m_updateTime = 0.0;
89 }
90 
92 {
94  m_updateTime += dt;
95  if (m_updateTime >= m_config.controlTime)
96  {
97 
98 #if (0) // Conditional compile for data logging
99  m_dataObserver.onStep(subject, m_updateTime);
100 #endif
101  notifyStep(m_updateTime);
102  m_updateTime = 0;
103  }
104 }
105 
107 {
108  std::vector<double> scores;
109  // @todo - check to make sure we ran for the right amount of time
110 
111  std::vector<double> finalConditions = subject.getSegmentCOM(m_config.segmentNumber);
112 
113  const double newX = finalConditions[0];
114  const double newZ = finalConditions[2];
115  const double oldX = initConditions[0];
116  const double oldZ = initConditions[2];
117 
118  const double distanceMoved = sqrt((newX-oldX) * (newX-oldX) +
119  (newZ-oldZ) * (newZ-oldZ));
120 
121  scores.push_back(distanceMoved);
122 
125  double totalEnergySpent=0;
126 
127  vector<tgSpringCableActuator* > tmpSCAs = subject.getAllMuscles();
128  vector<tgBasicActuator* > tmpStrings = tgCast::filter<tgSpringCableActuator, tgBasicActuator>(tmpSCAs);
129  for(int i=0; i<tmpStrings.size(); i++)
130  {
131  tgSpringCableActuator::SpringCableActuatorHistory stringHist = tmpStrings[i]->getHistory();
132 
133  for(int j=1; j<stringHist.tensionHistory.size(); j++)
134  {
135  const double previousTension = stringHist.tensionHistory[j-1];
136  const double previousLength = stringHist.restLengths[j-1];
137  const double currentLength = stringHist.restLengths[j];
138  //TODO: examine this assumption - free spinning motor may require more power
139  double motorSpeed = (currentLength-previousLength);
140  if(motorSpeed > 0) // Vestigial code
141  motorSpeed = 0;
142  const double workDone = previousTension * motorSpeed;
143  totalEnergySpent += workDone;
144  }
145  }
146 
147  scores.push_back(totalEnergySpent);
148 
149  edgeAdapter.endEpisode(scores);
150  nodeAdapter.endEpisode(scores);
151 
152  for(size_t i = 0; i < m_sineControllers.size(); i++)
153  {
154  delete m_sineControllers[i];
155  }
156  m_sineControllers.clear();
157  m_allControllers.clear();
158 }
159 
160 void LearningSpineSine::setupWaves(BaseSpineModelLearning& subject, array_2D nodeActions, array_2D edgeActions)
161 {
162  std::vector <tgSpringCableActuator*> allMuscles = subject.getAllMuscles();
163 
164  double tension;
165  double kPosition;
166  double kVelocity;
167  double controlLength;
168 
169  for (std::size_t i = 0; i < allMuscles.size(); i++)
170  {
171  if (allMuscles[i]->hasTag("inner top"))
172  {
173  tension = 2000.0;
174  kPosition = 500.0;
175  kVelocity = 100.0;
176  controlLength = allMuscles[i]->getStartLength();
177  }
178  else if (allMuscles[i]->hasTag("outer top"))
179  {
180  tension = 1000.0;
181  kPosition = 500.0;
182  kVelocity = 100.0;
183  controlLength = 19.5;
184  }
185  else if (allMuscles[i]->hasTag("inner"))
186  {
187  tension = 1500.0;
188  kPosition = 100.0;
189  kVelocity = 100.0;
190  controlLength = allMuscles[i]->getStartLength();
191  }
192  else if (allMuscles[i]->hasTag("outer"))
193  {
194  tension = 800.0;
195  kPosition = 100.0;
196  kVelocity = 100.0;
197  controlLength = 19.5 ;
198  }
199  else
200  {
201  throw std::runtime_error("Missing tags!");
202  }
203 
204  tgImpedanceController* p_ipc = new tgImpedanceController( tension,
205  kPosition,
206  kVelocity);
207 
208  tgSineStringControl* pStringControl = new tgSineStringControl(m_config.controlTime,
209  p_ipc,
210  nodeActions[0][0],
211  nodeActions[0][1],
212  edgeActions[i][0],
213  0.0, // Repeat learning this too? Unlikely to be helpful
214  controlLength);
215 
216 
217  allMuscles[i]->attach(pStringControl);
218  m_sineControllers.push_back(pStringControl);
219  }
220 
221  assert(m_sineControllers.size() == allMuscles.size());
222 
223 
224 
225 
226 }
227 
229  (vector< vector <double> > actions)
230 {
231  std::size_t numControllers = edgeConfigData.getintvalue("numberOfControllers");
232  std::size_t numActions = edgeConfigData.getintvalue("numberOfActions");
233 
234  assert( actions.size() == numControllers);
235  assert( actions[0].size() == numActions);
236 
237  array_2D edgeActions(boost::extents[numControllers][numActions]);
238 
239  array_2D limits(boost::extents[2][numActions]);
240 
241  // Check if we need to update limits
242  assert(numActions == 1);
243 
244 
245  limits[0][0] = m_config.lowPhase;
246  limits[1][0] = m_config.highPhase;
247 
248  // This one is square
249  for( std::size_t i = 0; i < numControllers; i++)
250  {
251  for( std::size_t j = 0; j < numActions; j++)
252  {
253  edgeActions[i][j] = ( actions[i][j] *
254  (limits[1][j] - limits[0][j])) + limits[0][j];
255  }
256  }
257 
258  return edgeActions;
259 }
260 
261 array_2D LearningSpineSine::scaleNodeActions
262  (vector< vector <double> > actions)
263 {
264  std::size_t numControllers = nodeConfigData.getintvalue("numberOfControllers");
265  std::size_t numActions = nodeConfigData.getintvalue("numberOfActions");
266 
267  assert( actions.size() == numControllers);
268  assert( actions[0].size() == numActions);
269 
270  array_2D nodeActions(boost::extents[numControllers][numActions]);
271 
272  array_2D limits(boost::extents[2][numActions]);
273 
274  // Check if we need to update limits
275  assert(numActions == 2);
276 
277 
278  limits[0][0] = m_config.lowAmp;
279  limits[1][0] = m_config.highAmp;
280  limits[1][1] = m_config.lowFreq;
281  limits[1][1] = m_config.highFreq;
282 
283  // This one is square
284  for( std::size_t i = 0; i < numControllers; i++)
285  {
286  for( std::size_t j = 0; j < numActions; j++)
287  {
288  nodeActions[i][j] = ( actions[i][j] *
289  (limits[1][j] - limits[0][j])) + limits[0][j];
290  }
291  }
292 
293  return nodeActions;
294 }
Contains the definition of class ImpedanceControl. $Id$.
virtual void onSetup(BaseSpineModelLearning &subject)
A class to read a learning configuration from a .ini file.
Contains the definition of abstract base class tgSpringCableActuator. Assumes that the string is line...
Contains the definition of class AnnealEvolution. Adapting NeuroEvolution to do Simulated Annealing...
virtual void onTeardown(BaseSpineModelLearning &subject)
Contains the definition of class tgBasicActuator.
virtual array_2D scalePhaseActions(std::vector< std::vector< double > > actions)
virtual void onStep(BaseSpineModelLearning &subject, double dt)
virtual void onStep(tgModel &model, double dt)
LearningSpineSine(BaseSpineCPGControl::Config config, std::string args, std::string ec="edgeConfig.ini", std::string nc="nodeConfig.ini")
void initialize(AnnealEvolution *evo, bool isLearning, configuration config)
virtual void onSetup(tgModel &model)
Controller for TetraSpineLearningModel.