Fix and reconfigure demo by rebuilding walkers every time.
This commit is contained in:
@@ -42,7 +42,7 @@ class NNWalker;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef POPULATION_SIZE
|
#ifndef POPULATION_SIZE
|
||||||
#define POPULATION_SIZE 10 // number of walkers in the population
|
#define POPULATION_SIZE 100 // number of walkers in the population
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef EVALUATION_DURATION
|
#ifndef EVALUATION_DURATION
|
||||||
@@ -93,14 +93,6 @@ class NNWalker;
|
|||||||
#define REBUILD_WALKER true // if the walker should be rebuilt on mutation
|
#define REBUILD_WALKER true // if the walker should be rebuilt on mutation
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef RANDOM_WALKER_MOVEMENT
|
|
||||||
#define RANDOM_WALKER_MOVEMENT false // movement is chosen randomly and not via neural network
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef RANDOMIZE_WALKER_DIMENSIONS
|
|
||||||
#define RANDOMIZE_WALKER_DIMENSIONS false // if the walker dimensions should be mutated or not
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef TIMESTAMP_TIME
|
#ifndef TIMESTAMP_TIME
|
||||||
#define TIMESTAMP_TIME 2000.0f // delay between speed up timestamps
|
#define TIMESTAMP_TIME 2000.0f // delay between speed up timestamps
|
||||||
#endif
|
#endif
|
||||||
@@ -158,7 +150,7 @@ public:
|
|||||||
m_legLength(0.45f),
|
m_legLength(0.45f),
|
||||||
m_foreLegLength(0.75f),
|
m_foreLegLength(0.75f),
|
||||||
m_foreLegRadius(0.08f),
|
m_foreLegRadius(0.08f),
|
||||||
m_parallelEvaluations(1.0f),
|
m_parallelEvaluations(10.0f),
|
||||||
// others
|
// others
|
||||||
m_resetPosition(0,0,0),
|
m_resetPosition(0,0,0),
|
||||||
m_SimulationTime(0),
|
m_SimulationTime(0),
|
||||||
@@ -188,14 +180,6 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual void exitPhysics();
|
virtual void exitPhysics();
|
||||||
|
|
||||||
/**
|
|
||||||
* Spawn a walker at startPosition.
|
|
||||||
* @param index
|
|
||||||
* @param startPosition
|
|
||||||
* @param fixedRootBodyPosition
|
|
||||||
*/
|
|
||||||
void spawnWalker(int index, const btVector3& startPosition, bool fixedRootBodyPosition);
|
|
||||||
|
|
||||||
virtual bool keyboardCallback(int key, int state);
|
virtual bool keyboardCallback(int key, int state);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -381,9 +365,7 @@ public:
|
|||||||
//initialize random weights
|
//initialize random weights
|
||||||
for(int i = 0;i < BODYPART_COUNT;i++){
|
for(int i = 0;i < BODYPART_COUNT;i++){
|
||||||
for(int j = 0;j < JOINT_COUNT;j++){
|
for(int j = 0;j < JOINT_COUNT;j++){
|
||||||
//TODO: clean this up
|
|
||||||
m_sensoryMotorWeights[i+j*BODYPART_COUNT] = ((double) rand() / (RAND_MAX))*2.0f-1.0f;
|
m_sensoryMotorWeights[i+j*BODYPART_COUNT] = ((double) rand() / (RAND_MAX))*2.0f-1.0f;
|
||||||
//m_sensoryMotorWeights[i+j*BODYPART_COUNT] = 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -408,10 +390,6 @@ public:
|
|||||||
|
|
||||||
NN3DWalkersExample* nnWalkersDemo = (NN3DWalkersExample*)m_ownerWorld->getWorldUserInfo();
|
NN3DWalkersExample* nnWalkersDemo = (NN3DWalkersExample*)m_ownerWorld->getWorldUserInfo();
|
||||||
|
|
||||||
clearTouchSensors(); // set touch sensors to zero
|
|
||||||
|
|
||||||
randomizeSensoryMotorWeights(); // set random sensory motor weights for neural network layer
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Setup geometry
|
// Setup geometry
|
||||||
m_shapes[0] = new btCapsuleShape(rootBodyRadius, rootBodyHeight); // root body capsule
|
m_shapes[0] = new btCapsuleShape(rootBodyRadius, rootBodyHeight); // root body capsule
|
||||||
@@ -443,7 +421,6 @@ public:
|
|||||||
m_bodyTouchSensorIndexMap.insert(btHashPtr(m_bodies[0]), 0);
|
m_bodyTouchSensorIndexMap.insert(btHashPtr(m_bodies[0]), 0);
|
||||||
|
|
||||||
btHingeConstraint* hingeC;
|
btHingeConstraint* hingeC;
|
||||||
//btConeTwistConstraint* coneC;
|
|
||||||
|
|
||||||
btTransform localA, localB, localC;
|
btTransform localA, localB, localC;
|
||||||
|
|
||||||
@@ -494,7 +471,7 @@ public:
|
|||||||
hingeC->setLimit(btScalar(-SIMD_PI_8), btScalar(0.2));
|
hingeC->setLimit(btScalar(-SIMD_PI_8), btScalar(0.2));
|
||||||
m_joints[1+2*i] = hingeC;
|
m_joints[1+2*i] = hingeC;
|
||||||
|
|
||||||
//test if we cause a collision with priorly inserted bodies. This prevents the walkers to have to resolve collisions on startup
|
//test if we cause a collision with priorly inserted bodies. This prevents the walkers from having to resolve collisions on startup
|
||||||
|
|
||||||
m_ownerWorld->addRigidBody(m_bodies[1+2*i]); // add thigh bone
|
m_ownerWorld->addRigidBody(m_bodies[1+2*i]); // add thigh bone
|
||||||
m_ownerWorld->addConstraint(m_joints[2*i], true); // connect thigh bone with root
|
m_ownerWorld->addConstraint(m_joints[2*i], true); // connect thigh bone with root
|
||||||
@@ -524,6 +501,11 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
removeFromWorld(); // the walker should not yet be in the world
|
removeFromWorld(); // the walker should not yet be in the world
|
||||||
|
|
||||||
|
clearTouchSensors(); // set touch sensors to zero
|
||||||
|
|
||||||
|
randomizeSensoryMotorWeights(); // set random sensory motor weights for neural network layer
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~NNWalker ()
|
virtual ~NNWalker ()
|
||||||
@@ -637,12 +619,13 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void resetAt(const btVector3& position) {
|
void resetAt(const btVector3& position) {
|
||||||
|
removeFromWorld();
|
||||||
btTransform resetPosition(btQuaternion::getIdentity(), position);
|
btTransform resetPosition(btQuaternion::getIdentity(), position);
|
||||||
|
|
||||||
for (int i = 0; i < 2*NUM_WALKER_LEGS; i++)
|
for (int i = 0; i < JOINT_COUNT; i++)
|
||||||
{
|
{
|
||||||
btHingeConstraint* hingeC = static_cast<btHingeConstraint*>(getJoints()[i]);
|
btHingeConstraint* hingeC = static_cast<btHingeConstraint*>(getJoints()[i]);
|
||||||
hingeC->enableAngularMotor(false,0,0);
|
hingeC->enableMotor(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < BODYPART_COUNT; ++i)
|
for (int i = 0; i < BODYPART_COUNT; ++i)
|
||||||
@@ -657,7 +640,7 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_startPosition = getPosition();
|
m_startPosition = position; // the starting position of the walker
|
||||||
|
|
||||||
m_legUpdateAccumulator = 0;
|
m_legUpdateAccumulator = 0;
|
||||||
|
|
||||||
@@ -861,9 +844,7 @@ void NN3DWalkersExample::initPhysics()
|
|||||||
slider);
|
slider);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{// Setup a big ground box
|
||||||
// Setup a big ground box
|
|
||||||
{
|
|
||||||
btCollisionShape* groundShape = new btBoxShape(btVector3(btScalar(200.),btScalar(10.),btScalar(200.)));
|
btCollisionShape* groundShape = new btBoxShape(btVector3(btScalar(200.),btScalar(10.),btScalar(200.)));
|
||||||
m_collisionShapes.push_back(groundShape);
|
m_collisionShapes.push_back(groundShape);
|
||||||
btTransform groundTransform;
|
btTransform groundTransform;
|
||||||
@@ -874,41 +855,25 @@ void NN3DWalkersExample::initPhysics()
|
|||||||
ground->setUserPointer(GROUND_ID);
|
ground->setUserPointer(GROUND_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int i = 0; i < POPULATION_SIZE ; i++){
|
|
||||||
if(RANDOMIZE_WALKER_DIMENSIONS){
|
|
||||||
float maxDimension = 0.2f;
|
|
||||||
|
|
||||||
// randomize the dimensions
|
|
||||||
m_rootBodyRadius = ((double) rand() / (RAND_MAX)) * (maxDimension-0.01f) + 0.01f;
|
|
||||||
m_rootBodyHeight = ((double) rand() / (RAND_MAX)) * (maxDimension-0.01f) + 0.01f;
|
|
||||||
m_legRadius = ((double) rand() / (RAND_MAX)) * (maxDimension-0.01f) + 0.01f;
|
|
||||||
m_legLength = ((double) rand() / (RAND_MAX)) * (maxDimension-0.01f) + 0.01f;
|
|
||||||
m_foreLegLength = ((double) rand() / (RAND_MAX)) * (maxDimension-0.01f) + 0.01f;
|
|
||||||
m_foreLegRadius = ((double) rand() / (RAND_MAX)) * (maxDimension-0.01f) + 0.01f;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Spawn one walker
|
|
||||||
spawnWalker(i, m_resetPosition, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// add walker filter making the walkers never collide with each other
|
// add walker filter making the walkers never collide with each other
|
||||||
btOverlapFilterCallback * filterCallback = new WalkerFilterCallback();
|
btOverlapFilterCallback * filterCallback = new WalkerFilterCallback();
|
||||||
m_dynamicsWorld->getPairCache()->setOverlapFilterCallback(filterCallback);
|
m_dynamicsWorld->getPairCache()->setOverlapFilterCallback(filterCallback);
|
||||||
|
|
||||||
|
|
||||||
// setup data sources for walkers in time series canvas
|
// setup data sources for walkers in time series canvas
|
||||||
m_timeSeriesCanvas = new TimeSeriesCanvas(m_guiHelper->getAppInterface()->m_2dCanvasInterface,400,300, "Fitness Performance");
|
m_timeSeriesCanvas = new TimeSeriesCanvas(m_guiHelper->getAppInterface()->m_2dCanvasInterface,400,300, "Fitness Performance");
|
||||||
m_timeSeriesCanvas->setupTimeSeries(TIME_SERIES_MIN_Y, TIME_SERIES_MAX_Y, 10, 0);
|
m_timeSeriesCanvas->setupTimeSeries(TIME_SERIES_MIN_Y, TIME_SERIES_MAX_Y, 10, 0);
|
||||||
for(int i = 0; i < POPULATION_SIZE ; i++){
|
for(int i = 0; i < POPULATION_SIZE ; i++){
|
||||||
m_timeSeriesCanvas->addDataSource(" ", 100*i/POPULATION_SIZE,100*(POPULATION_SIZE-i)/POPULATION_SIZE,100*(i)/POPULATION_SIZE);
|
m_timeSeriesCanvas->addDataSource(" ", 100*i/POPULATION_SIZE,100*(POPULATION_SIZE-i)/POPULATION_SIZE,100*(i)/POPULATION_SIZE);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
m_walkersInPopulation.resize(POPULATION_SIZE, NULL);
|
||||||
|
|
||||||
|
for(int i = 0; i < POPULATION_SIZE ; i++){
|
||||||
|
|
||||||
|
// Spawn one walker
|
||||||
|
resetWalkerAt(i, m_resetPosition);
|
||||||
|
}
|
||||||
|
|
||||||
void NN3DWalkersExample::spawnWalker(int index, const btVector3& resetPosition, bool fixedBodyPosition)
|
|
||||||
{
|
|
||||||
NNWalker* walker = new NNWalker(index, m_dynamicsWorld, resetPosition, m_rootBodyRadius,m_rootBodyHeight,m_legRadius,m_legLength,m_foreLegRadius,m_foreLegLength, fixedBodyPosition);
|
|
||||||
m_walkersInPopulation.push_back(walker);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NN3DWalkersExample::detectCollisions()
|
bool NN3DWalkersExample::detectCollisions()
|
||||||
@@ -1167,17 +1132,11 @@ void NN3DWalkersExample::updateEvaluations(const btScalar timeSinceLastTick) {
|
|||||||
|
|
||||||
m_SimulationTime += delta;
|
m_SimulationTime += delta;
|
||||||
|
|
||||||
for(int i = 0; i < POPULATION_SIZE;i++) // evaluation time passes
|
for(int r = 0; r < POPULATION_SIZE;r++) // evaluation time passes
|
||||||
{
|
{
|
||||||
if(m_walkersInPopulation[i]->isInEvaluation()){
|
if(m_walkersInPopulation[r] != NULL && m_walkersInPopulation[r]->isInEvaluation()){
|
||||||
m_walkersInPopulation[i]->setEvaluationTime(m_walkersInPopulation[i]->getEvaluationTime()+delta); // increase evaluation time
|
m_walkersInPopulation[r]->setEvaluationTime(m_walkersInPopulation[r]->getEvaluationTime()+delta); // increase evaluation time
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int r = 0; r < POPULATION_SIZE; r++)
|
|
||||||
{
|
|
||||||
if(m_walkersInPopulation[r]->isInEvaluation())
|
|
||||||
{
|
|
||||||
m_walkersInPopulation[r]->setLegUpdateAccumulator(m_walkersInPopulation[r]->getLegUpdateAccumulator() + delta);
|
m_walkersInPopulation[r]->setLegUpdateAccumulator(m_walkersInPopulation[r]->getLegUpdateAccumulator() + delta);
|
||||||
|
|
||||||
if(m_walkersInPopulation[r]->getLegUpdateAccumulator() >= btScalar(1.0f) /m_walkerLegTargetFrequency)
|
if(m_walkersInPopulation[r]->getLegUpdateAccumulator() >= btScalar(1.0f) /m_walkerLegTargetFrequency)
|
||||||
@@ -1189,17 +1148,13 @@ void NN3DWalkersExample::updateEvaluations(const btScalar timeSinceLastTick) {
|
|||||||
btScalar targetAngle = 0; // angle in range [0,1]
|
btScalar targetAngle = 0; // angle in range [0,1]
|
||||||
btHingeConstraint* hingeC = static_cast<btHingeConstraint*>(m_walkersInPopulation[r]->getJoints()[i]);
|
btHingeConstraint* hingeC = static_cast<btHingeConstraint*>(m_walkersInPopulation[r]->getJoints()[i]);
|
||||||
|
|
||||||
if(RANDOM_WALKER_MOVEMENT){
|
|
||||||
targetAngle = ((double) rand() / (RAND_MAX));
|
|
||||||
}
|
|
||||||
else{ // neural network movement
|
|
||||||
|
|
||||||
for(int j = 0; j < JOINT_COUNT;j++){ // accumulate sensor inputs with weights (summate inputs)
|
for(int j = 0; j < JOINT_COUNT;j++){ // accumulate sensor inputs with weights (summate inputs)
|
||||||
targetAngle += m_walkersInPopulation[r]->getSensoryMotorWeights()[i+j*BODYPART_COUNT] * m_walkersInPopulation[r]->getTouchSensor(i);
|
targetAngle += m_walkersInPopulation[r]->getSensoryMotorWeights()[i+j*BODYPART_COUNT] * m_walkersInPopulation[r]->getTouchSensor(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
targetAngle = (tanh(targetAngle)+1.0f)*0.5f; // apply the activation function (threshold) [0;1]
|
targetAngle = (tanh(targetAngle)+1.0f)*0.5f; // apply the activation function (threshold) [0;1]
|
||||||
}
|
|
||||||
btScalar targetLimitAngle = hingeC->getLowerLimit() + targetAngle * (hingeC->getUpperLimit() - hingeC->getLowerLimit()); // [lowerLimit;upperLimit]
|
btScalar targetLimitAngle = hingeC->getLowerLimit() + targetAngle * (hingeC->getUpperLimit() - hingeC->getLowerLimit()); // [lowerLimit;upperLimit]
|
||||||
btScalar currentAngle = hingeC->getHingeAngle();
|
btScalar currentAngle = hingeC->getHingeAngle();
|
||||||
btScalar angleError = targetLimitAngle - currentAngle; // target current delta
|
btScalar angleError = targetLimitAngle - currentAngle; // target current delta
|
||||||
@@ -1257,9 +1212,20 @@ void NN3DWalkersExample::scheduleEvaluations() {
|
|||||||
|
|
||||||
void NN3DWalkersExample::resetWalkerAt(int i, const btVector3& resetPosition){
|
void NN3DWalkersExample::resetWalkerAt(int i, const btVector3& resetPosition){
|
||||||
|
|
||||||
NNWalker* newWalker = new NNWalker(i, m_dynamicsWorld, resetPosition, m_rootBodyRadius,m_rootBodyHeight,m_legRadius,m_legLength,m_foreLegRadius,m_foreLegLength, false);
|
NNWalker* newWalker = new NNWalker(i, m_dynamicsWorld, resetPosition,
|
||||||
|
m_rootBodyRadius,
|
||||||
|
m_rootBodyHeight,
|
||||||
|
m_legRadius,
|
||||||
|
m_legLength,
|
||||||
|
m_foreLegRadius,
|
||||||
|
m_foreLegLength,
|
||||||
|
false);
|
||||||
|
|
||||||
|
if(m_walkersInPopulation[i] != NULL){
|
||||||
newWalker->copySensoryMotorWeights(m_walkersInPopulation[i]->getSensoryMotorWeights());
|
newWalker->copySensoryMotorWeights(m_walkersInPopulation[i]->getSensoryMotorWeights());
|
||||||
delete m_walkersInPopulation[i];
|
delete m_walkersInPopulation[i];
|
||||||
|
}
|
||||||
|
|
||||||
m_walkersInPopulation[i] = newWalker;
|
m_walkersInPopulation[i] = newWalker;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user