27 #include "JSONQuadFeedbackControl.h"
37 #include "examples/learningSpines/tgCPGCableControl.h"
46 #include "examples/learningSpines/tgCPGCableControl.h"
48 #include "neuralNet/Neural Network v2/neuralNetwork.h"
50 #include <json/json.h>
61 const string strSpineTag =
"spine ";
62 const string strLeftShoulderTag =
"left shoulder ";
63 const string strLeftHipTag =
"left hip ";
65 const string strLeftFrontLegTag =
"left_front_leg ";
66 const string strLeftHindLegTag =
"left_hind_leg ";
67 const string strRightShoulderTag =
"right shoulder ";
68 const string strRightHipTag =
"right hip ";
69 const string strRightFrontLegTag =
"right_front_leg ";
70 const string strRightHindLegTag =
"right_hind_leg ";
100 lp, hp, kt, kp, kv, def, cl, lf, hf),
101 freqFeedbackMin(ffMin),
102 freqFeedbackMax(ffMax),
103 highFreqFeedbackMin(hffMin),
104 highFreqFeedbackMax(hffMax),
105 ampFeedbackMin(afMin),
106 ampFeedbackMax(afMax),
107 phaseFeedbackMin(pfMin),
108 phaseFeedbackMax(pfMax),
121 std::string resourcePath) :
129 JSONQuadFeedbackControl::~JSONQuadFeedbackControl()
144 bool parsingSuccessful = reader.parse( FileHelpers::getFileString(controlFilename.c_str()), root );
145 if ( !parsingSuccessful )
148 std::cout <<
"Failed to parse configuration\n"
149 << reader.getFormattedErrorMessages();
150 throw std::invalid_argument(
"Bad filename for JSON");
154 Json::Value nodeVals = root.get(
"nodeVals",
"UTF-8");
155 Json::Value edgeVals = root.get(
"edgeVals",
"UTF-8");
157 std::cout << nodeVals << std::endl;
159 nodeVals = nodeVals.get(
"params",
"UTF-8");
160 edgeVals = edgeVals.get(
"params",
"UTF-8");
163 Json::Value highEdgeVals = root.get(
"highVals",
"UTF-8");
164 highEdgeVals = highEdgeVals.get(
"params",
"UTF-8");
167 Json::Value highLowEdgeVals = root.get(
"hLowVals",
"UTF-8");
168 highLowEdgeVals = highLowEdgeVals.get(
"params",
"UTF-8");
175 n_muscSpine = spineMuscles.size();
176 n_muscHip = leftShoulderMuscles.size();
177 n_muscLeg = leftFrontLegMuscles.size();
180 array_2D nodeParams = scaleNodeActions(nodeVals);
183 setupCPGs(subject, nodeParams, edgeParams);
184 setupHighCPGs(nodeParams, highEdgeParams, highLowEdgeVals);
186 Json::Value feedbackParams = root.get(
"feedbackVals",
"UTF-8");
187 feedbackParams = feedbackParams.get(
"params",
"UTF-8");
190 m_config.numStates = feedbackParams.get(
"numStates",
"UTF-8").asInt();
191 m_config.numActions = feedbackParams.get(
"numActions",
"UTF-8").asInt();
194 std::string nnFile = controlFilePath + feedbackParams.get(
"neuralFilename",
"UTF-8").asString();
196 nn =
new neuralNetwork(m_config.numStates, m_config.numStates*2, m_config.numActions);
198 nn->loadWeights(nnFile.c_str());
200 initConditions = subject.getSegmentCOM(m_config.segmentNumber);
201 for (
int i = 0; i < initConditions.size(); i++)
203 std::cout << initConditions[i] <<
" ";
205 std::cout << std::endl;
206 #ifdef LOGGING // Conditional compile for data logging
207 m_dataObserver.
onSetup(subject);
210 #if (0) // Conditional Compile for debug info
211 std::cout << *m_pCPGSys << std::endl;
220 if (m_updateTime >= m_config.controlTime)
223 std::vector<double> desComs = getFeedback(subject);
226 std::size_t numControllers = subject.getNumberofMuslces() * 3;
228 double descendingCommand = 0.0;
229 std::vector<double> desComs (numControllers, descendingCommand);
233 m_pCPGSys->
update(desComs, m_updateTime);
235 catch (std::runtime_error& e)
242 #ifdef LOGGING // Conditional compile for data logging
243 m_dataObserver.
onStep(subject, m_updateTime);
249 double currentHeight = subject.getSegmentCOM(m_config.segmentNumber)[1];
252 if (currentHeight > m_config.maxHeight || currentHeight < m_config.minHeight)
256 throw std::runtime_error(
"Height out of range");
265 std::vector<double> finalConditions = subject.getSegmentCOM(m_config.segmentNumber);
267 const double newX = finalConditions[0];
268 const double newZ = finalConditions[2];
269 const double oldX = initConditions[0];
270 const double oldZ = initConditions[2];
272 const double distanceMoved = sqrt((newX-oldX) * (newX-oldX) +
273 (newZ-oldZ) * (newZ-oldZ));
279 scores.push_back(-1.0);
283 scores.push_back(distanceMoved);
288 double totalEnergySpent=0;
292 for(std::size_t i=0; i<tmpStrings.size(); i++)
299 const double previousLength = stringHist.
restLengths[j-1];
300 const double currentLength = stringHist.
restLengths[j];
302 double motorSpeed = (currentLength-previousLength);
305 const double workDone = previousTension * motorSpeed;
306 totalEnergySpent += workDone;
310 scores.push_back(totalEnergySpent);
312 std::cout <<
"Dist travelled " << scores[0] << std::endl;
317 bool parsingSuccessful = reader.parse( FileHelpers::getFileString(controlFilename.c_str()), root );
318 if ( !parsingSuccessful )
321 std::cout <<
"Failed to parse configuration\n"
322 << reader.getFormattedErrorMessages();
323 throw std::invalid_argument(
"Bad filename for JSON");
326 Json::Value prevScores = root.get(
"scores", Json::nullValue);
328 Json::Value subScores;
329 subScores[
"distance"] = scores[0];
330 subScores[
"energy"] = totalEnergySpent;
332 prevScores.append(subScores);
333 root[
"scores"] = prevScores;
336 payloadLog.open(controlFilename.c_str(),ofstream::out);
338 payloadLog << root << std::endl;
343 for (
size_t b = 0; b < 9; b++)
345 for(
size_t i = 0; i < m_controllers[b].size(); i++)
347 delete m_controllers[b][i];
349 m_controllers[b].clear();
352 for (
size_t i = 0; i < m_highControllers.size(); i++)
354 delete m_highControllers[i];
356 m_highControllers.clear();
359 void JSONQuadFeedbackControl::setupCPGs(
BaseSpineModelLearning& subject, array_2D nodeActions, array_4D edgeActions)
361 CPGEquationsFB& m_CPGFBSys = *(tgCast::cast<CPGEquations, CPGEquationsFB>(m_pCPGSys));
373 std::vector <tgSpringCableActuator*> allMuscles[9] = { spineMuscles, leftShoulderMuscles, leftFrontLegMuscles, rightShoulderMuscles, rightFrontLegMuscles, leftHipMuscles, leftHindLegMuscles, rightHipMuscles, rightHindLegMuscles };
377 for (std::size_t b = 0; b < n_bodyParts; b++)
379 for (std::size_t i = 0; i < allMuscles[b].size(); i++)
385 allMuscles[b][i]->attach(pStringControl);
389 array_2D nodeAction(boost::extents[1][nodeActions.shape()[1]]);
390 for (std::size_t a = 0; a < nodeActions.shape()[1]; a++)
391 nodeAction[0][a] = nodeActions[(b+1)/2 + 5][a];
398 m_controllers[b].push_back(pStringControl);
404 size_t actionsStart = 0;
406 for (
size_t b = 0; b < n_bodyParts; b++)
408 for (std::size_t i = 0; i < m_controllers[b].size(); i++)
412 size_t numMuscles = b == 0 ? n_muscSpine : (b % 2 ? n_muscHip : n_muscLeg);
414 array_4D edgeActionsForBodyPart(boost::extents[3][numMuscles][numMuscles][edgeActions.shape()[3]]);
416 for (
size_t x = 0; x < 3; x++)
for (
size_t y = 0; y < numMuscles; y++)
for (
size_t z = 0; z < numMuscles; z++)
for (
size_t w = 0; w < edgeActions.shape()[3]; w++)
417 edgeActionsForBodyPart[x][y][z][w] = edgeActions[x][y+actionsStart][z+actionsStart][w];
420 assert(pStringInfo != NULL);
421 pStringInfo->
setConnectivity(m_controllers[b], edgeActionsForBodyPart);
427 if (m_config.useDefault)
429 pStringInfo->setupControl(*p_ipc);
433 pStringInfo->setupControl(*p_ipc, m_config.controlLength);
437 actionsStart += b == 0 ? 16 : (b % 2 ? n_muscHip : n_muscLeg);
441 void JSONQuadFeedbackControl::setupHighCPGs(array_2D nodeActions, array_4D highEdgeActions, Json::Value highLowEdgeActions)
443 CPGEquationsFB& m_CPGFBSys = *(tgCast::cast<CPGEquations, CPGEquationsFB>(m_pCPGSys));
446 for (std::size_t b = 5; b < 10; b++)
453 array_2D nodeAction(boost::extents[1][nodeActions.shape()[1]]);
454 for (std::size_t a = 0; a < nodeActions.shape()[1]; a++)
455 nodeAction[0][a] = nodeActions[b][a];
460 m_highControllers.push_back(pStringControl);
467 for (std::size_t i = 0; i < m_highControllers.size(); i++)
470 assert(pStringInfo != NULL);
480 double lowerLimit = m_config.lowPhase;
481 double upperLimit = m_config.highPhase;
482 double range = upperLimit - lowerLimit;
484 Json::Value::iterator edgeIt = highLowEdgeActions.end();
489 for (
size_t b = 0; b < 5; b++)
493 std::vector<int> connectivityList;
494 std::vector<double> weights;
495 std::vector<double> phases;
497 Json::Value param = *edgeIt;
498 assert(param.size() == 2);
501 int n = b == 0 ? n_muscSpine : n_muscHip + n_muscLeg;
504 for (
size_t i = 0; i < n; i++, nodeStart++)
506 connectivityList.push_back(nodeStart);
507 weights.push_back(param[0].asDouble());
508 phases.push_back(param[1].asDouble() * (range) + lowerLimit);
511 int highCPGnode = b + n_muscSpine + n_muscHip*4 + n_muscLeg*4;
512 m_CPGFBSys.defineConnections(highCPGnode, connectivityList, weights, phases);
518 assert(highLowEdgeActions.begin() == edgeIt);
595 (Json::Value edgeParam)
603 assert(edgeParam[0].size() == 2);
605 double lowerLimit = m_config.lowPhase;
606 double upperLimit = m_config.highPhase;
607 double range = upperLimit - lowerLimit;
609 array_4D actionList(boost::extents[m_config.segmentSpan]
610 [m_config.theirMuscles]
611 [m_config.ourMuscles]
625 Json::Value::iterator edgeIt = edgeParam.end();
633 for (
size_t b = 0; b < n_bodyParts; b++)
635 while (i < m_config.segmentSpan)
640 if (b != 0 && i != 1)
651 if (edgeIt == edgeParam.begin())
653 std::cout <<
"ran out before table populated!"
655 cout << count << endl;
656 cout << b <<
" " << i <<
" " << j <<
" " << k <<
" " << musc << endl;
662 if (i == 1 && j == k)
669 cout << b <<
" " << i <<
" " << j <<
" " << k <<
" " << musc << endl;
671 Json::Value edgeParam1 = *edgeIt;
672 assert(edgeParam1.size() == 2);
674 actionList[i][j][k][0] = edgeParam1[0].asDouble();
677 actionList[i][j][k][1] = edgeParam1[1].asDouble() *
678 (range) + lowerLimit;
689 j = musc - (b > 0 ? (b % 2 ? n_muscHip : n_muscLeg) : 16);
696 musc += b % 2 ? n_muscHip : n_muscLeg;
699 std::cout<<
"Params used: " << count << std::endl;
701 assert(edgeParam.begin() == edgeIt);
708 assert(highEdgeParam[0].size() == 2);
710 double lowerLimit = m_config.lowPhase;
711 double upperLimit = m_config.highPhase;
712 double range = upperLimit - lowerLimit;
718 array_4D actionList(boost::extents[m_config.segmentSpan]
734 Json::Value::iterator highEdgeIt = highEdgeParam.end();
749 if (highEdgeIt == highEdgeParam.begin())
751 std::cout <<
"ran out before table populated!"
760 Json::Value edgeParam1 = *highEdgeIt;
761 assert(edgeParam1.size() == 2);
763 while (i < m_config.segmentSpan)
765 actionList[i][j][k][0] = edgeParam1[0].asDouble();
768 actionList[i][j][k][1] = edgeParam1[1].asDouble() *
769 (range) + lowerLimit;
783 std::cout<<
"Params used: " << count << std::endl;
785 assert(highEdgeParam.begin() == highEdgeIt);
790 array_2D JSONQuadFeedbackControl::scaleNodeActions (Json::Value actions)
792 std::size_t numControllers = actions.size();
793 std::size_t numActions = actions[0].size();
795 array_2D nodeActions(boost::extents[numControllers][numActions]);
797 array_2D limits(boost::extents[2][numActions]);
800 assert(numActions == 5);
802 limits[0][0] = m_config.lowFreq;
803 limits[1][0] = m_config.highFreq;
804 limits[0][1] = m_config.lowAmp;
805 limits[1][1] = m_config.highAmp;
806 limits[0][2] = m_config.freqFeedbackMin;
807 limits[1][2] = m_config.freqFeedbackMax;
808 limits[0][3] = m_config.ampFeedbackMin;
809 limits[1][3] = m_config.ampFeedbackMax;
810 limits[0][4] = m_config.phaseFeedbackMin;
811 limits[1][4] = m_config.phaseFeedbackMax;
813 Json::Value::iterator nodeIt = actions.begin();
816 for( std::size_t i = 0; i < numControllers; i++)
819 if (i > n_muscSpine + n_muscHip*4 + n_muscLeg*4)
823 limits[0][2] = m_config.highFreqFeedbackMin;
824 limits[1][2] = m_config.highFreqFeedbackMax;
826 Json::Value nodeParam = *nodeIt;
827 for( std::size_t j = 0; j < numActions; j++)
829 nodeActions[i][j] = ( (nodeParam.get(j, 0.0)).asDouble() *
830 (limits[1][j] - limits[0][j])) + limits[0][j];
841 std::vector<double> feedback;
844 const std::vector<tgSpringCableActuator*>& leftShoulderCables = subject.
find<
tgSpringCableActuator> (strLeftShoulderTag);
846 const std::vector<tgSpringCableActuator*>& leftFrontLegCables = subject.
find<
tgSpringCableActuator> (strLeftFrontLegTag);
848 const std::vector<tgSpringCableActuator*>& rightShoulderCables = subject.
find<
tgSpringCableActuator> (strRightShoulderTag);
850 const std::vector<tgSpringCableActuator*>& rightFrontLegCables = subject.
find<
tgSpringCableActuator> (strRightFrontLegTag);
851 const std::vector<tgSpringCableActuator*>& rightHindLegCables = subject.
find<
tgSpringCableActuator> (strRightHindLegTag);
853 const std::vector <tgSpringCableActuator*> allCables[9] = { spineCables, leftShoulderCables, leftFrontLegCables, rightShoulderCables, rightFrontLegCables, leftHipCables, leftHindLegCables, rightHipCables, rightHindLegCables };
855 double *inputs =
new double[m_config.numStates];
857 for (
size_t b = 0; b < 9; b++)
859 std::size_t n = allCables[b].size();
860 for(std::size_t i = 0; i != n; i++)
862 std::vector< std::vector<double> > actions;
865 std::vector<double > state = getCableState(cable);
868 for (std::size_t i = 0; i < state.size(); i++)
870 inputs[i]=state[i] / 2.0 + 0.5;
873 double *output =
nn->feedForwardPattern(inputs);
874 vector<double> tmpAct;
875 for(
int j=0;j<m_config.numActions;j++)
877 tmpAct.push_back(output[j]);
879 actions.push_back(tmpAct);
881 std::vector<double> cableFeedback = transformFeedbackActions(actions);
883 feedback.insert(feedback.end(), cableFeedback.begin(), cableFeedback.end());
888 std::size_t n = m_highControllers.size();
889 for (
size_t i = 0; i != n; i++)
891 std::vector< std::vector<double> > actions;
894 for (std::size_t i = 0; i < m_config.numStates; i++)
899 double *output =
nn->feedForwardPattern(inputs);
900 vector<double> tmpAct;
901 for(
int j=0;j<m_config.numActions;j++)
903 tmpAct.push_back(output[j]);
905 actions.push_back(tmpAct);
907 std::vector<double> cableFeedback = transformFeedbackActions(actions);
909 feedback.insert(feedback.end(), cableFeedback.begin(), cableFeedback.end());
919 std::vector<double> state;
925 const double maxTension = cable.
getConfig().maxTens;
926 state.push_back((cable.
getTension() - maxTension / 2.0) / maxTension);
931 std::vector<double> JSONQuadFeedbackControl::transformFeedbackActions(std::vector< std::vector<double> >& actions)
934 std::vector<double> feedback;
937 const std::size_t numControllers = 1;
938 const std::size_t numActions = m_config.numActions;
940 assert( actions.size() == numControllers);
941 assert( actions[0].size() == numActions);
944 for( std::size_t i = 0; i < numControllers; i++)
946 for( std::size_t j = 0; j < numActions; j++)
948 feedback.push_back(actions[i][j] * 2.0 - 1.0);
Contains the definition of class ImpedanceControl. $Id$.
virtual array_4D scaleEdgeActions(Json::Value edgeParam)
void update(std::vector< double > &descCom, double dt)
virtual void onTeardown(BaseSpineModelLearning &subject)
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.
A template base class for a tensegrity spine.
A class to read a learning configuration from a .ini file.
virtual void onStep(BaseSpineModelLearning &subject, double dt)
Contains the definition of abstract base class tgSpringCableActuator. Assumes that the string is line...
A series of functions to assist with file input/output.
JSONQuadFeedbackControl(JSONQuadFeedbackControl::Config config, std::string args, std::string resourcePath="")
Contains the definition of class AnnealEvolution. Adapting NeuroEvolution to do Simulated Annealing...
virtual void onSetup(BaseSpineModelLearning &subject)
Contains the definition of class tgBasicActuator.
virtual array_4D scaleHighEdgeActions(Json::Value highEdgeParam)
const Config & getConfig() const
std::vector< T * > find(const tgTagSearch &tagSearch)
virtual void onStep(tgModel &model, double dt)
Definition of class CPGEquationsFB.
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, double hffMin=0.0, double hffMax=0.0)
virtual void onSetup(tgModel &model)
virtual const double getCurrentLength() const
void notifyStep(double dt)
void assignNodeNumberFB(CPGEquationsFB &CPGSys, array_2D nodeParams)