NTRT Simulator  Version: Master
 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 resourcePath,
55  std::string ec,
56  std::string nc) :
57 BaseSpineCPGControl(config, args, resourcePath)
58 
59 {
60 }
61 
63 {
64  //Initialize the Learning Adapters
65  nodeAdapter.initialize(&nodeEvolution,
69  edgeLearning,
70  edgeConfigData);
71  /* Empty vector signifying no state information
72  * All parameters are stateless parameters, so we can get away with
73  * only doing this once
74  */
75  std::vector<double> state;
76  double dt = 0;
77 
78  array_2D edgeParams = scalePhaseActions(edgeAdapter.step(dt, state));
79  array_2D nodeParams = scaleNodeActions(nodeAdapter.step(dt, state));
80 
81  setupWaves(subject, nodeParams, edgeParams);
82 
83  initConditions = subject.getSegmentCOM(m_config.segmentNumber);
84 #if (0) // Conditional compile for data logging
85  m_dataObserver.onSetup(subject);
86 #endif
87 
88 
89  m_updateTime = 0.0;
90 }
91 
93 {
95  m_updateTime += dt;
96  if (m_updateTime >= m_config.controlTime)
97  {
98 
99 #if (0) // Conditional compile for data logging
100  m_dataObserver.onStep(subject, m_updateTime);
101 #endif
102  notifyStep(m_updateTime);
103  m_updateTime = 0;
104  }
105 }
106 
108 {
109  std::vector<double> scores;
110  // @todo - check to make sure we ran for the right amount of time
111 
112  std::vector<double> finalConditions = subject.getSegmentCOM(m_config.segmentNumber);
113 
114  const double newX = finalConditions[0];
115  const double newZ = finalConditions[2];
116  const double oldX = initConditions[0];
117  const double oldZ = initConditions[2];
118 
119  const double distanceMoved = sqrt((newX-oldX) * (newX-oldX) +
120  (newZ-oldZ) * (newZ-oldZ));
121 
122  scores.push_back(distanceMoved);
123 
126  double totalEnergySpent=0;
127 
128  vector<tgSpringCableActuator* > tmpSCAs = subject.getAllMuscles();
129  vector<tgBasicActuator* > tmpStrings = tgCast::filter<tgSpringCableActuator, tgBasicActuator>(tmpSCAs);
130  for(std::size_t i=0; i<tmpStrings.size(); i++)
131  {
132  tgSpringCableActuator::SpringCableActuatorHistory stringHist = tmpStrings[i]->getHistory();
133 
134  for(std::size_t j=1; j<stringHist.tensionHistory.size(); j++)
135  {
136  const double previousTension = stringHist.tensionHistory[j-1];
137  const double previousLength = stringHist.restLengths[j-1];
138  const double currentLength = stringHist.restLengths[j];
139  //TODO: examine this assumption - free spinning motor may require more power
140  double motorSpeed = (currentLength-previousLength);
141  if(motorSpeed > 0) // Vestigial code
142  motorSpeed = 0;
143  const double workDone = previousTension * motorSpeed;
144  totalEnergySpent += workDone;
145  }
146  }
147 
148  scores.push_back(totalEnergySpent);
149 
150  edgeAdapter.endEpisode(scores);
151  nodeAdapter.endEpisode(scores);
152 
153  for(size_t i = 0; i < m_sineControllers.size(); i++)
154  {
155  delete m_sineControllers[i];
156  }
157  m_sineControllers.clear();
158  m_allControllers.clear();
159 }
160 
161 void LearningSpineSine::setupWaves(BaseSpineModelLearning& subject, array_2D nodeActions, array_2D edgeActions)
162 {
163  std::vector <tgSpringCableActuator*> allMuscles = subject.getAllMuscles();
164 
165  double tension;
166  double kPosition;
167  double kVelocity;
168  double controlLength;
169 
170  for (std::size_t i = 0; i < allMuscles.size(); i++)
171  {
172  if (allMuscles[i]->hasTag("inner top"))
173  {
174  tension = 2000.0;
175  kPosition = 500.0;
176  kVelocity = 100.0;
177  controlLength = allMuscles[i]->getStartLength();
178  }
179  else if (allMuscles[i]->hasTag("outer top"))
180  {
181  tension = 1000.0;
182  kPosition = 500.0;
183  kVelocity = 100.0;
184  controlLength = 19.5;
185  }
186  else if (allMuscles[i]->hasTag("inner"))
187  {
188  tension = 1500.0;
189  kPosition = 100.0;
190  kVelocity = 100.0;
191  controlLength = allMuscles[i]->getStartLength();
192  }
193  else if (allMuscles[i]->hasTag("outer"))
194  {
195  tension = 800.0;
196  kPosition = 100.0;
197  kVelocity = 100.0;
198  controlLength = 19.5 ;
199  }
200  else
201  {
202  throw std::runtime_error("Missing tags!");
203  }
204 
205  tgImpedanceController* p_ipc = new tgImpedanceController( tension,
206  kPosition,
207  kVelocity);
208 
209  tgSineStringControl* pStringControl = new tgSineStringControl(m_config.controlTime,
210  p_ipc,
211  nodeActions[0][0],
212  nodeActions[0][1],
213  edgeActions[i][0],
214  0.0, // Repeat learning this too? Unlikely to be helpful
215  controlLength);
216 
217 
218  allMuscles[i]->attach(pStringControl);
219  m_sineControllers.push_back(pStringControl);
220  }
221 
222  assert(m_sineControllers.size() == allMuscles.size());
223 
224 
225 
226 
227 }
228 
230  (vector< vector <double> > actions)
231 {
232  std::size_t numControllers = edgeConfigData.getintvalue("numberOfControllers");
233  std::size_t numActions = edgeConfigData.getintvalue("numberOfActions");
234 
235  assert( actions.size() == numControllers);
236  assert( actions[0].size() == numActions);
237 
238  array_2D edgeActions(boost::extents[numControllers][numActions]);
239 
240  array_2D limits(boost::extents[2][numActions]);
241 
242  // Check if we need to update limits
243  assert(numActions == 1);
244 
245 
246  limits[0][0] = m_config.lowPhase;
247  limits[1][0] = m_config.highPhase;
248 
249  // This one is square
250  for( std::size_t i = 0; i < numControllers; i++)
251  {
252  for( std::size_t j = 0; j < numActions; j++)
253  {
254  edgeActions[i][j] = ( actions[i][j] *
255  (limits[1][j] - limits[0][j])) + limits[0][j];
256  }
257  }
258 
259  return edgeActions;
260 }
261 
262 array_2D LearningSpineSine::scaleNodeActions
263  (vector< vector <double> > actions)
264 {
265  std::size_t numControllers = nodeConfigData.getintvalue("numberOfControllers");
266  std::size_t numActions = nodeConfigData.getintvalue("numberOfActions");
267 
268  assert( actions.size() == numControllers);
269  assert( actions[0].size() == numActions);
270 
271  array_2D nodeActions(boost::extents[numControllers][numActions]);
272 
273  array_2D limits(boost::extents[2][numActions]);
274 
275  // Check if we need to update limits
276  assert(numActions == 2);
277 
278 
279  limits[0][0] = m_config.lowAmp;
280  limits[1][0] = m_config.highAmp;
281  limits[1][1] = m_config.lowFreq;
282  limits[1][1] = m_config.highFreq;
283 
284  // This one is square
285  for( std::size_t i = 0; i < numControllers; i++)
286  {
287  for( std::size_t j = 0; j < numActions; j++)
288  {
289  nodeActions[i][j] = ( actions[i][j] *
290  (limits[1][j] - limits[0][j])) + limits[0][j];
291  }
292  }
293 
294  return nodeActions;
295 }
Contains the definition of class ImpedanceControl. $Id$.
AnnealEvolution edgeEvolution
configuration nodeConfigData
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 resourcePath="", 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.