38 #include "examples/learningSpines/tgCPGCableControl.h"
40 #include "dev/dhustigschultz/BigPuppy_SpineOnly_Stats/BaseQuadModelLearning.h"
47 #include "examples/learningSpines/tgCPGCableControl.h"
49 #include "neuralNet/Neural Network v2/neuralNetwork.h"
51 #include <json/json.h>
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),
117 freqFeedbackMax2(ffMax2)
128 std::string resourcePath) :
136 JSONAOHierarchyControl::~JSONAOHierarchyControl()
148 bool parsingSuccessful = reader.parse( FileHelpers::getFileString(controlFilename.c_str()), root );
149 if ( !parsingSuccessful )
152 std::cout <<
"Failed to parse configuration\n"
153 << reader.getFormattedErrorMessages();
154 throw std::invalid_argument(
"Bad filename for JSON");
164 Json::Value achillesNodeVals = root.get(
"achillesNodeVals",
"UTF-8");
165 Json::Value achillesEdgeVals = root.get(
"achillesEdgeVals",
"UTF-8");
167 std::cout << achillesNodeVals << std::endl;
174 achillesNodeVals = achillesNodeVals.get(
"params",
"UTF-8");
175 achillesEdgeVals = achillesEdgeVals.get(
"params",
"UTF-8");
181 array_4D achillesEdgeParams =
scaleEdgeActions(achillesEdgeVals,m_config.segmentSpan,m_config.theirMuscles,m_config.ourMuscles);
184 array_2D achillesNodeParams = scaleNodeActions(achillesNodeVals, m_config.highFreq, m_config.freqFeedbackMax);
187 setupCPGs(subject, achillesNodeParams, achillesEdgeParams);
189 Json::Value feedbackParams = root.get(
"feedbackVals",
"UTF-8");
190 feedbackParams = feedbackParams.get(
"params",
"UTF-8");
193 m_config.numStates = feedbackParams.get(
"numStates",
"UTF-8").asInt();
194 m_config.numActions = feedbackParams.get(
"numActions",
"UTF-8").asInt();
197 std::string nnFile = controlFilePath + feedbackParams.get(
"neuralFilename",
"UTF-8").asString();
199 nn =
new neuralNetwork(m_config.numStates, m_config.numStates*2, m_config.numActions);
201 nn->loadWeights(nnFile.c_str());
203 initConditions = subject.getSegmentCOM(m_config.segmentNumber);
204 for (
int i = 0; i < initConditions.size(); i++)
206 std::cout << initConditions[i] <<
" ";
208 std::cout << std::endl;
209 #ifdef LOGGING // Conditional compile for data logging
210 m_dataObserver.
onSetup(subject);
213 #if (0) // Conditional Compile for debug info
214 std::cout << *m_pCPGSys << std::endl;
223 std::vector<double> structureCOM = subject.getCOM(m_config.segmentNumber);
225 for(std::size_t i=0; i<3; i++)
227 metrics.push_back(structureCOM[i]);
232 Json::Value prevMetrics = root.get(
"metrics", Json::nullValue);
234 Json::Value subMetrics;
235 subMetrics[
"initial COM x"] = metrics[0];
236 subMetrics[
"initial COM y"] = metrics[1];
237 subMetrics[
"initial COM z"] = metrics[2];
239 prevMetrics.append(subMetrics);
240 root[
"metrics"] = prevMetrics;
243 payloadLog.open(controlFilename.c_str(),ofstream::out);
245 payloadLog << root << std::endl;
249 Json::Value PVal = root.get(
"propVals",
"UTF-8");
250 Json::Value DVal = root.get(
"derVals",
"UTF-8");
252 cout << PVal << endl;
255 PVal = PVal.get(
"params",
"UTF-8");
256 DVal = DVal.get(
"params",
"UTF-8");
258 if (PVal[0].isArray())
262 if (DVal[0].isArray())
268 P = (PVal.get(j, 0.0)).asDouble();
269 D = (DVal.get(j, 0.0)).asDouble();
278 if (m_updateTime >= m_config.controlTime)
281 std::vector<double> desComs = getFeedback(subject);
284 std::size_t numControllers = subject.getNumberofMuslces() * 3;
286 double descendingCommand = 0.0;
287 std::vector<double> desComs (numControllers, descendingCommand);
291 m_pCPGSys->
update(desComs, m_updateTime);
293 catch (std::runtime_error& e)
300 #ifdef LOGGING // Conditional compile for data logging
301 m_dataObserver.
onStep(subject, m_updateTime);
307 double currentHeight = subject.getSegmentCOM(m_config.segmentNumber)[1];
308 double currentHeightRear = subject.getSegmentCOM(6)[1];
311 if (currentHeight > m_config.maxHeight || currentHeight < m_config.minHeight || currentHeightRear > m_config.maxHeight || currentHeightRear < m_config.minHeight)
315 throw std::runtime_error(
"Height out of range");
326 std::vector<double> finalConditions = subject.getSegmentCOM(m_config.segmentNumber);
328 const double newX = finalConditions[0];
329 const double newZ = finalConditions[2];
330 const double oldX = initConditions[0];
331 const double oldZ = initConditions[2];
333 const double distanceMoved = sqrt((newX-oldX) * (newX-oldX) +
334 (newZ-oldZ) * (newZ-oldZ));
338 scores.push_back(-1.0);
342 scores.push_back(distanceMoved);
347 double totalEnergySpent=0;
351 for(std::size_t i=0; i<tmpStrings.size(); i++)
358 const double previousLength = stringHist.
restLengths[j-1];
359 const double currentLength = stringHist.
restLengths[j];
361 double motorSpeed = (currentLength-previousLength);
364 const double workDone = previousTension * motorSpeed;
365 totalEnergySpent += workDone;
369 scores.push_back(totalEnergySpent);
372 std::vector<double> structureCOM = subject.getCOM(m_config.segmentNumber);
374 for(std::size_t i=0; i<3; i++)
376 metrics.push_back(structureCOM[i]);
379 std::cout <<
"Dist travelled " << scores[0] << std::endl;
384 bool parsingSuccessful = reader.parse( FileHelpers::getFileString(controlFilename.c_str()), root );
385 if ( !parsingSuccessful )
388 std::cout <<
"Failed to parse configuration\n"
389 << reader.getFormattedErrorMessages();
390 throw std::invalid_argument(
"Bad filename for JSON");
393 Json::Value prevScores = root.get(
"scores", Json::nullValue);
394 Json::Value prevMetrics = root.get(
"metrics", Json::nullValue);
396 Json::Value subScores;
397 subScores[
"distance"] = scores[0];
398 subScores[
"energy"] = scores[1];
400 Json::Value subMetrics;
401 subMetrics[
"final COM x"] = metrics[0];
402 subMetrics[
"final COM y"] = metrics[1];
403 subMetrics[
"final COM z"] = metrics[2];
405 prevScores.append(subScores);
406 prevMetrics.append(subMetrics);
408 root[
"scores"] = prevScores;
409 root[
"metrics"] = prevMetrics;
412 payloadLog.open(controlFilename.c_str(),ofstream::out);
414 payloadLog << root << std::endl;
422 for(
size_t i = 0; i < m_leftFrontAchillesControllers.size(); i++)
424 delete m_leftFrontAchillesControllers[i];
426 m_leftFrontAchillesControllers.clear();
428 for(
size_t i = 0; i < m_rightFrontAchillesControllers.size(); i++)
430 delete m_rightFrontAchillesControllers[i];
432 m_rightFrontAchillesControllers.clear();
434 for(
size_t i = 0; i < m_leftRearAchillesControllers.size(); i++)
436 delete m_leftRearAchillesControllers[i];
438 m_leftRearAchillesControllers.clear();
440 for(
size_t i = 0; i < m_rightRearAchillesControllers.size(); i++)
442 delete m_rightRearAchillesControllers[i];
444 m_rightRearAchillesControllers.clear();
455 void JSONAOHierarchyControl::setupCPGs(
BaseQuadModelLearning& subject, array_2D achillesNodeActions, array_4D achillesEdgeActions)
459 std::vector <tgSpringCableActuator*> leftFrontAchillesMuscles = subject.
find<
tgSpringCableActuator> (
"left_front_achilles_tendon");
460 std::vector <tgSpringCableActuator*> rightFrontAchillesMuscles = subject.
find<
tgSpringCableActuator> (
"right_front_achilles_tendon");
462 std::vector <tgSpringCableActuator*> leftRearAchillesMuscles = subject.
find<
tgSpringCableActuator> (
"left_rear_achilles_tendon");
463 std::vector <tgSpringCableActuator*> rightRearAchillesMuscles = subject.
find<
tgSpringCableActuator> (
"right_rear_achilles_tendon");
465 CPGEquationsFB& m_CPGFBSys = *(tgCast::cast<CPGEquations, CPGEquationsFB>(m_pCPGSys));
473 for (std::size_t i = 0; i < leftFrontAchillesMuscles.size(); i++)
479 leftFrontAchillesMuscles[i]->attach(pStringControl);
484 m_leftFrontAchillesControllers.push_back(pStringControl);
488 for (std::size_t i = 0; i < m_leftFrontAchillesControllers.size(); i++)
491 assert(pStringInfo != NULL);
492 pStringInfo->
setConnectivity(m_leftFrontAchillesControllers, achillesEdgeActions);
498 if (m_config.useDefault)
500 pStringInfo->setupControl(*p_ipc);
504 pStringInfo->setupControl(*p_ipc, m_config.controlLength);
509 for (std::size_t i = 0; i < rightFrontAchillesMuscles.size(); i++)
515 rightFrontAchillesMuscles[i]->attach(pStringControl);
520 m_rightFrontAchillesControllers.push_back(pStringControl);
524 for (std::size_t i = 0; i < m_rightFrontAchillesControllers.size(); i++)
527 assert(pStringInfo != NULL);
528 pStringInfo->
setConnectivity(m_rightFrontAchillesControllers, achillesEdgeActions);
534 if (m_config.useDefault)
536 pStringInfo->setupControl(*p_ipc);
540 pStringInfo->setupControl(*p_ipc, m_config.controlLength);
545 for (std::size_t i = 0; i < leftRearAchillesMuscles.size(); i++)
551 leftRearAchillesMuscles[i]->attach(pStringControl);
556 m_leftRearAchillesControllers.push_back(pStringControl);
560 for (std::size_t i = 0; i < m_leftRearAchillesControllers.size(); i++)
563 assert(pStringInfo != NULL);
564 pStringInfo->
setConnectivity(m_leftRearAchillesControllers, achillesEdgeActions);
570 if (m_config.useDefault)
572 pStringInfo->setupControl(*p_ipc);
576 pStringInfo->setupControl(*p_ipc, m_config.controlLength);
581 for (std::size_t i = 0; i < rightRearAchillesMuscles.size(); i++)
587 rightRearAchillesMuscles[i]->attach(pStringControl);
592 m_rightRearAchillesControllers.push_back(pStringControl);
596 for (std::size_t i = 0; i < m_rightRearAchillesControllers.size(); i++)
599 assert(pStringInfo != NULL);
600 pStringInfo->
setConnectivity(m_rightRearAchillesControllers, achillesEdgeActions);
606 if (m_config.useDefault)
608 pStringInfo->setupControl(*p_ipc);
612 pStringInfo->setupControl(*p_ipc, m_config.controlLength);
618 array_2D JSONAOHierarchyControl::scaleNodeActions (Json::Value actions,
double highFreq,
double freqFeedbackMax)
620 std::size_t numControllers = actions.size();
621 std::size_t numActions = actions[0].size();
623 array_2D nodeActions(boost::extents[numControllers][numActions]);
625 array_2D limits(boost::extents[2][numActions]);
628 assert(numActions == 5);
630 limits[0][0] = m_config.lowFreq;
631 limits[1][0] = highFreq;
632 limits[0][1] = m_config.lowAmp;
633 limits[1][1] = m_config.highAmp;
634 limits[0][2] = m_config.freqFeedbackMin;
635 limits[1][2] = freqFeedbackMax;
636 limits[0][3] = m_config.ampFeedbackMin;
637 limits[1][3] = m_config.ampFeedbackMax;
638 limits[0][4] = m_config.phaseFeedbackMin;
639 limits[1][4] = m_config.phaseFeedbackMax;
641 Json::Value::iterator nodeIt = actions.begin();
644 for( std::size_t i = 0; i < numControllers; i++)
646 Json::Value nodeParam = *nodeIt;
647 for( std::size_t j = 0; j < numActions; j++)
649 nodeActions[i][j] = ( (nodeParam.get(j, 0.0)).asDouble() *
650 (limits[1][j] - limits[0][j])) + limits[0][j];
659 (Json::Value edgeParam,
int segmentSpan,
int theirMuscles,
int ourMuscles)
661 assert(edgeParam[0].size() == 2);
663 double lowerLimit = m_config.lowPhase;
664 double upperLimit = m_config.highPhase;
665 double range = upperLimit - lowerLimit;
667 array_4D actionList(boost::extents[segmentSpan][theirMuscles][ourMuscles][m_config.params]);
680 Json::Value::iterator edgeIt = edgeParam.end();
684 while (i < segmentSpan)
686 while(j < theirMuscles)
688 while(k < ourMuscles)
690 if (edgeIt == edgeParam.begin())
692 std::cout <<
"ran out before table populated!"
699 if (i == 1 && j == k)
707 Json::Value edgeParam = *edgeIt;
708 assert(edgeParam.size() == 2);
710 actionList[i][j][k][0] = edgeParam[0].asDouble();
713 actionList[i][j][k][1] = edgeParam[1].asDouble() *
714 (range) + lowerLimit;
730 std::cout<<
"Params used: " << count << std::endl;
732 assert(edgeParam.begin() == edgeIt);
740 std::vector<double> feedback;
744 double *inputs =
new double[m_config.numStates];
746 std::size_t n = allCables.size();
747 for(std::size_t i = 0; i != n; i++)
749 std::vector< std::vector<double> > actions;
752 std::vector<double > state = getCableState(cable);
755 for (std::size_t i = 0; i < state.size(); i++)
757 inputs[i]=state[i] / 2.0 + 0.5;
760 double *output = nn->feedForwardPattern(inputs);
761 vector<double> tmpAct;
762 for(
int j=0;j<m_config.numActions;j++)
764 tmpAct.push_back(output[j]);
766 actions.push_back(tmpAct);
768 std::vector<double> cableFeedback = transformFeedbackActions(actions);
770 feedback.insert(feedback.end(), cableFeedback.begin(), cableFeedback.end());
780 std::vector<double> state;
786 const double maxTension = cable.
getConfig().maxTens;
787 state.push_back((cable.
getTension() - maxTension / 2.0) / maxTension);
792 std::vector<double> JSONAOHierarchyControl::transformFeedbackActions(std::vector< std::vector<double> >& actions)
795 std::vector<double> feedback;
798 const std::size_t numControllers = 1;
799 const std::size_t numActions = m_config.numActions;
801 assert( actions.size() == numControllers);
802 assert( actions[0].size() == numActions);
805 for( std::size_t i = 0; i < numControllers; i++)
807 for( std::size_t j = 0; j < numActions; j++)
809 feedback.push_back(actions[i][j] * 2.0 - 1.0);
Contains the definition of class ImpedanceControl. $Id$.
JSONAOHierarchyControl(JSONAOHierarchyControl::Config config, std::string args, std::string resourcePath="")
void update(std::vector< double > &descCom, double dt)
std::deque< double > tensionHistory
virtual const double getTension() const
virtual const double getStartLength() const
void setConnectivity(const std::vector< tgCPGActuatorControl * > &allStrings, array_4D edgeParams)
std::deque< double > restLengths
Definition of the tgCPGStringControl observer class.
virtual void onSetup(BaseQuadModelLearning &subject)
A class to read a learning configuration from a .ini file.
Contains the definition of abstract base class tgSpringCableActuator. Assumes that the string is line...
virtual void onTeardown(BaseQuadModelLearning &subject)
A series of functions to assist with file input/output.
virtual array_4D scaleEdgeActions(Json::Value actions, int segmentSpan, int theirMuscles, int ourMuscles)
virtual void onStep(BaseQuadModelLearning &subject, double dt)
Contains the definition of class AnnealEvolution. Adapting NeuroEvolution to do Simulated Annealing...
Contains the definition of class tgBasicActuator.
const Config & getConfig() const
A controller for the template class BaseQuadModelLearning Implementing a CPG hierachy for MountainGoa...
std::vector< T * > find(const tgTagSearch &tagSearch)
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 ohighm=5, int thighm=5, double hf2=20.0, double ffMax2=0.0)
virtual void onStep(tgModel &model, double dt)
Definition of class CPGEquationsFB.
virtual void onSetup(tgModel &model)
virtual const double getCurrentLength() const
void notifyStep(double dt)
void assignNodeNumberFB(CPGEquationsFB &CPGSys, array_2D nodeParams)