39 #include "examples/learningSpines/tgCPGCableControl.h"
47 #include "examples/learningSpines/tgCPGCableControl.h"
82 lp, hp, kt, kp, kv, def, cl, lf, hf),
83 freqFeedbackMin(ffMin),
84 freqFeedbackMax(ffMax),
85 ampFeedbackMin(afMin),
86 ampFeedbackMax(afMax),
87 phaseFeedbackMin(pfMin),
88 phaseFeedbackMax(pfMax),
100 std::string resourcePath,
107 feedbackConfigFilename(fc),
109 feedbackEvolution(args +
"_fb", fc, resourcePath),
111 feedbackLearning(false),
112 goalConfigFilename(gc),
114 goalEvolution(args +
"_goal", gc, resourcePath),
118 if (resourcePath !=
"")
127 feedbackConfigData.readFile(path + feedbackConfigFilename);
128 feedbackLearning = feedbackConfigData.getintvalue(
"learning");
130 goalConfigData.readFile(path + goalConfigFilename);
131 goalLearning = goalConfigData.getintvalue(
"learning");
145 feedbackAdapter.
initialize(&feedbackEvolution,
155 std::vector<double> state;
159 array_2D nodeParams = scaleNodeActions(nodeAdapter.step(dt, state));
161 setupCPGs(subject, nodeParams, edgeParams);
163 initConditions = subject.getSegmentCOM(m_config.segmentNumber);
164 #ifdef LOGGING // Conditional compile for data logging
165 m_dataObserver.
onSetup(subject);
168 #if (0) // Conditional Compile for debug info
169 std::cout << *m_pCPGSys << std::endl;
174 const BaseSpineModelGoal* goalSubject = tgCast::cast<BaseSpineModelLearning, BaseSpineModelGoal>(subject);
175 std::cout << goalSubject->goalBoxPosition() << std::endl;
181 if (m_updateTime >= m_config.controlTime)
185 const BaseSpineModelGoal* goalSubject = tgCast::cast<BaseSpineModelLearning, BaseSpineModelGoal>(subject);
186 std::vector<double> desComs = getGoalFeedback(goalSubject);
187 #else // Goal feedback vs others
189 std::vector<double> desComs = getFeedback(subject);
191 #else // cable feedback vs no feedback
192 std::size_t numControllers = subject.getNumberofMuslces() * 3;
194 double descendingCommand = 0.0;
195 std::vector<double> desComs (numControllers, descendingCommand);
200 m_pCPGSys->
update(desComs, m_updateTime);
202 catch (std::runtime_error& e)
209 #ifdef LOGGING // Conditional compile for data logging
210 m_dataObserver.
onStep(subject, m_updateTime);
216 double currentHeight = subject.getSegmentCOM(m_config.segmentNumber)[1];
219 if (currentHeight > 25 || currentHeight < 1.0)
223 throw std::runtime_error(
"Height out of range");
232 const BaseSpineModelGoal* goalSubject = tgCast::cast<BaseSpineModelLearning, BaseSpineModelGoal>(subject);
234 const double distanceMoved = calculateDistanceMoved(goalSubject);
238 scores.push_back(-1.0);
242 scores.push_back(distanceMoved);
247 double totalEnergySpent=0;
249 std::vector<tgSpringCableActuator* > tmpStrings = subject.getAllMuscles();
251 for(
int i=0; i<tmpStrings.size(); i++)
258 const double previousLength = stringHist.
restLengths[j-1];
259 const double currentLength = stringHist.
restLengths[j];
261 double motorSpeed = (currentLength-previousLength);
264 const double workDone = previousTension * motorSpeed;
265 totalEnergySpent += workDone;
269 scores.push_back(totalEnergySpent);
272 nodeAdapter.endEpisode(scores);
273 feedbackAdapter.endEpisode(scores);
274 goalAdapter.endEpisode(scores);
279 for(
size_t i = 0; i < m_allControllers.size(); i++)
281 delete m_allControllers[i];
283 m_allControllers.clear();
286 void SpineGoalControl::setupCPGs(
BaseSpineModelLearning& subject, array_2D nodeActions, array_4D edgeActions)
289 std::vector <tgSpringCableActuator*> allMuscles = subject.getAllMuscles();
291 CPGEquationsFB& m_CPGFBSys = *(tgCast::cast<CPGEquations, CPGEquationsFB>(m_pCPGSys));
293 for (std::size_t i = 0; i < allMuscles.size(); i++)
299 allMuscles[i]->attach(pStringControl);
304 m_allControllers.push_back(pStringControl);
308 for (std::size_t i = 0; i < m_allControllers.size(); i++)
311 assert(pStringInfo != NULL);
318 if (m_config.useDefault)
320 pStringInfo->setupControl(*p_ipc);
324 pStringInfo->setupControl(*p_ipc, m_config.controlLength);
330 array_2D SpineGoalControl::scaleNodeActions
331 (vector< vector <double> > actions)
333 std::size_t numControllers =
nodeConfigData.getintvalue(
"numberOfControllers");
334 std::size_t numActions =
nodeConfigData.getintvalue(
"numberOfActions");
336 assert( actions.size() == numControllers);
337 assert( actions[0].size() == numActions);
339 array_2D nodeActions(boost::extents[numControllers][numActions]);
341 array_2D limits(boost::extents[2][numActions]);
344 assert(numActions == 5);
346 limits[0][0] = m_config.lowFreq;
347 limits[1][0] = m_config.highFreq;
348 limits[0][1] = m_config.lowAmp;
349 limits[1][1] = m_config.highAmp;
350 limits[0][2] = m_config.freqFeedbackMin;
351 limits[1][2] = m_config.freqFeedbackMax;
352 limits[0][3] = m_config.ampFeedbackMin;
353 limits[1][3] = m_config.ampFeedbackMax;
354 limits[0][4] = m_config.phaseFeedbackMin;
355 limits[1][4] = m_config.phaseFeedbackMax;
358 for( std::size_t i = 0; i < numControllers; i++)
360 for( std::size_t j = 0; j < numActions; j++)
362 nodeActions[i][j] = ( actions[i][j] *
363 (limits[1][j] - limits[0][j])) + limits[0][j];
373 std:vector<double> feedback;
377 const std::vector<tgSpringCableActuator*>& allCables = subject.getAllMuscles();
379 std::size_t n = allCables.size();
380 for(std::size_t i = 0; i != n; i++)
383 std::vector<double > state = getCableState(cable);
384 std::vector< std::vector<double> > actions = feedbackAdapter.step(m_updateTime, state);
385 std::vector<double> cableFeedback = transformFeedbackActions(actions, feedbackConfigData);
387 feedback.insert(feedback.end(), cableFeedback.begin(), cableFeedback.end());
394 std::vector<double> SpineGoalControl::getGoalFeedback(
const BaseSpineModelGoal* subject)
398 const std::vector<tgSpringCableActuator*>& allCables = subject->getAllMuscles();
400 std::size_t n = allCables.size();
401 std::size_t nA = feedbackConfigData.getintvalue(
"numberOfActions");
404 std:vector<double> feedback;
410 std::vector<double> currentPosition = subject->getSegmentCOM(m_config.segmentNumber);
412 assert(currentPosition.size() == 3);
414 btVector3 currentPosVector(currentPosition[0], currentPosition[1], currentPosition[2]);
416 btVector3 goalPosition = subject->goalBoxPosition();
418 btVector3 desiredHeading = (goalPosition - currentPosVector).normalize();
421 #if (1) // Direct to CPG or set impedance controller tensions
423 int m = subject->getSegments() - 1;
425 for (
int i = 0; i != m; i++)
428 std::vector<double> state;
429 state.push_back(desiredHeading.getX());
430 state.push_back(desiredHeading.getZ());
432 assert(state[0] >= -1.0 && state[0] <= 1.0);
433 assert(state[1] >= -1.0 && state[1] <= 1.0);
435 std::vector< std::vector<double> > actions = goalAdapter.step(m_updateTime, state);
437 std::vector<double> segmentFeedback = transformFeedbackActions(actions, goalConfigData);
439 feedback.insert(feedback.end(), segmentFeedback.begin(), segmentFeedback.end());
442 assert (feedback.size() == n * nA);
447 setGoalTensions(subject, desiredHeading);
449 std::vector<double> zeroFB(n * nA, 0.0);
451 feedback.insert(feedback.end(), zeroFB.begin(), zeroFB.end());
454 assert (feedback.size() == n * nA);
456 #if (0) //Switch for cable based feedback
457 for(std::size_t i = 0; i != n; i++)
460 std::vector<double > state = getCableState(cable);
461 std::vector< std::vector<double> > actions = feedbackAdapter.step(m_updateTime, state);
462 std::vector<double> cableFeedback = transformFeedbackActions(actions, feedbackConfigData);
464 for (std::size_t j = 0; j != nA; j++)
466 feedback[i * nA + j] += cableFeedback[j];
474 void SpineGoalControl::setGoalTensions(
const BaseSpineModelGoal* subject, btVector3& desiredHeading)
476 std::vector<double> state;
477 state.push_back(desiredHeading.getX());
478 state.push_back(desiredHeading.getZ());
480 assert(state[0] >= -1.0 && state[0] <= 1.0);
481 assert(state[1] >= -1.0 && state[1] <= 1.0);
483 std::size_t numActions = goalConfigData.getintvalue(
"numberOfActions");
485 std::vector< std::vector<double> > actions = goalAdapter.step(m_updateTime, state);
487 for (std::size_t i = 0; i < subject->getSegments() - 1; i++)
489 for (std::size_t j = 0; j < numActions; j++)
491 tgCPGCableControl* cableControl = tgCast::cast<tgCPGActuatorControl, tgCPGCableControl>(m_allControllers[i * numActions + j]);
501 std::vector<double> state;
507 const double maxTension = cable.
getConfig().maxTens;
508 state.push_back((cable.
getTension() - maxTension / 2.0) / maxTension);
513 std::vector<double> SpineGoalControl::transformFeedbackActions(std::vector< std::vector<double> >& actions,
configuration& configData)
516 std:vector<double> feedback;
518 std::size_t numControllers = configData.getintvalue(
"numberOfControllers");
519 std::size_t numActions = configData.getintvalue(
"numberOfActions");
521 assert( actions.size() == numControllers);
522 assert( actions[0].size() == numActions);
525 for( std::size_t i = 0; i < numControllers; i++)
527 for( std::size_t j = 0; j < numActions; j++)
529 feedback.push_back(actions[i][j] * 2.0 - 1.0);
536 double SpineGoalControl::calculateDistanceMoved(
const BaseSpineModelGoal* subject)
const
538 std::vector<double> finalConditions = subject->getSegmentCOM(m_config.segmentNumber);
540 const btVector3 goalPos = subject->goalBoxPosition();
542 std::cout << goalPos << std::endl;
544 double x= finalConditions[0] - goalPos.getX();
545 double z= finalConditions[2] - goalPos.getZ();
546 double distanceNew=sqrt(x*x + z*z);
547 double xx=initConditions[0]-goalPos.getX();
548 double zz=initConditions[2]-goalPos.getZ();
549 double distanceOld=sqrt(xx*xx + zz*zz);
550 double distanceMoved=distanceOld-distanceNew;
555 return distanceMoved;
Contains the definition of class ImpedanceControl. $Id$.
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 tf=0.0)
void initialize(NeuroEvolution *evo, bool isLearning, configuration config)
void update(std::vector< double > &descCom, double dt)
AnnealEvolution edgeEvolution
std::deque< double > tensionHistory
virtual const double getTension() const
virtual const double getStartLength() const
void setConnectivity(const std::vector< tgCPGActuatorControl * > &allStrings, array_4D edgeParams)
SpineGoalControl(SpineGoalControl::Config config, std::string args, std::string resourcePath="", std::string ec="edgeConfig.ini", std::string nc="nodeConfig.ini", std::string fc="feedbackConfig.ini", std::string gc="goalConfig.ini")
void updateTensionSetpoint(double newTension)
std::deque< double > restLengths
configuration nodeConfigData
Definition of the tgCPGStringControl observer class.
Implementing the tetrahedral complex spine inspired by Tom Flemons.
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.
AnnealAdapter edgeAdapter
virtual void onTeardown(BaseSpineModelLearning &subject)
static std::string getResourcePath(std::string relPath)
Contains the definition of class AnnealEvolution. Adapting NeuroEvolution to do Simulated Annealing...
Contains the definition of class tgBasicActuator.
A controller for the template class BaseSpineModelLearning.
const Config & getConfig() const
virtual array_4D scaleEdgeActions(std::vector< std::vector< double > > actions)
virtual void onStep(tgModel &model, double dt)
virtual void onSetup(BaseSpineModelLearning &subject)
Definition of class CPGEquationsFB.
void initialize(AnnealEvolution *evo, bool isLearning, configuration config)
Rand seeding simular to the evolution and terrain classes.
virtual void onSetup(tgModel &model)
virtual void onStep(BaseSpineModelLearning &subject, double dt)
virtual const double getCurrentLength() const
void notifyStep(double dt)
void assignNodeNumberFB(CPGEquationsFB &CPGSys, array_2D nodeParams)