28 #include "JSONMetricsFeedbackControl.h"
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>
89 lp, hp, kt, kp, kv, def, cl, lf, hf),
90 freqFeedbackMin(ffMin),
91 freqFeedbackMax(ffMax),
92 ampFeedbackMin(afMin),
93 ampFeedbackMax(afMax),
94 phaseFeedbackMin(pfMin),
95 phaseFeedbackMax(pfMax),
108 std::string resourcePath) :
116 JSONMetricsFeedbackControl::~JSONMetricsFeedbackControl()
128 bool parsingSuccessful = reader.parse( FileHelpers::getFileString(controlFilename.c_str()), root );
129 if ( !parsingSuccessful )
132 std::cout <<
"Failed to parse configuration\n"
133 << reader.getFormattedErrorMessages();
134 throw std::invalid_argument(
"Bad filename for JSON");
138 Json::Value nodeVals = root.get(
"nodeVals",
"UTF-8");
139 Json::Value edgeVals = root.get(
"edgeVals",
"UTF-8");
141 std::cout << nodeVals << std::endl;
143 nodeVals = nodeVals.get(
"params",
"UTF-8");
144 edgeVals = edgeVals.get(
"params",
"UTF-8");
147 array_2D nodeParams = scaleNodeActions(nodeVals);
149 setupCPGs(subject, nodeParams, edgeParams);
151 Json::Value feedbackParams = root.get(
"feedbackVals",
"UTF-8");
152 feedbackParams = feedbackParams.get(
"params",
"UTF-8");
155 m_config.numStates = feedbackParams.get(
"numStates",
"UTF-8").asInt();
156 m_config.numActions = feedbackParams.get(
"numActions",
"UTF-8").asInt();
159 std::string nnFile = controlFilePath + feedbackParams.get(
"neuralFilename",
"UTF-8").asString();
161 nn =
new neuralNetwork(m_config.numStates, m_config.numStates*2, m_config.numActions);
163 nn->loadWeights(nnFile.c_str());
165 initConditions = subject.getSegmentCOM(m_config.segmentNumber);
166 for (
int i = 0; i < initConditions.size(); i++)
168 std::cout << initConditions[i] <<
" ";
170 std::cout << std::endl;
171 #ifdef LOGGING // Conditional compile for data logging
172 m_dataObserver.
onSetup(subject);
175 #if (0) // Conditional Compile for debug info
176 std::cout << *m_pCPGSys << std::endl;
185 std::vector<double> structureCOM = subject.getCOM(m_config.segmentNumber);
187 for(std::size_t i=0; i<3; i++)
189 metrics.push_back(structureCOM[i]);
194 Json::Value prevMetrics = root.get(
"metrics", Json::nullValue);
196 Json::Value subMetrics;
197 subMetrics[
"initial COM x"] = metrics[0];
198 subMetrics[
"initial COM y"] = metrics[1];
199 subMetrics[
"initial COM z"] = metrics[2];
201 prevMetrics.append(subMetrics);
202 root[
"metrics"] = prevMetrics;
205 payloadLog.open(controlFilename.c_str(),ofstream::out);
207 payloadLog << root << std::endl;
213 for(std::size_t i=0; i<tmpStrings.size(); i++){
214 m_muscleTensionsAll.push_back(vector <double> ());
215 m_muscleLengthsAll.push_back(vector <double> ());
224 if (m_updateTime >= m_config.controlTime)
227 std::vector<double> desComs = getFeedback(subject);
230 std::size_t numControllers = subject.getNumberofMuslces() * 3;
232 double descendingCommand = 0.0;
233 std::vector<double> desComs (numControllers, descendingCommand);
237 m_pCPGSys->
update(desComs, m_updateTime);
239 catch (std::runtime_error& e)
246 #ifdef LOGGING // Conditional compile for data logging
247 m_dataObserver.
onStep(subject, m_updateTime);
253 double currentHeight = subject.getSegmentCOM(m_config.segmentNumber)[1];
256 if (currentHeight > m_config.maxHeight || currentHeight < m_config.minHeight)
260 throw std::runtime_error(
"Height out of range");
265 static int count = 0;
267 m_timeStep.push_back(m_totalTime);
270 std::vector<double> structureCOM = subject.getCOM(m_config.segmentNumber);
271 m_quadCOM.push_back(structureCOM);
277 for(std::size_t i=0; i<tmpStrings.size(); i++)
279 double tension = tmpStrings[i]->getTension();
280 m_muscleTensionsAll.at(i).push_back(tension);
284 for(std::size_t i=0; i<tmpStrings.size(); i++)
286 double length = tmpStrings[i]->getCurrentLength();
287 m_muscleLengthsAll.at(i).push_back(length);
304 std::vector<double> finalConditions = subject.getSegmentCOM(m_config.segmentNumber);
306 const double newX = finalConditions[0];
307 const double newZ = finalConditions[2];
308 const double oldX = initConditions[0];
309 const double oldZ = initConditions[2];
311 const double distanceMoved = sqrt((newX-oldX) * (newX-oldX) +
312 (newZ-oldZ) * (newZ-oldZ));
316 scores.push_back(-1.0);
320 scores.push_back(distanceMoved);
325 double totalEnergySpent=0;
329 for(std::size_t i=0; i<tmpStrings.size(); i++)
336 const double previousLength = stringHist.
restLengths[j-1];
337 const double currentLength = stringHist.
restLengths[j];
339 double motorSpeed = (currentLength-previousLength);
342 const double workDone = previousTension * motorSpeed;
343 totalEnergySpent += workDone;
347 scores.push_back(totalEnergySpent);
350 std::vector<double> structureCOM = subject.getCOM(m_config.segmentNumber);
352 for(std::size_t i=0; i<3; i++)
354 metrics.push_back(structureCOM[i]);
357 std::cout <<
"Dist travelled " << scores[0] << std::endl;
362 bool parsingSuccessful = reader.parse( FileHelpers::getFileString(controlFilename.c_str()), root );
363 if ( !parsingSuccessful )
366 std::cout <<
"Failed to parse configuration\n"
367 << reader.getFormattedErrorMessages();
368 throw std::invalid_argument(
"Bad filename for JSON");
371 Json::Value prevScores = root.get(
"scores", Json::nullValue);
372 Json::Value prevMetrics = root.get(
"metrics", Json::nullValue);
374 Json::Value subScores;
375 subScores[
"distance"] = scores[0];
376 subScores[
"energy"] = scores[1];
378 Json::Value subMetrics;
379 subMetrics[
"final COM x"] = metrics[0];
380 subMetrics[
"final COM y"] = metrics[1];
381 subMetrics[
"final COM z"] = metrics[2];
383 prevScores.append(subScores);
384 prevMetrics.append(subMetrics);
386 root[
"scores"] = prevScores;
387 root[
"metrics"] = prevMetrics;
390 payloadLog.open(controlFilename.c_str(),ofstream::out);
392 payloadLog << root << std::endl;
395 printMetrics(subject);
401 for(
size_t i = 0; i < m_spineControllers.size(); i++)
403 delete m_spineControllers[i];
405 m_spineControllers.clear();
408 void JSONMetricsFeedbackControl::setupCPGs(
BaseQuadModelLearning& subject, array_2D nodeActions, array_4D edgeActions)
413 CPGEquationsFB& m_CPGFBSys = *(tgCast::cast<CPGEquations, CPGEquationsFB>(m_pCPGSys));
415 for (std::size_t i = 0; i < spineMuscles.size(); i++)
421 spineMuscles[i]->attach(pStringControl);
426 m_spineControllers.push_back(pStringControl);
430 for (std::size_t i = 0; i < m_spineControllers.size(); i++)
433 assert(pStringInfo != NULL);
440 if (m_config.useDefault)
442 pStringInfo->setupControl(*p_ipc);
446 pStringInfo->setupControl(*p_ipc, m_config.controlLength);
452 array_2D JSONMetricsFeedbackControl::scaleNodeActions (Json::Value actions)
454 std::size_t numControllers = actions.size();
455 std::size_t numActions = actions[0].size();
457 array_2D nodeActions(boost::extents[numControllers][numActions]);
459 array_2D limits(boost::extents[2][numActions]);
462 assert(numActions == 5);
464 limits[0][0] = m_config.lowFreq;
465 limits[1][0] = m_config.highFreq;
466 limits[0][1] = m_config.lowAmp;
467 limits[1][1] = m_config.highAmp;
468 limits[0][2] = m_config.freqFeedbackMin;
469 limits[1][2] = m_config.freqFeedbackMax;
470 limits[0][3] = m_config.ampFeedbackMin;
471 limits[1][3] = m_config.ampFeedbackMax;
472 limits[0][4] = m_config.phaseFeedbackMin;
473 limits[1][4] = m_config.phaseFeedbackMax;
475 Json::Value::iterator nodeIt = actions.begin();
478 for( std::size_t i = 0; i < numControllers; i++)
480 Json::Value nodeParam = *nodeIt;
481 for( std::size_t j = 0; j < numActions; j++)
483 nodeActions[i][j] = ( (nodeParam.get(j, 0.0)).asDouble() *
484 (limits[1][j] - limits[0][j])) + limits[0][j];
495 std::vector<double> feedback;
499 double *inputs =
new double[m_config.numStates];
501 std::size_t n = spineCables.size();
502 for(std::size_t i = 0; i != n; i++)
504 std::vector< std::vector<double> > actions;
507 std::vector<double > state = getCableState(cable);
510 for (std::size_t i = 0; i < state.size(); i++)
512 inputs[i]=state[i] / 2.0 + 0.5;
515 double *output = nn->feedForwardPattern(inputs);
516 vector<double> tmpAct;
517 for(
int j=0;j<m_config.numActions;j++)
519 tmpAct.push_back(output[j]);
521 actions.push_back(tmpAct);
523 std::vector<double> cableFeedback = transformFeedbackActions(actions);
525 feedback.insert(feedback.end(), cableFeedback.begin(), cableFeedback.end());
536 std::vector<double> state;
542 const double maxTension = cable.
getConfig().maxTens;
543 state.push_back((cable.
getTension() - maxTension / 2.0) / maxTension);
548 std::vector<double> JSONMetricsFeedbackControl::transformFeedbackActions(std::vector< std::vector<double> >& actions)
551 std::vector<double> feedback;
554 const std::size_t numControllers = 1;
555 const std::size_t numActions = m_config.numActions;
557 assert( actions.size() == numControllers);
558 assert( actions[0].size() == numActions);
561 for( std::size_t i = 0; i < numControllers; i++)
563 for( std::size_t j = 0; j < numActions; j++)
565 feedback.push_back(actions[i][j] * 2.0 - 1.0);
577 for(std::size_t i=0; i<tmpStrings.size(); i++)
579 std::string delim =
" ";
580 std::string muscle = tmpStrings[i]->getTagStr(delim);
581 cout << muscle << endl;
586 for (
int i = 0; i < m_timeStep.size(); ++i) {
587 cout << m_timeStep[i] <<
",";
592 for (
int i = 0; i < m_muscleTensionsAll.size(); i++){
593 for(
int j = 0; j < m_muscleTensionsAll[i].size(); j++){
594 cout << m_muscleTensionsAll[i][j] <<
",";
600 for (
int i = 0; i < m_muscleLengthsAll.size(); i++){
601 for(
int j = 0; j < m_muscleLengthsAll[i].size(); j++){
602 cout << m_muscleLengthsAll[i][j] <<
",";
Contains the definition of class ImpedanceControl. $Id$.
void update(std::vector< double > &descCom, double dt)
std::deque< double > tensionHistory
virtual void onSetup(BaseQuadModelLearning &subject)
virtual const double getTension() const
virtual const double getStartLength() const
virtual void onStep(BaseQuadModelLearning &subject, double dt)
void setConnectivity(const std::vector< tgCPGActuatorControl * > &allStrings, array_4D edgeParams)
std::deque< double > restLengths
virtual void onTeardown(BaseQuadModelLearning &subject)
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.
const Config & getConfig() const
std::vector< T * > find(const tgTagSearch &tagSearch)
JSONMetricsFeedbackControl(JSONMetricsFeedbackControl::Config config, std::string args, std::string resourcePath="")
virtual void onStep(tgModel &model, double dt)
virtual array_4D scaleEdgeActions(Json::Value edgeParam)
Definition of class CPGEquationsFB.
virtual void onSetup(tgModel &model)
virtual const double getCurrentLength() const
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)
void notifyStep(double dt)
void assignNodeNumberFB(CPGEquationsFB &CPGSys, array_2D nodeParams)