NTRT Simulator  Version: Master
 All Classes Namespaces Files Functions Variables Typedefs Friends Pages
JSONAchillesHierarchyControl.cpp
Go to the documentation of this file.
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 
29 
30 
31 // Should include tgString, but compiler complains since its been
32 // included from BaseSpineModelLearning. Perhaps we should move things
33 // to a cpp over there
35 #include "core/tgBasicActuator.h"
38 #include "examples/learningSpines/tgCPGCableControl.h"
39 
40 #include "dev/dhustigschultz/BigPuppy_SpineOnly_Stats/BaseQuadModelLearning.h"
41 #include "helpers/FileHelpers.h"
42 
45 
46 #include "util/CPGEquationsFB.h"
47 #include "examples/learningSpines/tgCPGCableControl.h"
48 
49 #include "neuralNet/Neural Network v2/neuralNetwork.h"
50 
51 #include <json/json.h>
52 
53 #include <string>
54 #include <iostream>
55 #include <vector>
56 
57 //#define LOGGING
58 #define USE_KINEMATIC
59 //#define PRINT_METRICS
60 
61 using namespace std;
62 
64  int tm,
65  int om,
66  int param,
67  int segnum,
68  double ct,
69  double la,
70  double ha,
71  double lp,
72  double hp,
73  double kt,
74  double kp,
75  double kv,
76  bool def,
77  double cl,
78  double lf,
79  double hf,
80  double ffMin,
81  double ffMax,
82  double afMin,
83  double afMax,
84  double pfMin,
85  double pfMax,
86  double maxH,
87  double minH,
88  int ohm,
89  int thm,
90  int olm,
91  int tlm,
92  int oam,
93  int tam,
94  int ohighm,
95  int thighm,
96  double hf2,
97  double ffMax2) :
98 JSONQuadCPGControl::Config::Config(ss, tm, om, param, segnum, ct, la, ha,
99  lp, hp, kt, kp, kv, def, cl, lf, hf),
100 freqFeedbackMin(ffMin),
101 freqFeedbackMax(ffMax),
102 ampFeedbackMin(afMin),
103 ampFeedbackMax(afMax),
104 phaseFeedbackMin(pfMin),
105 phaseFeedbackMax(pfMax),
106 maxHeight(maxH),
107 minHeight(minH),
108 ourHipMuscles(ohm),
109 theirHipMuscles(thm),
110 ourLegMuscles(olm),
111 theirLegMuscles(tlm),
112 ourAchillesMuscles(oam),
113 theirAchillesMuscles(tam),
114 ourHighMuscles(ohighm),
115 theirHighMuscles(thighm),
116 highFreq2(hf2),
117 freqFeedbackMax2(ffMax2)
118 {
119 
120 }
127  std::string args,
128  std::string resourcePath) :
129 JSONQuadCPGControl(config, args, resourcePath),
130 m_config(config)
131 {
132  // Path and filename handled by base class
133 
134 }
135 
136 JSONAchillesHierarchyControl::~JSONAchillesHierarchyControl()
137 {
138  //delete nn;
139 }
140 
142 {
143  m_pCPGSys = new CPGEquationsFB(500);
144 
145  Json::Value root; // will contains the root value after parsing.
146  Json::Reader reader;
147 
148  bool parsingSuccessful = reader.parse( FileHelpers::getFileString(controlFilename.c_str()), root );
149  if ( !parsingSuccessful )
150  {
151  // report to the user the failure and their locations in the document.
152  std::cout << "Failed to parse configuration\n"
153  << reader.getFormattedErrorMessages();
154  throw std::invalid_argument("Bad filename for JSON");
155  }
156  // Get the value of the member of root named 'encoding', return 'UTF-8' if there is no
157  // such member.
158  // Lower level CPG node and edge params:
159  Json::Value spineNodeVals = root.get("spineNodeVals", "UTF-8");
160  Json::Value legNodeVals = root.get("legNodeVals", "UTF-8");
161  Json::Value spineEdgeVals = root.get("spineEdgeVals", "UTF-8");
162  Json::Value hipEdgeVals = root.get("hipEdgeVals", "UTF-8");
163  Json::Value legEdgeVals = root.get("legEdgeVals", "UTF-8");
164  Json::Value achillesEdgeVals = root.get("achillesEdgeVals", "UTF-8");
165 
166  std::cout << spineNodeVals << std::endl;
167 
168  spineNodeVals = spineNodeVals.get("params", "UTF-8");
169  legNodeVals = legNodeVals.get("params", "UTF-8");
170  spineEdgeVals = spineEdgeVals.get("params", "UTF-8");
171  hipEdgeVals = hipEdgeVals.get("params", "UTF-8");
172  legEdgeVals = legEdgeVals.get("params", "UTF-8");
173  achillesEdgeVals = achillesEdgeVals.get("params", "UTF-8");
174 
175  // A painful way of reducing the solution space... had to rewrite scaleEdgeActions() to take in a couple more parameters.
176  array_4D spineEdgeParams = scaleEdgeActions(spineEdgeVals,m_config.segmentSpan,m_config.theirMuscles,m_config.ourMuscles);
177  array_4D hipEdgeParams = scaleEdgeActions(hipEdgeVals,m_config.segmentSpan,m_config.theirHipMuscles,m_config.ourHipMuscles);
178  array_4D legEdgeParams = scaleEdgeActions(legEdgeVals,m_config.segmentSpan,m_config.theirLegMuscles,m_config.ourLegMuscles);
179  array_4D achillesEdgeParams = scaleEdgeActions(achillesEdgeVals,m_config.segmentSpan,m_config.theirAchillesMuscles,m_config.ourAchillesMuscles);
180  array_2D spineNodeParams = scaleNodeActions(spineNodeVals, m_config.highFreq, m_config.freqFeedbackMax);
181  array_2D legNodeParams = scaleNodeActions(legNodeVals, m_config.highFreq, m_config.freqFeedbackMax);
182 
183 
184  // Higher level CPG node and edge params:
185  Json::Value highNodeVals = root.get("highNodeVals", "UTF-8");
186  Json::Value highEdgeVals = root.get("highEdgeVals", "UTF-8");
187 
188  highNodeVals = highNodeVals.get("params", "UTF-8");
189  highEdgeVals = highEdgeVals.get("params", "UTF-8");
190 
191  // Edge params for couplings between higher and lower levels:
192  Json::Value highLowEdgeVals = root.get("hLowVals", "UTF-8");
193  highLowEdgeVals = highLowEdgeVals.get("params", "UTF-8");
194 
195  array_4D highEdgeParams = scaleEdgeActions(highEdgeVals,2,m_config.theirHighMuscles,m_config.ourHighMuscles);
196  array_2D highNodeParams = scaleNodeActions(highNodeVals, m_config.highFreq2, m_config.freqFeedbackMax2);
197 
198  // Setup the higher level of CPGs
199  setupHighCPGs(subject, highNodeParams, highEdgeParams);
200 
201  // Setup the lower level of CPGs
202  setupCPGs(subject, spineNodeParams, legNodeParams, spineEdgeParams, hipEdgeParams, legEdgeParams, achillesEdgeParams);
203 
204  // Setup the couplings between higher and lower level CPGs
205  setupHighLowCouplings(subject, highLowEdgeVals);
206 
207  Json::Value feedbackParams = root.get("feedbackVals", "UTF-8");
208  feedbackParams = feedbackParams.get("params", "UTF-8");
209 
210  // Setup neural network
211  m_config.numStates = feedbackParams.get("numStates", "UTF-8").asInt();
212  m_config.numActions = feedbackParams.get("numActions", "UTF-8").asInt();
213  //m_config.numHidden = feedbackParams.get("numHidden", "UTF-8").asInt();
214 
215  std::string nnFile = controlFilePath + feedbackParams.get("neuralFilename", "UTF-8").asString();
216 
217  nn = new neuralNetwork(m_config.numStates, m_config.numStates*2, m_config.numActions);
218 
219  nn->loadWeights(nnFile.c_str());
220 
221  initConditions = subject.getSegmentCOM(m_config.segmentNumber);
222  for (int i = 0; i < initConditions.size(); i++)
223  {
224  std::cout << initConditions[i] << " ";
225  }
226  std::cout << std::endl;
227 #ifdef LOGGING // Conditional compile for data logging
228  m_dataObserver.onSetup(subject);
229 #endif
230 
231 #if (0) // Conditional Compile for debug info
232  std::cout << *m_pCPGSys << std::endl;
233 #endif
234  m_updateTime = 0.0;
235  m_totalTime = 0.0; //For metrics.
236  bogus = false;
237 
238  metrics.clear();
239 
240  //Getting the center of mass of the entire structure.
241  std::vector<double> structureCOM = subject.getCOM(m_config.segmentNumber);
242 
243  for(std::size_t i=0; i<3; i++)
244  {
245  metrics.push_back(structureCOM[i]);
246  }
247 
248  //"metrics" is a new section of the controller's JSON file that is
249  //added in the getNewFile function in evolution_job_master.py
250  Json::Value prevMetrics = root.get("metrics", Json::nullValue);
251 
252  Json::Value subMetrics;
253  subMetrics["initial COM x"] = metrics[0];
254  subMetrics["initial COM y"] = metrics[1];
255  subMetrics["initial COM z"] = metrics[2];
256 
257  prevMetrics.append(subMetrics);
258  root["metrics"] = prevMetrics;
259 
260  ofstream payloadLog;
261  payloadLog.open(controlFilename.c_str(),ofstream::out);
262 
263  payloadLog << root << std::endl;
264 
265 }
266 
268 {
269  m_updateTime += dt;
270  m_totalTime += dt;
271  if (m_updateTime >= m_config.controlTime)
272  {
273 #if (1)
274  std::vector<double> desComs = getFeedback(subject);
275 
276 #else
277  std::size_t numControllers = subject.getNumberofMuslces() * 3;
278 
279  double descendingCommand = 0.0;
280  std::vector<double> desComs (numControllers, descendingCommand);
281 #endif
282  try
283  {
284  m_pCPGSys->update(desComs, m_updateTime);
285  }
286  catch (std::runtime_error& e)
287  {
288  // Stops the trial immediately, lets teardown know it broke
289  bogus = true;
290  throw (e);
291  }
292 
293 #ifdef LOGGING // Conditional compile for data logging
294  m_dataObserver.onStep(subject, m_updateTime);
295 #endif
296  notifyStep(m_updateTime);
297  m_updateTime = 0;
298  }
299 
300  double currentHeight = subject.getSegmentCOM(m_config.segmentNumber)[1];
301  double currentHeightRear = subject.getSegmentCOM(6)[1];
302 
304  if (currentHeight > m_config.maxHeight || currentHeight < m_config.minHeight || currentHeightRear > m_config.maxHeight || currentHeightRear < m_config.minHeight)
305  {
307  bogus = true;
308  throw std::runtime_error("Height out of range");
309  }
310 
311 }
312 
314 {
315  scores.clear();
316  metrics.clear();
317  // @todo - check to make sure we ran for the right amount of time
318 
319  std::vector<double> finalConditions = subject.getSegmentCOM(m_config.segmentNumber);
320 
321  const double newX = finalConditions[0];
322  const double newZ = finalConditions[2];
323  const double oldX = initConditions[0];
324  const double oldZ = initConditions[2];
325 
326  const double distanceMoved = sqrt((newX-oldX) * (newX-oldX) +
327  (newZ-oldZ) * (newZ-oldZ));
328 
329  if (bogus)
330  {
331  scores.push_back(-1.0);
332  }
333  else
334  {
335  scores.push_back(distanceMoved);
336  }
337 
340  double totalEnergySpent=0;
341 
342  std::vector<tgSpringCableActuator* > tmpStrings = subject.find<tgSpringCableActuator> ("all ");
343 
344  for(std::size_t i=0; i<tmpStrings.size(); i++)
345  {
346  tgSpringCableActuator::SpringCableActuatorHistory stringHist = tmpStrings[i]->getHistory();
347 
348  for(std::size_t j=1; j<stringHist.tensionHistory.size(); j++)
349  {
350  const double previousTension = stringHist.tensionHistory[j-1];
351  const double previousLength = stringHist.restLengths[j-1];
352  const double currentLength = stringHist.restLengths[j];
353  //TODO: examine this assumption - free spinning motor may require more power
354  double motorSpeed = (currentLength-previousLength);
355  if(motorSpeed > 0) // Vestigial code
356  motorSpeed = 0;
357  const double workDone = previousTension * motorSpeed;
358  totalEnergySpent += workDone;
359  }
360  }
361 
362  scores.push_back(totalEnergySpent);
363 
364  //Getting the center of mass of the entire structure.
365  std::vector<double> structureCOM = subject.getCOM(m_config.segmentNumber);
366 
367  for(std::size_t i=0; i<3; i++)
368  {
369  metrics.push_back(structureCOM[i]);
370  }
371 
372  std::cout << "Dist travelled " << scores[0] << std::endl;
373 
374  Json::Value root; // will contain the root value after parsing.
375  Json::Reader reader;
376 
377  bool parsingSuccessful = reader.parse( FileHelpers::getFileString(controlFilename.c_str()), root );
378  if ( !parsingSuccessful )
379  {
380  // report to the user the failure and their locations in the document.
381  std::cout << "Failed to parse configuration\n"
382  << reader.getFormattedErrorMessages();
383  throw std::invalid_argument("Bad filename for JSON");
384  }
385 
386  Json::Value prevScores = root.get("scores", Json::nullValue);
387  Json::Value prevMetrics = root.get("metrics", Json::nullValue);
388 
389  Json::Value subScores;
390  subScores["distance"] = scores[0];
391  subScores["energy"] = scores[1];
392 
393  Json::Value subMetrics;
394  subMetrics["final COM x"] = metrics[0];
395  subMetrics["final COM y"] = metrics[1];
396  subMetrics["final COM z"] = metrics[2];
397 
398  prevScores.append(subScores);
399  prevMetrics.append(subMetrics);
400 
401  root["scores"] = prevScores;
402  root["metrics"] = prevMetrics;
403 
404  ofstream payloadLog;
405  payloadLog.open(controlFilename.c_str(),ofstream::out);
406 
407  payloadLog << root << std::endl;
408 
409  delete m_pCPGSys;
410  m_pCPGSys = NULL;
411 
412  // This is ugly, will clean up later:
413  for(size_t i = 0; i < m_spineControllers.size(); i++)
414  {
415  delete m_spineControllers[i];
416  }
417  m_spineControllers.clear();
418 
419  for(size_t i = 0; i < m_leftShoulderControllers.size(); i++)
420  {
421  delete m_leftShoulderControllers[i];
422  }
423  m_leftShoulderControllers.clear();
424 
425  for(size_t i = 0; i < m_rightShoulderControllers.size(); i++)
426  {
427  delete m_rightShoulderControllers[i];
428  }
429  m_rightShoulderControllers.clear();
430 
431  for(size_t i = 0; i < m_leftHipControllers.size(); i++)
432  {
433  delete m_leftHipControllers[i];
434  }
435  m_leftHipControllers.clear();
436 
437  for(size_t i = 0; i < m_rightHipControllers.size(); i++)
438  {
439  delete m_rightHipControllers[i];
440  }
441  m_rightHipControllers.clear();
442 
443  for(size_t i = 0; i < m_leftForelegControllers.size(); i++)
444  {
445  delete m_leftForelegControllers[i];
446  }
447  m_leftForelegControllers.clear();
448 
449  for(size_t i = 0; i < m_rightForelegControllers.size(); i++)
450  {
451  delete m_rightForelegControllers[i];
452  }
453  m_rightForelegControllers.clear();
454 
455  for(size_t i = 0; i < m_leftHindlegControllers.size(); i++)
456  {
457  delete m_leftHindlegControllers[i];
458  }
459  m_leftHindlegControllers.clear();
460 
461  for(size_t i = 0; i < m_rightHindlegControllers.size(); i++)
462  {
463  delete m_rightHindlegControllers[i];
464  }
465  m_rightHindlegControllers.clear();
466 
467  //Achilles controllers
468  for(size_t i = 0; i < m_leftFrontAchillesControllers.size(); i++)
469  {
470  delete m_leftFrontAchillesControllers[i];
471  }
472  m_leftFrontAchillesControllers.clear();
473 
474  for(size_t i = 0; i < m_rightFrontAchillesControllers.size(); i++)
475  {
476  delete m_rightFrontAchillesControllers[i];
477  }
478  m_rightFrontAchillesControllers.clear();
479 
480  for(size_t i = 0; i < m_leftRearAchillesControllers.size(); i++)
481  {
482  delete m_leftRearAchillesControllers[i];
483  }
484  m_leftRearAchillesControllers.clear();
485 
486  for(size_t i = 0; i < m_rightRearAchillesControllers.size(); i++)
487  {
488  delete m_rightRearAchillesControllers[i];
489  }
490  m_rightRearAchillesControllers.clear();
491 
492  // High controllers
493  for(size_t i = 0; i < m_highControllers.size(); i++)
494  {
495  delete m_highControllers[i];
496  }
497  m_highControllers.clear();
498 
499  // Trying to delete here instead, to fix the leak
500  delete nn;
501 
502 }
503 
504 //Note: Will make a more compact, reuseable function later when I decide on how want to handle m_xControllers for different body parts
505 //Perhaps a vector of vectors can be created, so looping can be done instead, or the function can be reused.
506 //For now, I'll settle for horrendous but works.
507 //This way makes it easier to grab the right node numbers again when doing high-low couplings.
508 void JSONAchillesHierarchyControl::setupCPGs(BaseQuadModelLearning& subject, array_2D spineNodeActions, array_2D legNodeActions, array_4D spineEdgeActions, array_4D hipEdgeActions, array_4D legEdgeActions, array_4D achillesEdgeActions)
509 {
510 
511  std::vector <tgSpringCableActuator*> spineMuscles = subject.find<tgSpringCableActuator> ("spine ");
512 
513  // Hip/shoulder muscles
514  std::vector <tgSpringCableActuator*> leftShoulderMuscles = subject.find<tgSpringCableActuator> ("left_shoulder");
515  std::vector <tgSpringCableActuator*> rightShoulderMuscles = subject.find<tgSpringCableActuator> ("right_shoulder");
516 
517  std::vector <tgSpringCableActuator*> leftHipMuscles = subject.find<tgSpringCableActuator> ("left_hip ");
518  std::vector <tgSpringCableActuator*> rightHipMuscles = subject.find<tgSpringCableActuator> ("right_hip ");
519 
520  // Lower leg muscles
521  std::vector <tgSpringCableActuator*> leftForelegMuscles = subject.find<tgSpringCableActuator> ("left_foreleg");
522  std::vector <tgSpringCableActuator*> rightForelegMuscles = subject.find<tgSpringCableActuator> ("right_foreleg");
523 
524  std::vector <tgSpringCableActuator*> leftHindlegMuscles = subject.find<tgSpringCableActuator> ("left_hindleg");
525  std::vector <tgSpringCableActuator*> rightHindlegMuscles = subject.find<tgSpringCableActuator> ("right_hindleg");
526 
527  // Achilles muscles
528  std::vector <tgSpringCableActuator*> leftFrontAchillesMuscles = subject.find<tgSpringCableActuator> ("left_front_achilles_tendon");
529  std::vector <tgSpringCableActuator*> rightFrontAchillesMuscles = subject.find<tgSpringCableActuator> ("right_front_achilles_tendon");
530 
531  std::vector <tgSpringCableActuator*> leftRearAchillesMuscles = subject.find<tgSpringCableActuator> ("left_rear_achilles_tendon");
532  std::vector <tgSpringCableActuator*> rightRearAchillesMuscles = subject.find<tgSpringCableActuator> ("right_rear_achilles_tendon");
533 
534  CPGEquationsFB& m_CPGFBSys = *(tgCast::cast<CPGEquations, CPGEquationsFB>(m_pCPGSys));
535 
536  /*
537  * SPINE COUPLING STARTS HERE
538  */
539 
540  for (std::size_t i = 0; i < spineMuscles.size(); i++)
541  {
542 
543  tgPIDController::Config config(20000.0, 0.0, 5.0, true); // Non backdrivable
544  tgCPGCableControl* pStringControl = new tgCPGCableControl(config);
545 
546  spineMuscles[i]->attach(pStringControl);
547 
548  // First assign node numbers
549  pStringControl->assignNodeNumberFB(m_CPGFBSys, spineNodeActions);
550 
551  m_spineControllers.push_back(pStringControl);
552  }
553 
554  // Then determine connectivity and setup string
555  for (std::size_t i = 0; i < m_spineControllers.size(); i++)
556  {
557  tgCPGActuatorControl * const pStringInfo = m_spineControllers[i];
558  assert(pStringInfo != NULL);
559  pStringInfo->setConnectivity(m_spineControllers, spineEdgeActions);
560 
561  //String will own this pointer
562  tgImpedanceController* p_ipc = new tgImpedanceController( m_config.tension,
563  m_config.kPosition,
564  m_config.kVelocity);
565  if (m_config.useDefault)
566  {
567  pStringInfo->setupControl(*p_ipc);
568  }
569  else
570  {
571  pStringInfo->setupControl(*p_ipc, m_config.controlLength);
572  }
573  }
574 
575  /*
576  * HIPS START HERE
577  */
578 
579  //Left shoulder first.
580  for (std::size_t i = 0; i < leftShoulderMuscles.size(); i++)
581  {
582 
583  tgPIDController::Config config(20000.0, 0.0, 5.0, true); // Non backdrivable
584  tgCPGCableControl* pStringControl = new tgCPGCableControl(config);
585 
586  leftShoulderMuscles[i]->attach(pStringControl);
587 
588  // First assign node numbers
589  pStringControl->assignNodeNumberFB(m_CPGFBSys, legNodeActions);
590 
591  m_leftShoulderControllers.push_back(pStringControl);
592  }
593 
594  // Then determine connectivity and setup string
595  for (std::size_t i = 0; i < m_leftShoulderControllers.size(); i++)
596  {
597  tgCPGActuatorControl * const pStringInfo = m_leftShoulderControllers[i];
598  assert(pStringInfo != NULL);
599  pStringInfo->setConnectivity(m_leftShoulderControllers, hipEdgeActions);
600 
601  //String will own this pointer
602  tgImpedanceController* p_ipc = new tgImpedanceController( m_config.tension,
603  m_config.kPosition,
604  m_config.kVelocity);
605  if (m_config.useDefault)
606  {
607  pStringInfo->setupControl(*p_ipc);
608  }
609  else
610  {
611  pStringInfo->setupControl(*p_ipc, m_config.controlLength);
612  }
613  }
614 
615  //Now right shoulder.
616  for (std::size_t i = 0; i < rightShoulderMuscles.size(); i++)
617  {
618 
619  tgPIDController::Config config(20000.0, 0.0, 5.0, true); // Non backdrivable
620  tgCPGCableControl* pStringControl = new tgCPGCableControl(config);
621 
622  rightShoulderMuscles[i]->attach(pStringControl);
623 
624  // First assign node numbers
625  pStringControl->assignNodeNumberFB(m_CPGFBSys, legNodeActions);
626 
627  m_rightShoulderControllers.push_back(pStringControl);
628  }
629 
630  // Then determine connectivity and setup string
631  for (std::size_t i = 0; i < m_rightShoulderControllers.size(); i++)
632  {
633  tgCPGActuatorControl * const pStringInfo = m_rightShoulderControllers[i];
634  assert(pStringInfo != NULL);
635  pStringInfo->setConnectivity(m_rightShoulderControllers, hipEdgeActions);
636 
637  //String will own this pointer
638  tgImpedanceController* p_ipc = new tgImpedanceController( m_config.tension,
639  m_config.kPosition,
640  m_config.kVelocity);
641  if (m_config.useDefault)
642  {
643  pStringInfo->setupControl(*p_ipc);
644  }
645  else
646  {
647  pStringInfo->setupControl(*p_ipc, m_config.controlLength);
648  }
649  }
650 
651  // Now the left hip
652  for (std::size_t i = 0; i < leftHipMuscles.size(); i++)
653  {
654 
655  tgPIDController::Config config(20000.0, 0.0, 5.0, true); // Non backdrivable
656  tgCPGCableControl* pStringControl = new tgCPGCableControl(config);
657 
658  leftHipMuscles[i]->attach(pStringControl);
659 
660  // First assign node numbers
661  pStringControl->assignNodeNumberFB(m_CPGFBSys, legNodeActions);
662 
663  m_leftHipControllers.push_back(pStringControl);
664  }
665 
666  // Then determine connectivity and setup string
667  for (std::size_t i = 0; i < m_leftHipControllers.size(); i++)
668  {
669  tgCPGActuatorControl * const pStringInfo = m_leftHipControllers[i];
670  assert(pStringInfo != NULL);
671  pStringInfo->setConnectivity(m_leftHipControllers, hipEdgeActions);
672 
673  //String will own this pointer
674  tgImpedanceController* p_ipc = new tgImpedanceController( m_config.tension,
675  m_config.kPosition,
676  m_config.kVelocity);
677  if (m_config.useDefault)
678  {
679  pStringInfo->setupControl(*p_ipc);
680  }
681  else
682  {
683  pStringInfo->setupControl(*p_ipc, m_config.controlLength);
684  }
685  }
686 
687  // Now the right hip
688  for (std::size_t i = 0; i < rightHipMuscles.size(); i++)
689  {
690 
691  tgPIDController::Config config(20000.0, 0.0, 5.0, true); // Non backdrivable
692  tgCPGCableControl* pStringControl = new tgCPGCableControl(config);
693 
694  leftHipMuscles[i]->attach(pStringControl);
695 
696  // First assign node numbers
697  pStringControl->assignNodeNumberFB(m_CPGFBSys, legNodeActions);
698 
699  m_rightHipControllers.push_back(pStringControl);
700  }
701 
702  // Then determine connectivity and setup string
703  for (std::size_t i = 0; i < m_rightHipControllers.size(); i++)
704  {
705  tgCPGActuatorControl * const pStringInfo = m_rightHipControllers[i];
706  assert(pStringInfo != NULL);
707  pStringInfo->setConnectivity(m_rightHipControllers, hipEdgeActions);
708 
709  //String will own this pointer
710  tgImpedanceController* p_ipc = new tgImpedanceController( m_config.tension,
711  m_config.kPosition,
712  m_config.kVelocity);
713  if (m_config.useDefault)
714  {
715  pStringInfo->setupControl(*p_ipc);
716  }
717  else
718  {
719  pStringInfo->setupControl(*p_ipc, m_config.controlLength);
720  }
721  }
722 
723  /*
724  * LEGS START HERE
725  */
726 
727  // Left foreleg first
728  for (std::size_t i = 0; i < leftForelegMuscles.size(); i++)
729  {
730 
731  tgPIDController::Config config(20000.0, 0.0, 5.0, true); // Non backdrivable
732  tgCPGCableControl* pStringControl = new tgCPGCableControl(config);
733 
734  leftForelegMuscles[i]->attach(pStringControl);
735 
736  // First assign node numbers
737  pStringControl->assignNodeNumberFB(m_CPGFBSys, legNodeActions);
738 
739  m_leftForelegControllers.push_back(pStringControl);
740  }
741 
742  // Then determine connectivity and setup string
743  for (std::size_t i = 0; i < m_leftForelegControllers.size(); i++)
744  {
745  tgCPGActuatorControl * const pStringInfo = m_leftForelegControllers[i];
746  assert(pStringInfo != NULL);
747  pStringInfo->setConnectivity(m_leftForelegControllers, legEdgeActions);
748 
749  //String will own this pointer
750  tgImpedanceController* p_ipc = new tgImpedanceController( m_config.tension,
751  m_config.kPosition,
752  m_config.kVelocity);
753  if (m_config.useDefault)
754  {
755  pStringInfo->setupControl(*p_ipc);
756  }
757  else
758  {
759  pStringInfo->setupControl(*p_ipc, m_config.controlLength);
760  }
761  }
762 
763  // Now right foreleg
764  for (std::size_t i = 0; i < rightForelegMuscles.size(); i++)
765  {
766 
767  tgPIDController::Config config(20000.0, 0.0, 5.0, true); // Non backdrivable
768  tgCPGCableControl* pStringControl = new tgCPGCableControl(config);
769 
770  rightForelegMuscles[i]->attach(pStringControl);
771 
772  // First assign node numbers
773  pStringControl->assignNodeNumberFB(m_CPGFBSys, legNodeActions);
774 
775  m_rightForelegControllers.push_back(pStringControl);
776  }
777 
778  // Then determine connectivity and setup string
779  for (std::size_t i = 0; i < m_rightForelegControllers.size(); i++)
780  {
781  tgCPGActuatorControl * const pStringInfo = m_rightForelegControllers[i];
782  assert(pStringInfo != NULL);
783  pStringInfo->setConnectivity(m_rightForelegControllers, legEdgeActions);
784 
785  //String will own this pointer
786  tgImpedanceController* p_ipc = new tgImpedanceController( m_config.tension,
787  m_config.kPosition,
788  m_config.kVelocity);
789  if (m_config.useDefault)
790  {
791  pStringInfo->setupControl(*p_ipc);
792  }
793  else
794  {
795  pStringInfo->setupControl(*p_ipc, m_config.controlLength);
796  }
797  }
798 
799  // Now left hindleg
800  for (std::size_t i = 0; i < leftHindlegMuscles.size(); i++)
801  {
802 
803  tgPIDController::Config config(20000.0, 0.0, 5.0, true); // Non backdrivable
804  tgCPGCableControl* pStringControl = new tgCPGCableControl(config);
805 
806  leftHindlegMuscles[i]->attach(pStringControl);
807 
808  // First assign node numbers
809  pStringControl->assignNodeNumberFB(m_CPGFBSys, legNodeActions);
810 
811  m_leftHindlegControllers.push_back(pStringControl);
812  }
813 
814  // Then determine connectivity and setup string
815  for (std::size_t i = 0; i < m_leftHindlegControllers.size(); i++)
816  {
817  tgCPGActuatorControl * const pStringInfo = m_leftHindlegControllers[i];
818  assert(pStringInfo != NULL);
819  pStringInfo->setConnectivity(m_leftHindlegControllers, legEdgeActions);
820 
821  //String will own this pointer
822  tgImpedanceController* p_ipc = new tgImpedanceController( m_config.tension,
823  m_config.kPosition,
824  m_config.kVelocity);
825  if (m_config.useDefault)
826  {
827  pStringInfo->setupControl(*p_ipc);
828  }
829  else
830  {
831  pStringInfo->setupControl(*p_ipc, m_config.controlLength);
832  }
833  }
834 
835  // Finally, right hindleg
836  for (std::size_t i = 0; i < rightHindlegMuscles.size(); i++)
837  {
838 
839  tgPIDController::Config config(20000.0, 0.0, 5.0, true); // Non backdrivable
840  tgCPGCableControl* pStringControl = new tgCPGCableControl(config);
841 
842  rightHindlegMuscles[i]->attach(pStringControl);
843 
844  // First assign node numbers
845  pStringControl->assignNodeNumberFB(m_CPGFBSys, legNodeActions);
846 
847  m_rightHindlegControllers.push_back(pStringControl);
848  }
849 
850  // Then determine connectivity and setup string
851  for (std::size_t i = 0; i < m_rightHindlegControllers.size(); i++)
852  {
853  tgCPGActuatorControl * const pStringInfo = m_rightHindlegControllers[i];
854  assert(pStringInfo != NULL);
855  pStringInfo->setConnectivity(m_rightHindlegControllers, legEdgeActions);
856 
857  //String will own this pointer
858  tgImpedanceController* p_ipc = new tgImpedanceController( m_config.tension,
859  m_config.kPosition,
860  m_config.kVelocity);
861  if (m_config.useDefault)
862  {
863  pStringInfo->setupControl(*p_ipc);
864  }
865  else
866  {
867  pStringInfo->setupControl(*p_ipc, m_config.controlLength);
868  }
869  }
870 
871 
872  /*
873  * ACHILLES START HERE
874  */
875  // Left front achilles first
876  for (std::size_t i = 0; i < leftFrontAchillesMuscles.size(); i++)
877  {
878 
879  tgPIDController::Config config(100000.0, 0.0, 10.0, true); // Non backdrivable
880  tgCPGCableControl* pStringControl = new tgCPGCableControl(config);
881 
882  leftFrontAchillesMuscles[i]->attach(pStringControl);
883 
884  // First assign node numbers
885  pStringControl->assignNodeNumberFB(m_CPGFBSys, legNodeActions);
886 
887  m_leftFrontAchillesControllers.push_back(pStringControl);
888  }
889 
890  // Then determine connectivity and setup string
891  for (std::size_t i = 0; i < m_leftFrontAchillesControllers.size(); i++)
892  {
893  tgCPGActuatorControl * const pStringInfo = m_leftFrontAchillesControllers[i];
894  assert(pStringInfo != NULL);
895  pStringInfo->setConnectivity(m_leftFrontAchillesControllers, achillesEdgeActions);
896 
897  //String will own this pointer
898  tgImpedanceController* p_ipc = new tgImpedanceController( m_config.tension,
899  m_config.kPosition,
900  m_config.kVelocity);
901  if (m_config.useDefault)
902  {
903  pStringInfo->setupControl(*p_ipc);
904  }
905  else
906  {
907  pStringInfo->setupControl(*p_ipc, m_config.controlLength);
908  }
909  }
910 
911  // Now right front achilles
912  for (std::size_t i = 0; i < rightFrontAchillesMuscles.size(); i++)
913  {
914 
915  tgPIDController::Config config(100000.0, 0.0, 10.0, true); // Non backdrivable
916  tgCPGCableControl* pStringControl = new tgCPGCableControl(config);
917 
918  rightFrontAchillesMuscles[i]->attach(pStringControl);
919 
920  // First assign node numbers
921  pStringControl->assignNodeNumberFB(m_CPGFBSys, legNodeActions);
922 
923  m_rightFrontAchillesControllers.push_back(pStringControl);
924  }
925 
926  // Then determine connectivity and setup string
927  for (std::size_t i = 0; i < m_rightFrontAchillesControllers.size(); i++)
928  {
929  tgCPGActuatorControl * const pStringInfo = m_rightFrontAchillesControllers[i];
930  assert(pStringInfo != NULL);
931  pStringInfo->setConnectivity(m_rightFrontAchillesControllers, achillesEdgeActions);
932 
933  //String will own this pointer
934  tgImpedanceController* p_ipc = new tgImpedanceController( m_config.tension,
935  m_config.kPosition,
936  m_config.kVelocity);
937  if (m_config.useDefault)
938  {
939  pStringInfo->setupControl(*p_ipc);
940  }
941  else
942  {
943  pStringInfo->setupControl(*p_ipc, m_config.controlLength);
944  }
945  }
946 
947  // Now left rear achilles
948  for (std::size_t i = 0; i < leftRearAchillesMuscles.size(); i++)
949  {
950 
951  tgPIDController::Config config(100000.0, 0.0, 10.0, true); // Non backdrivable
952  tgCPGCableControl* pStringControl = new tgCPGCableControl(config);
953 
954  leftRearAchillesMuscles[i]->attach(pStringControl);
955 
956  // First assign node numbers
957  pStringControl->assignNodeNumberFB(m_CPGFBSys, legNodeActions);
958 
959  m_leftRearAchillesControllers.push_back(pStringControl);
960  }
961 
962  // Then determine connectivity and setup string
963  for (std::size_t i = 0; i < m_leftRearAchillesControllers.size(); i++)
964  {
965  tgCPGActuatorControl * const pStringInfo = m_leftRearAchillesControllers[i];
966  assert(pStringInfo != NULL);
967  pStringInfo->setConnectivity(m_leftRearAchillesControllers, achillesEdgeActions);
968 
969  //String will own this pointer
970  tgImpedanceController* p_ipc = new tgImpedanceController( m_config.tension,
971  m_config.kPosition,
972  m_config.kVelocity);
973  if (m_config.useDefault)
974  {
975  pStringInfo->setupControl(*p_ipc);
976  }
977  else
978  {
979  pStringInfo->setupControl(*p_ipc, m_config.controlLength);
980  }
981  }
982 
983  // Finally, right rear achilles
984  for (std::size_t i = 0; i < rightRearAchillesMuscles.size(); i++)
985  {
986 
987  tgPIDController::Config config(100000.0, 0.0, 10.0, true); // Non backdrivable
988  tgCPGCableControl* pStringControl = new tgCPGCableControl(config);
989 
990  rightRearAchillesMuscles[i]->attach(pStringControl);
991 
992  // First assign node numbers
993  pStringControl->assignNodeNumberFB(m_CPGFBSys, legNodeActions);
994 
995  m_rightRearAchillesControllers.push_back(pStringControl);
996  }
997 
998  // Then determine connectivity and setup string
999  for (std::size_t i = 0; i < m_rightRearAchillesControllers.size(); i++)
1000  {
1001  tgCPGActuatorControl * const pStringInfo = m_rightRearAchillesControllers[i];
1002  assert(pStringInfo != NULL);
1003  pStringInfo->setConnectivity(m_rightRearAchillesControllers, achillesEdgeActions);
1004 
1005  //String will own this pointer
1006  tgImpedanceController* p_ipc = new tgImpedanceController( m_config.tension,
1007  m_config.kPosition,
1008  m_config.kVelocity);
1009  if (m_config.useDefault)
1010  {
1011  pStringInfo->setupControl(*p_ipc);
1012  }
1013  else
1014  {
1015  pStringInfo->setupControl(*p_ipc, m_config.controlLength);
1016  }
1017  }
1018 
1019 }
1020 
1021 
1022 //This is horrendous too, will make it more bearable looking later.
1023 void JSONAchillesHierarchyControl::setupHighLowCouplings(BaseQuadModelLearning& subject, Json::Value highLowEdgeActions)
1024 {
1025  // Now couple high level with low level
1026  // list of other nodenums, eq size list of weights/phases
1027  //m_pCPGSystem->defineConnections(m_nodeNumber, connectivityList, weights, phases);
1028 
1029  double lowerLimit = m_config.lowPhase;
1030  double upperLimit = m_config.highPhase;
1031  double range = upperLimit - lowerLimit;
1032 
1033  CPGEquationsFB& m_CPGFBSys = *(tgCast::cast<CPGEquations, CPGEquationsFB>(m_pCPGSys));
1034 
1035  Json::Value::iterator edgeIt = highLowEdgeActions.end();
1036 
1037  // Number of node to start at (Note that nodes 0-4 are high CPGs)
1038 
1039  //Unrolling loop for now... again, horrendous, and will think of a way to roll it back up eventually
1040  //First high CPG, b == 0:
1041  int b = 0;
1042  edgeIt--;
1043 
1044  std::vector<int> spineConnectivityList;
1045  std::vector<double> spineWeights;
1046  std::vector<double> spinePhases;
1047 
1048  std::vector<int> leftShoulderConnectivityList;
1049  std::vector<double> leftShoulderWeights;
1050  std::vector<double> leftShoulderPhases;
1051 
1052  std::vector<int> leftForelegConnectivityList;
1053  std::vector<double> leftForelegWeights;
1054  std::vector<double> leftForelegPhases;
1055 
1056  std::vector<int> leftFrontAchillesConnectivityList;
1057  std::vector<double> leftFrontAchillesWeights;
1058  std::vector<double> leftFrontAchillesPhases;
1059 
1060  std::vector<int> rightShoulderConnectivityList;
1061  std::vector<double> rightShoulderWeights;
1062  std::vector<double> rightShoulderPhases;
1063 
1064  std::vector<int> rightForelegConnectivityList;
1065  std::vector<double> rightForelegWeights;
1066  std::vector<double> rightForelegPhases;
1067 
1068  std::vector<int> rightFrontAchillesConnectivityList;
1069  std::vector<double> rightFrontAchillesWeights;
1070  std::vector<double> rightFrontAchillesPhases;
1071 
1072  std::vector<int> leftHipConnectivityList;
1073  std::vector<double> leftHipWeights;
1074  std::vector<double> leftHipPhases;
1075 
1076  std::vector<int> leftHindlegConnectivityList;
1077  std::vector<double> leftHindlegWeights;
1078  std::vector<double> leftHindlegPhases;
1079 
1080  std::vector<int> leftRearAchillesConnectivityList;
1081  std::vector<double> leftRearAchillesWeights;
1082  std::vector<double> leftRearAchillesPhases;
1083 
1084  std::vector<int> rightHipConnectivityList;
1085  std::vector<double> rightHipWeights;
1086  std::vector<double> rightHipPhases;
1087 
1088  std::vector<int> rightHindlegConnectivityList;
1089  std::vector<double> rightHindlegWeights;
1090  std::vector<double> rightHindlegPhases;
1091 
1092  std::vector<int> rightRearAchillesConnectivityList;
1093  std::vector<double> rightRearAchillesWeights;
1094  std::vector<double> rightRearAchillesPhases;
1095 
1096  Json::Value param = *edgeIt;
1097  assert(param.size() == 2);
1098 
1099  // Use the vector of "m_controllers" vector for the part in question, to find the right node numbers
1100 
1101  for (size_t i = 0; i < m_spineControllers.size(); i++)
1102  {
1103  // Get the node number for each muscle
1104  int nodeNum = m_spineControllers[i]->getNodeNumber();
1105 
1106  // And then add to the connectivity list.
1107  spineConnectivityList.push_back(nodeNum);
1108  spineWeights.push_back(param[0].asDouble());
1109  spinePhases.push_back(param[1].asDouble() * (range) + lowerLimit);
1110  }
1111  m_CPGFBSys.defineConnections(b, spineConnectivityList, spineWeights, spinePhases);
1112 
1113  b++;
1114  edgeIt--;
1115 
1116  for (size_t i = 0; i < m_leftShoulderControllers.size(); i++)
1117  {
1118  // Get the node number for each muscle
1119  int nodeNum = m_leftShoulderControllers[i]->getNodeNumber();
1120 
1121  // And then add to the connectivity list.
1122  leftShoulderConnectivityList.push_back(nodeNum);
1123  leftShoulderWeights.push_back(param[0].asDouble());
1124  leftShoulderPhases.push_back(param[1].asDouble() * (range) + lowerLimit);
1125  }
1126  m_CPGFBSys.defineConnections(b, leftShoulderConnectivityList, leftShoulderWeights, leftShoulderPhases);
1127 
1128  //Do not increment/decrement b/edgeIt again, until full left foreleg is done!
1129 
1130  for (size_t i = 0; i < m_leftForelegControllers.size(); i++)
1131  {
1132  // Get the node number for each muscle
1133  int nodeNum = m_leftForelegControllers[i]->getNodeNumber();
1134 
1135  // And then add to the connectivity list.
1136  leftForelegConnectivityList.push_back(nodeNum);
1137  leftForelegWeights.push_back(param[0].asDouble());
1138  leftForelegPhases.push_back(param[1].asDouble() * (range) + lowerLimit);
1139  }
1140  m_CPGFBSys.defineConnections(b, leftForelegConnectivityList, leftForelegWeights, leftForelegPhases);
1141 
1142  //Do not increment/decrement b/edgeIt again, until full left front achilles tendons are done!
1143 
1144  for (size_t i = 0; i < m_leftFrontAchillesControllers.size(); i++)
1145  {
1146  // Get the node number for each muscle
1147  int nodeNum = m_leftFrontAchillesControllers[i]->getNodeNumber();
1148 
1149  // And then add to the connectivity list.
1150  leftFrontAchillesConnectivityList.push_back(nodeNum);
1151  leftFrontAchillesWeights.push_back(param[0].asDouble());
1152  leftFrontAchillesPhases.push_back(param[1].asDouble() * (range) + lowerLimit);
1153  }
1154  m_CPGFBSys.defineConnections(b, leftFrontAchillesConnectivityList, leftFrontAchillesWeights, leftFrontAchillesPhases);
1155 
1156  // Now it's safe to increment/decrement
1157 
1158  b++;
1159  edgeIt--;
1160 
1161  for (size_t i = 0; i < m_rightShoulderControllers.size(); i++)
1162  {
1163  // Get the node number for each muscle
1164  int nodeNum = m_rightShoulderControllers[i]->getNodeNumber();
1165 
1166  // And then add to the connectivity list.
1167  rightShoulderConnectivityList.push_back(nodeNum);
1168  rightShoulderWeights.push_back(param[0].asDouble());
1169  rightShoulderPhases.push_back(param[1].asDouble() * (range) + lowerLimit);
1170  }
1171  m_CPGFBSys.defineConnections(b, rightShoulderConnectivityList, rightShoulderWeights, rightShoulderPhases);
1172 
1173  //Again, do not increment/decrement b/edgeIt until full right foreleg is done!
1174 
1175  for (size_t i = 0; i < m_rightForelegControllers.size(); i++)
1176  {
1177  // Get the node number for each muscle
1178  int nodeNum = m_rightForelegControllers[i]->getNodeNumber();
1179 
1180  // And then add to the connectivity list.
1181  rightForelegConnectivityList.push_back(nodeNum);
1182  rightForelegWeights.push_back(param[0].asDouble());
1183  rightForelegPhases.push_back(param[1].asDouble() * (range) + lowerLimit);
1184  }
1185  m_CPGFBSys.defineConnections(b, rightForelegConnectivityList, rightForelegWeights, rightForelegPhases);
1186 
1187  //Do not increment/decrement b/edgeIt again, until right front achilles tendons are done!
1188 
1189  for (size_t i = 0; i < m_rightFrontAchillesControllers.size(); i++)
1190  {
1191  // Get the node number for each muscle
1192  int nodeNum = m_rightFrontAchillesControllers[i]->getNodeNumber();
1193 
1194  // And then add to the connectivity list.
1195  rightFrontAchillesConnectivityList.push_back(nodeNum);
1196  rightFrontAchillesWeights.push_back(param[0].asDouble());
1197  rightFrontAchillesPhases.push_back(param[1].asDouble() * (range) + lowerLimit);
1198  }
1199  m_CPGFBSys.defineConnections(b, rightFrontAchillesConnectivityList, rightFrontAchillesWeights, rightFrontAchillesPhases);
1200 
1201  // Now it's safe to increment/decrement
1202 
1203  b++;
1204  edgeIt--;
1205 
1206  for (size_t i = 0; i < m_leftHipControllers.size(); i++)
1207  {
1208  // Get the node number for each muscle
1209  int nodeNum = m_leftHipControllers[i]->getNodeNumber();
1210 
1211  // And then add to the connectivity list.
1212  leftHipConnectivityList.push_back(nodeNum);
1213  leftHipWeights.push_back(param[0].asDouble());
1214  leftHipPhases.push_back(param[1].asDouble() * (range) + lowerLimit);
1215  }
1216  m_CPGFBSys.defineConnections(b, leftHipConnectivityList, leftHipWeights, leftHipPhases);
1217 
1218  //Do not increment/decrement b/edgeIt again, until full left hindleg leg is done!
1219 
1220  for (size_t i = 0; i < m_leftHindlegControllers.size(); i++)
1221  {
1222  // Get the node number for each muscle
1223  int nodeNum = m_leftHindlegControllers[i]->getNodeNumber();
1224 
1225  // And then add to the connectivity list.
1226  leftHindlegConnectivityList.push_back(nodeNum);
1227  leftHindlegWeights.push_back(param[0].asDouble());
1228  leftHindlegPhases.push_back(param[1].asDouble() * (range) + lowerLimit);
1229  }
1230  m_CPGFBSys.defineConnections(b, leftHindlegConnectivityList, leftHindlegWeights, leftHindlegPhases);
1231 
1232  //Do not increment/decrement b/edgeIt again, until left rear achilles tendons are done!
1233 
1234  for (size_t i = 0; i < m_leftRearAchillesControllers.size(); i++)
1235  {
1236  // Get the node number for each muscle
1237  int nodeNum = m_leftRearAchillesControllers[i]->getNodeNumber();
1238 
1239  // And then add to the connectivity list.
1240  leftRearAchillesConnectivityList.push_back(nodeNum);
1241  leftRearAchillesWeights.push_back(param[0].asDouble());
1242  leftRearAchillesPhases.push_back(param[1].asDouble() * (range) + lowerLimit);
1243  }
1244  m_CPGFBSys.defineConnections(b, leftRearAchillesConnectivityList, leftRearAchillesWeights, leftRearAchillesPhases);
1245 
1246  // Now it's safe to increment/decrement
1247 
1248  b++;
1249  edgeIt--;
1250 
1251  for (size_t i = 0; i < m_rightHipControllers.size(); i++)
1252  {
1253  // Get the node number for each muscle
1254  int nodeNum = m_rightHipControllers[i]->getNodeNumber();
1255 
1256  // And then add to the connectivity list.
1257  rightHipConnectivityList.push_back(nodeNum);
1258  rightHipWeights.push_back(param[0].asDouble());
1259  rightHipPhases.push_back(param[1].asDouble() * (range) + lowerLimit);
1260  }
1261  m_CPGFBSys.defineConnections(b, rightHipConnectivityList, rightHipWeights, rightHipPhases);
1262 
1263  //Again, do not increment/decrement b/edgeIt until full right foreleg leg is done!
1264 
1265 
1266  for (size_t i = 0; i < m_rightHindlegControllers.size(); i++)
1267  {
1268  // Get the node number for each muscle
1269  int nodeNum = m_rightHindlegControllers[i]->getNodeNumber();
1270 
1271  // And then add to the connectivity list.
1272  rightHindlegConnectivityList.push_back(nodeNum);
1273  rightHindlegWeights.push_back(param[0].asDouble());
1274  rightHindlegPhases.push_back(param[1].asDouble() * (range) + lowerLimit);
1275  }
1276  m_CPGFBSys.defineConnections(b, rightHindlegConnectivityList, rightHindlegWeights, rightHindlegPhases);
1277 
1278 
1279  //Do not increment/decrement b/edgeIt again, until right rear achilles tendons are done!
1280 
1281  for (size_t i = 0; i < m_rightRearAchillesControllers.size(); i++)
1282  {
1283  // Get the node number for each muscle
1284  int nodeNum = m_rightRearAchillesControllers[i]->getNodeNumber();
1285 
1286  // And then add to the connectivity list.
1287  rightRearAchillesConnectivityList.push_back(nodeNum);
1288  rightRearAchillesWeights.push_back(param[0].asDouble());
1289  rightRearAchillesPhases.push_back(param[1].asDouble() * (range) + lowerLimit);
1290  }
1291  m_CPGFBSys.defineConnections(b, rightRearAchillesConnectivityList, rightRearAchillesWeights, rightRearAchillesPhases);
1292 
1293  // TODO?
1294  assert(highLowEdgeActions.begin() == edgeIt);
1295 }
1296 
1297 void JSONAchillesHierarchyControl::setupHighCPGs(BaseQuadModelLearning& subject, array_2D highNodeActions, array_4D highEdgeActions)
1298 {
1299  CPGEquationsFB& m_CPGFBSys = *(tgCast::cast<CPGEquations, CPGEquationsFB>(m_pCPGSys));
1300 
1301  // Make higher level CPGs, give them node params
1302  for (std::size_t b = 0; b < 5; b++)
1303  {
1304  tgPIDController::Config config(20000.0, 0.0, 5.0, true); // Non backdrivable
1305  tgCPGCableControl* pStringControl = new tgCPGCableControl(config);
1306 
1307  // need to make a 1 row 2D array so we can pass it into assignNodeNumber.
1308  // using nodeActions will not work. (notice subtle name difference) ~B
1309  //array_2D nodeAction(boost::extents[1][nodeActions.shape()[1]]);
1310  //for (std::size_t a = 0; a < nodeActions.shape()[1]; a++)
1311  //nodeAction[0][a] = nodeActions[b][a];
1312 
1313  // must give node number, to make things easier and stuff
1314  pStringControl->assignNodeNumberFB(m_CPGFBSys, highNodeActions);
1315 
1316  m_highControllers.push_back(pStringControl);
1317  }
1318 
1319  // Determine connectivity between higher level CPGs
1320  for (std::size_t i = 0; i < m_highControllers.size(); i++)
1321  {
1322  tgCPGActuatorControl * const pStringInfo = m_highControllers[i];
1323  assert(pStringInfo != NULL);
1324  pStringInfo->setConnectivity(m_highControllers, highEdgeActions);
1325  }
1326 
1327 }
1328 
1329 array_2D JSONAchillesHierarchyControl::scaleNodeActions (Json::Value actions, double highFreq, double freqFeedbackMax)
1330 {
1331  std::size_t numControllers = actions.size();
1332  std::size_t numActions = actions[0].size();
1333 
1334  array_2D nodeActions(boost::extents[numControllers][numActions]);
1335 
1336  array_2D limits(boost::extents[2][numActions]);
1337 
1338  // Check if we need to update limits
1339  assert(numActions == 5);
1340 
1341  limits[0][0] = m_config.lowFreq;
1342  limits[1][0] = highFreq;
1343  limits[0][1] = m_config.lowAmp;
1344  limits[1][1] = m_config.highAmp;
1345  limits[0][2] = m_config.freqFeedbackMin;
1346  limits[1][2] = freqFeedbackMax;
1347  limits[0][3] = m_config.ampFeedbackMin;
1348  limits[1][3] = m_config.ampFeedbackMax;
1349  limits[0][4] = m_config.phaseFeedbackMin;
1350  limits[1][4] = m_config.phaseFeedbackMax;
1351 
1352  Json::Value::iterator nodeIt = actions.begin();
1353 
1354  // This one is square
1355  for( std::size_t i = 0; i < numControllers; i++)
1356  {
1357  Json::Value nodeParam = *nodeIt;
1358  for( std::size_t j = 0; j < numActions; j++)
1359  {
1360  nodeActions[i][j] = ( (nodeParam.get(j, 0.0)).asDouble() *
1361  (limits[1][j] - limits[0][j])) + limits[0][j];
1362  }
1363  nodeIt++;
1364  }
1365 
1366  return nodeActions;
1367 }
1368 
1370  (Json::Value edgeParam, int segmentSpan, int theirMuscles, int ourMuscles)
1371 {
1372  assert(edgeParam[0].size() == 2);
1373 
1374  double lowerLimit = m_config.lowPhase;
1375  double upperLimit = m_config.highPhase;
1376  double range = upperLimit - lowerLimit;
1377 
1378  array_4D actionList(boost::extents[segmentSpan][theirMuscles][ourMuscles][m_config.params]);
1379 
1380  /* Horrid while loop to populate upper diagonal of matrix, since
1381  * its symmetric and we want to minimze parameters used in learing
1382  * note that i==1, j==k will refer to the same muscle
1383  * @todo use boost to set up array so storage is only allocated for
1384  * elements that are used
1385  */
1386  int i = 0;
1387  int j = 0;
1388  int k = 0;
1389 
1390  // Quirk of the old learning code. Future examples can move forward
1391  Json::Value::iterator edgeIt = edgeParam.end();
1392 
1393  int count = 0;
1394 
1395  while (i < segmentSpan)
1396  {
1397  while(j < theirMuscles)
1398  {
1399  while(k < ourMuscles)
1400  {
1401  if (edgeIt == edgeParam.begin())
1402  {
1403  std::cout << "ran out before table populated!"
1404  << std::endl;
1406  break;
1407  }
1408  else
1409  {
1410  if (i == 1 && j == k)
1411  {
1412  // std::cout << "Skipped identical muscle" << std::endl;
1413  //Skip since its the same muscle
1414  }
1415  else
1416  {
1417  edgeIt--;
1418  Json::Value edgeParam = *edgeIt;
1419  assert(edgeParam.size() == 2);
1420  // Weight from 0 to 1
1421  actionList[i][j][k][0] = edgeParam[0].asDouble();
1422  //std::cout << actionList[i][j][k][0] << " ";
1423  // Phase offset from -pi to pi
1424  actionList[i][j][k][1] = edgeParam[1].asDouble() *
1425  (range) + lowerLimit;
1426  //std::cout << actionList[i][j][k][1] << std::endl;
1427  count++;
1428  }
1429  }
1430  k++;
1431  }
1432  j++;
1433  k = j;
1434 
1435  }
1436  j = 0;
1437  k = 0;
1438  i++;
1439  }
1440 
1441  std::cout<< "Params used: " << count << std::endl;
1442 
1443  assert(edgeParam.begin() == edgeIt);
1444 
1445  return actionList;
1446 }
1447 
1448 std::vector<double> JSONAchillesHierarchyControl::getFeedback(BaseQuadModelLearning& subject)
1449 {
1450  // Placeholder
1451  std::vector<double> feedback;
1452 
1453  const std::vector<tgSpringCableActuator*>& allCables = subject.find<tgSpringCableActuator> ("all ");
1454 
1455  double *inputs = new double[m_config.numStates];
1456 
1457  std::size_t n = allCables.size();
1458  for(std::size_t i = 0; i != n; i++)
1459  {
1460  std::vector< std::vector<double> > actions;
1461 
1462  const tgSpringCableActuator& cable = *(allCables[i]);
1463  std::vector<double > state = getCableState(cable);
1464 
1465  // Rescale to 0 to 1 (consider doing this inside getState
1466  for (std::size_t i = 0; i < state.size(); i++)
1467  {
1468  inputs[i]=state[i] / 2.0 + 0.5;
1469  }
1470 
1471  double *output = nn->feedForwardPattern(inputs);
1472  vector<double> tmpAct;
1473  for(int j=0;j<m_config.numActions;j++)
1474  {
1475  tmpAct.push_back(output[j]);
1476  }
1477  actions.push_back(tmpAct);
1478 
1479  std::vector<double> cableFeedback = transformFeedbackActions(actions);
1480 
1481  feedback.insert(feedback.end(), cableFeedback.begin(), cableFeedback.end());
1482  }
1483 
1484  // Inputting 0 for now. Still thinking of a better feedback mechanism.
1485  std::size_t n2 = m_highControllers.size();
1486  for (size_t i = 0; i != n2; i++)
1487  {
1488  std::vector< std::vector<double> > actions;
1489 
1490  // Rescale to 0 to 1 (consider doing this inside getState)
1491  for (std::size_t i = 0; i < m_config.numStates; i++)
1492  {
1493  inputs[i] = 0;
1494  }
1495 
1496  double *output = nn->feedForwardPattern(inputs);
1497  vector<double> tmpAct;
1498  for(int j=0;j<m_config.numActions;j++)
1499  {
1500  tmpAct.push_back(output[j]);
1501  }
1502  actions.push_back(tmpAct);
1503 
1504  std::vector<double> cableFeedback = transformFeedbackActions(actions);
1505 
1506  feedback.insert(feedback.end(), cableFeedback.begin(), cableFeedback.end());
1507  }
1508 
1509  return feedback;
1510 }
1511 
1512 std::vector<double> JSONAchillesHierarchyControl::getCableState(const tgSpringCableActuator& cable)
1513 {
1514  // For each string, scale value from -1 to 1 based on initial length or max tension of motor
1515 
1516  std::vector<double> state;
1517 
1518  // Scale length by starting length
1519  const double startLength = cable.getStartLength();
1520  state.push_back((cable.getCurrentLength() - startLength) / startLength);
1521 
1522  const double maxTension = cable.getConfig().maxTens;
1523  state.push_back((cable.getTension() - maxTension / 2.0) / maxTension);
1524 
1525  return state;
1526 }
1527 
1528 std::vector<double> JSONAchillesHierarchyControl::transformFeedbackActions(std::vector< std::vector<double> >& actions)
1529 {
1530  // Placeholder
1531  std::vector<double> feedback;
1532 
1533  // Leave in place for generalization later
1534  const std::size_t numControllers = 1;
1535  const std::size_t numActions = m_config.numActions;
1536 
1537  assert( actions.size() == numControllers);
1538  assert( actions[0].size() == numActions);
1539 
1540  // Scale values back to -1 to +1
1541  for( std::size_t i = 0; i < numControllers; i++)
1542  {
1543  for( std::size_t j = 0; j < numActions; j++)
1544  {
1545  feedback.push_back(actions[i][j] * 2.0 - 1.0);
1546  }
1547  }
1548 
1549  return feedback;
1550 }
Contains the definition of class ImpedanceControl. $Id$.
virtual void onTeardown(BaseQuadModelLearning &subject)
JSONAchillesHierarchyControl(JSONAchillesHierarchyControl::Config config, std::string args, std::string resourcePath="")
void update(std::vector< double > &descCom, double dt)
virtual const double getTension() const
virtual const double getStartLength() const
void setConnectivity(const std::vector< tgCPGActuatorControl * > &allStrings, array_4D edgeParams)
virtual void onStep(BaseQuadModelLearning &subject, double dt)
Definition of the tgCPGStringControl observer class.
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...
A series of functions to assist with file input/output.
Contains the definition of class AnnealEvolution. Adapting NeuroEvolution to do Simulated Annealing...
Contains the definition of class tgBasicActuator.
virtual array_4D scaleEdgeActions(Json::Value actions, int segmentSpan, int theirMuscles, int ourMuscles)
const Config & getConfig() const
std::vector< T * > find(const tgTagSearch &tagSearch)
Definition: tgModel.h:128
virtual void onStep(tgModel &model, double dt)
A controller for the template class BaseQuadModelLearning Implementing a CPG hierachy for MountainGoa...
Definition of class CPGEquationsFB.
virtual void onSetup(tgModel &model)
Config(int ss, int tm, int om, int param, int segnum=6, double ct=0.1, double la=0, double ha=30, double lp=-1 *M_PI, double hp=M_PI, double kt=0.0, double kp=1000.0, double kv=100.0, bool def=true, double cl=10.0, double lf=0.0, double hf=30.0, double ffMin=0.0, double ffMax=0.0, double afMin=0.0, double afMax=0.0, double pfMin=0.0, double pfMax=0.0, double maxH=60.0, double minH=1.0, int ohm=10, int thm=10, int olm=10, int tlm=10, int oam=2, int tam=2, int ohighm=5, int thighm=5, double hf2=20.0, double ffMax2=0.0)
virtual const double getCurrentLength() const
virtual void onSetup(BaseQuadModelLearning &subject)
void assignNodeNumberFB(CPGEquationsFB &CPGSys, array_2D nodeParams)