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