2016-07-01 17:35:27 +00:00
/*
2016-09-11 20:25:22 +00:00
Bullet Continuous Collision Detection and Physics Library
Copyright ( c ) 2015 Google Inc . http : //bulletphysics.org
2016-07-01 17:35:27 +00:00
This software is provided ' as - is ' , without any express or implied warranty .
In no event will the authors be held liable for any damages arising from the use of this software .
Permission is granted to anyone to use this software for any purpose ,
including commercial applications , and to alter it and redistribute it freely ,
subject to the following restrictions :
1. The origin of this software must not be misrepresented ; you must not claim that you wrote the original software . If you use this software in a product , an acknowledgment in the product documentation would be appreciated but is not required .
2. Altered source versions must be plainly marked as such , and must not be misrepresented as being the original software .
3. This notice may not be removed or altered from any source distribution .
*/
# include "NN3DWalkers.h"
2016-07-04 17:17:10 +00:00
2016-07-01 17:35:27 +00:00
# include "btBulletDynamicsCommon.h"
# include "LinearMath/btIDebugDraw.h"
# include "LinearMath/btAlignedObjectArray.h"
2016-10-19 19:56:09 +00:00
# include "LinearMath/btHashMap.h"
2017-05-28 13:10:45 +00:00
2016-07-01 17:35:27 +00:00
class btBroadphaseInterface ;
class btCollisionShape ;
class btOverlappingPairCache ;
class btCollisionDispatcher ;
class btConstraintSolver ;
struct btCollisionAlgorithmCreateFunc ;
class btDefaultCollisionConfiguration ;
2016-09-11 20:25:22 +00:00
class NNWalker ;
2016-07-01 17:35:27 +00:00
2016-10-22 20:50:08 +00:00
# include "NN3DWalkersTimeWarpBase.h"
2016-07-04 17:17:10 +00:00
# include "../CommonInterfaces/CommonParameterInterface.h"
2016-07-01 17:35:27 +00:00
2016-09-11 20:25:22 +00:00
# include "../Utils/b3ReferenceFrameHelper.hpp"
2016-11-08 21:16:08 +00:00
# include "../Utils/b3Clock.h"
2016-09-12 14:36:37 +00:00
# include "../RenderingExamples/TimeSeriesCanvas.h"
2016-07-03 17:54:47 +00:00
2016-11-01 14:34:22 +00:00
// #### configurable parameters ####
# ifndef NUM_WALKER_LEGS
# define NUM_WALKER_LEGS 6 // the number of walker legs
2016-09-11 20:25:22 +00:00
# endif
2016-11-01 14:34:22 +00:00
# ifndef POPULATION_SIZE
2016-12-30 00:46:36 +00:00
# define POPULATION_SIZE 10 // number of walkers in the population
2016-09-11 20:25:22 +00:00
# endif
2016-11-01 14:34:22 +00:00
# ifndef EVALUATION_DURATION
# define EVALUATION_DURATION 10 // s (duration of one single evaluation)
2016-09-11 20:25:22 +00:00
# endif
2016-11-01 18:48:39 +00:00
# ifndef TIME_SERIES_MAX_Y
2016-12-30 00:46:36 +00:00
# define TIME_SERIES_MAX_Y 20.0f // chart maximum y
2016-11-01 18:48:39 +00:00
# endif
# ifndef TIME_SERIES_MIN_Y
2016-12-30 00:46:36 +00:00
# define TIME_SERIES_MIN_Y 0.0f // chart minimum y
2016-11-01 18:48:39 +00:00
# endif
2016-12-30 00:46:36 +00:00
// walker dimensions and properties
2016-11-01 21:11:12 +00:00
static btScalar gWalkerMotorStrength = 0.5f ;
2016-12-27 20:00:22 +00:00
static btScalar gWalkerLegTargetFrequency = 3 ;
2016-11-01 21:11:12 +00:00
static btScalar gRootBodyRadius = 0.25f ;
static btScalar gRootBodyHeight = 0.1f ;
static btScalar gLegRadius = 0.1f ;
static btScalar gLegLength = 0.45f ;
static btScalar gForeLegLength = 0.75f ;
static btScalar gForeLegRadius = 0.08f ;
static btScalar gParallelEvaluations = 10.0f ;
2016-11-01 14:34:22 +00:00
// Evaluation configurable parameters
2016-09-11 20:25:22 +00:00
# ifndef REAP_QTY
# define REAP_QTY 0.3f // number of walkers reaped based on their bad performance
# endif
# ifndef SOW_CROSSOVER_QTY
2016-11-01 14:34:22 +00:00
# define SOW_CROSSOVER_QTY 0.2f // number of walkers recreated via crossover
2016-09-11 20:25:22 +00:00
# endif
2016-11-01 14:34:22 +00:00
// this means the rest of them is randomly created: REAP_QTY-SOW_CROSSOVER_QTY = NEW_RANDOM_BREED_QTY
2016-09-11 20:25:22 +00:00
# ifndef SOW_ELITE_QTY
2016-11-01 14:34:22 +00:00
# define SOW_ELITE_QTY 0.2f // number of walkers kept using an elitist strategy (the best performing creatures are NOT mutated at all)
2016-09-11 20:25:22 +00:00
# endif
# ifndef SOW_MUTATION_QTY
# define SOW_MUTATION_QTY 0.5f // SOW_ELITE_QTY + SOW_MUTATION_QTY + REAP_QTY = 1
# endif
# ifndef MUTATION_RATE
# define MUTATION_RATE 0.5f // the mutation rate of for the walker with the worst performance
# endif
# ifndef SOW_ELITE_PARTNER
2016-11-01 14:34:22 +00:00
# define SOW_ELITE_PARTNER 0.8f // the chance an elite partner is chosen for breeding
# endif
// #### debugging ####
# ifndef DRAW_INTERPENETRATIONS
# define DRAW_INTERPENETRATIONS false // DEBUG toggle: draw interpenetrations of a walker body
# endif
# ifndef REBUILD_WALKER
2016-12-30 00:46:36 +00:00
# define REBUILD_WALKER false // if the walker should be rebuilt on mutation
2016-11-01 14:34:22 +00:00
# endif
# ifndef TIMESTAMP_TIME
# define TIMESTAMP_TIME 2000.0f // delay between speed up timestamps
# endif
// #### not to be reconfigured ####
# define BODYPART_COUNT (2 * NUM_WALKER_LEGS + 1)
2016-09-11 20:25:22 +00:00
# define JOINT_COUNT (BODYPART_COUNT - 1)
2016-09-06 20:30:46 +00:00
void * GROUND_ID = ( void * ) 1 ;
2016-11-01 14:34:22 +00:00
# ifndef SIMD_PI_4
# define SIMD_PI_4 0.5 * SIMD_HALF_PI
# endif
# ifndef SIMD_PI_8
# define SIMD_PI_8 0.25 * SIMD_HALF_PI
# endif
2016-10-22 20:50:08 +00:00
class NN3DWalkersExample : public NN3DWalkersTimeWarpBase
2016-07-01 17:35:27 +00:00
{
2016-11-01 14:34:22 +00:00
btScalar m_SimulationTime ; // the current simulation time
btScalar m_LastSpeedupPrintTimestamp ;
btScalar m_bestWalkerFitness ; // to keep track of the best fitness
btVector3 m_resetPosition ; // initial position of an evaluation
int m_walkersInEvaluation ; // number of walkers in evaluation
int m_nextReapedIndex ; // index of the next reaped walker
2016-07-01 17:35:27 +00:00
2016-09-11 20:25:22 +00:00
btAlignedObjectArray < class NNWalker * > m_walkersInPopulation ;
2016-07-01 17:35:27 +00:00
2016-12-30 00:46:36 +00:00
bool m_rebuildWorldNeeded ; // if the world should be rebuilt (for determinism)
2016-12-27 20:00:22 +00:00
btRigidBody * m_ground ; // reference to ground to readd if world is rebuilt
btOverlapFilterCallback * m_filterCallback ; // the collision filter callback
2016-11-01 14:34:22 +00:00
TimeSeriesCanvas * m_timeSeriesCanvas ; // A plotting canvas for the walker fitnesses
2016-07-01 17:35:27 +00:00
public :
2016-09-06 20:30:46 +00:00
NN3DWalkersExample ( struct GUIHelperInterface * helper )
2016-10-22 20:50:08 +00:00
: NN3DWalkersTimeWarpBase ( helper ) ,
2016-11-01 14:34:22 +00:00
// others
m_resetPosition ( 0 , 0 , 0 ) ,
m_SimulationTime ( 0 ) ,
m_bestWalkerFitness ( 0 ) ,
m_LastSpeedupPrintTimestamp ( 0 ) ,
m_walkersInEvaluation ( 0 ) ,
m_nextReapedIndex ( 0 ) ,
2016-12-27 20:00:22 +00:00
m_timeSeriesCanvas ( NULL ) ,
m_ground ( NULL ) ,
2016-12-30 00:46:36 +00:00
m_rebuildWorldNeeded ( false ) ,
2016-12-27 20:00:22 +00:00
m_filterCallback ( NULL )
2016-07-01 17:35:27 +00:00
{
2016-11-08 21:16:08 +00:00
b3Clock clock ;
srand ( clock . getSystemTimeMilliseconds ( ) ) ;
2016-07-03 17:54:47 +00:00
}
2016-07-01 17:35:27 +00:00
2016-09-06 20:30:46 +00:00
virtual ~ NN3DWalkersExample ( )
2016-07-01 17:35:27 +00:00
{
2016-11-01 14:34:22 +00:00
//m_walkersInPopulation deallocates itself
2016-10-21 15:52:11 +00:00
delete m_timeSeriesCanvas ;
2016-07-01 17:35:27 +00:00
}
2016-09-11 20:25:22 +00:00
2016-11-01 14:34:22 +00:00
/**
* Setup physics scene .
*/
2016-09-11 20:25:22 +00:00
void initPhysics ( ) ;
2016-12-27 20:00:22 +00:00
/**
* Recreate the world if necessary .
* @ param deltaTime
*/
virtual void performModelUpdate ( float deltaTime ) ;
/**
* Delete the world and recreate it anew .
*/
void recreateWorld ( ) ;
2016-11-01 14:34:22 +00:00
/**
* Shutdown physics scene .
*/
2016-09-11 20:25:22 +00:00
virtual void exitPhysics ( ) ;
2016-07-01 17:35:27 +00:00
2016-12-27 20:00:22 +00:00
/**
* Handle keyboard inputs .
* @ param key
* @ param state
* @ return
*/
2016-11-01 14:34:22 +00:00
virtual bool keyboardCallback ( int key , int state ) ;
2016-10-19 19:20:57 +00:00
2016-11-01 14:34:22 +00:00
/**
* Detect collisions within simulation . Used to avoid collisions happening at startup .
* @ return
*/
2016-09-11 20:25:22 +00:00
bool detectCollisions ( ) ;
2016-09-06 20:30:46 +00:00
2016-11-01 14:34:22 +00:00
/**
* Reset the camera to a certain position and orientation .
*/
2016-07-01 17:35:27 +00:00
void resetCamera ( )
{
float dist = 11 ;
float pitch = 52 ;
float yaw = 35 ;
float targetPos [ 3 ] = { 0 , 0.46 , 0 } ;
m_guiHelper - > resetCamera ( dist , pitch , yaw , targetPos [ 0 ] , targetPos [ 1 ] , targetPos [ 2 ] ) ;
}
2016-09-11 20:25:22 +00:00
// Evaluation
2016-07-01 17:35:27 +00:00
2016-11-01 14:34:22 +00:00
/**
* Update the simulation .
* @ param timeSinceLastTick
*/
2016-09-12 21:59:42 +00:00
void update ( const btScalar timeSinceLastTick ) ;
2016-07-01 17:35:27 +00:00
2016-11-01 14:34:22 +00:00
/**
* Update all evaluations .
* @ param timeSinceLastTick
*/
2016-09-12 21:59:42 +00:00
void updateEvaluations ( const btScalar timeSinceLastTick ) ;
2016-07-01 17:35:27 +00:00
2016-11-01 14:34:22 +00:00
/**
* Schedule new evaluations and tear down old ones .
*/
2016-09-11 20:25:22 +00:00
void scheduleEvaluations ( ) ;
2016-07-01 17:35:27 +00:00
2016-11-01 14:34:22 +00:00
/**
* Draw distance markings on ground .
*/
2016-09-12 14:36:37 +00:00
void drawMarkings ( ) ;
2016-11-01 14:34:22 +00:00
/**
* Reset a walker by deleting and rebuilding it .
* @ param i
* @ param resetPosition
*/
void resetWalkerAt ( int i , const btVector3 & resetPosition ) ;
2016-09-11 20:25:22 +00:00
// Reaper
2016-07-05 16:57:51 +00:00
2016-11-01 14:34:22 +00:00
/**
* Rate all evaluations via fitness function .
*/
2016-09-11 20:25:22 +00:00
void rateEvaluations ( ) ;
2016-11-01 14:34:22 +00:00
/**
* Reap the worst performing walkers .
*/
2016-09-11 20:25:22 +00:00
void reap ( ) ;
2016-11-01 14:34:22 +00:00
/**
* Sow new walkers .
*/
2016-09-11 20:25:22 +00:00
void sow ( ) ;
2016-11-01 14:34:22 +00:00
/**
* Crossover two walkers to create an offspring .
* @ param mother
* @ param father
* @ param offspring
*/
2016-09-11 20:25:22 +00:00
void crossover ( NNWalker * mother , NNWalker * father , NNWalker * offspring ) ;
2016-11-01 14:34:22 +00:00
/**
* Mutate a walker .
* @ param mutant
* @ param mutationRate
*/
2016-09-12 21:59:42 +00:00
void mutate ( NNWalker * mutant , btScalar mutationRate ) ;
2016-09-11 20:25:22 +00:00
2016-11-01 14:34:22 +00:00
/**
* Get a random elite walker .
* @ return
*/
2016-09-11 20:25:22 +00:00
NNWalker * getRandomElite ( ) ;
2016-11-01 14:34:22 +00:00
/**
* Get a random non elite walker .
* @ return
*/
2016-09-11 20:25:22 +00:00
NNWalker * getRandomNonElite ( ) ;
2016-11-01 14:34:22 +00:00
/**
* Get the next walker to be reaped .
* @ return
*/
2016-09-11 20:25:22 +00:00
NNWalker * getNextReaped ( ) ;
2016-11-01 14:34:22 +00:00
/**
* Print walker configurations to console .
*/
2016-09-12 14:36:37 +00:00
void printWalkerConfigs ( ) ;
2016-09-11 20:25:22 +00:00
} ;
static NN3DWalkersExample * nn3DWalkers = NULL ;
2016-07-01 17:35:27 +00:00
class NNWalker
{
2016-11-01 14:34:22 +00:00
btDynamicsWorld * m_ownerWorld ;
btCollisionShape * m_shapes [ BODYPART_COUNT ] ;
btRigidBody * m_bodies [ BODYPART_COUNT ] ;
btTransform m_bodyRelativeTransforms [ BODYPART_COUNT ] ;
btTypedConstraint * m_joints [ JOINT_COUNT ] ;
2016-10-19 19:56:09 +00:00
btHashMap < btHashPtr , int > m_bodyTouchSensorIndexMap ;
2016-11-01 14:34:22 +00:00
bool m_touchSensors [ BODYPART_COUNT ] ;
btScalar m_sensoryMotorWeights [ BODYPART_COUNT * JOINT_COUNT ] ;
2016-09-11 20:25:22 +00:00
2016-11-01 14:34:22 +00:00
bool m_inEvaluation ;
btScalar m_evaluationTime ;
bool m_reaped ;
btVector3 m_startPosition ;
int m_index ;
btScalar m_legUpdateAccumulator ;
2016-07-01 17:35:27 +00:00
btRigidBody * localCreateRigidBody ( btScalar mass , const btTransform & startTransform , btCollisionShape * shape )
{
bool isDynamic = ( mass ! = 0.f ) ;
btVector3 localInertia ( 0 , 0 , 0 ) ;
if ( isDynamic )
shape - > calculateLocalInertia ( mass , localInertia ) ;
2016-07-03 17:54:47 +00:00
btDefaultMotionState * motionState = new btDefaultMotionState ( startTransform ) ;
btRigidBody : : btRigidBodyConstructionInfo rbInfo ( mass , motionState , shape , localInertia ) ;
2016-07-01 17:35:27 +00:00
btRigidBody * body = new btRigidBody ( rbInfo ) ;
return body ;
}
public :
2016-09-11 20:25:22 +00:00
void randomizeSensoryMotorWeights ( ) {
2016-07-04 17:17:10 +00:00
//initialize random weights
for ( int i = 0 ; i < BODYPART_COUNT ; i + + ) {
for ( int j = 0 ; j < JOINT_COUNT ; j + + ) {
2016-07-04 17:43:26 +00:00
m_sensoryMotorWeights [ i + j * BODYPART_COUNT ] = ( ( double ) rand ( ) / ( RAND_MAX ) ) * 2.0f - 1.0f ;
2016-07-04 17:17:10 +00:00
}
}
2016-09-11 20:25:22 +00:00
}
2016-12-30 00:46:36 +00:00
NNWalker ( int index , btDynamicsWorld * ownerWorld ,
const btVector3 & startingPosition ,
2016-11-01 14:34:22 +00:00
const btScalar & rootBodyRadius ,
const btScalar & rootBodyHeight ,
const btScalar & legRadius ,
const btScalar & legLength ,
const btScalar & foreLegRadius ,
const btScalar & foreLegLength ,
bool fixedBodyPosition )
: m_ownerWorld ( ownerWorld ) , // the world the walker walks in
m_inEvaluation ( false ) , // the walker is not in evaluation
m_evaluationTime ( 0 ) , // reset evaluation time
m_reaped ( false ) , // the walker is not reaped
m_startPosition ( startingPosition ) , // the starting position of the walker
2016-12-30 00:46:36 +00:00
m_legUpdateAccumulator ( 0 ) ,
m_index ( index )
2016-09-11 20:25:22 +00:00
{
btVector3 vUp ( 0 , 1 , 0 ) ; // up in local reference frame
NN3DWalkersExample * nnWalkersDemo = ( NN3DWalkersExample * ) m_ownerWorld - > getWorldUserInfo ( ) ;
2016-07-01 17:35:27 +00:00
// Setup geometry
2016-11-01 14:34:22 +00:00
m_shapes [ 0 ] = new btCapsuleShape ( rootBodyRadius , rootBodyHeight ) ; // root body capsule
2016-07-01 17:35:27 +00:00
int i ;
2016-11-01 14:34:22 +00:00
for ( i = 0 ; i < NUM_WALKER_LEGS ; i + + )
2016-07-01 17:35:27 +00:00
{
2016-11-01 14:34:22 +00:00
m_shapes [ 1 + 2 * i ] = new btCapsuleShape ( legRadius , legLength ) ; // leg capsule
m_shapes [ 2 + 2 * i ] = new btCapsuleShape ( foreLegRadius , foreLegLength ) ; // fore leg capsule
2016-07-01 17:35:27 +00:00
}
// Setup rigid bodies
2016-11-01 14:34:22 +00:00
btScalar rootAboveGroundHeight = foreLegLength ;
2016-07-01 17:35:27 +00:00
btTransform bodyOffset ; bodyOffset . setIdentity ( ) ;
2016-11-01 14:34:22 +00:00
bodyOffset . setOrigin ( startingPosition ) ;
2016-07-01 17:35:27 +00:00
// root body
2016-09-11 20:25:22 +00:00
btVector3 localRootBodyPosition = btVector3 ( btScalar ( 0. ) , rootAboveGroundHeight , btScalar ( 0. ) ) ; // root body position in local reference frame
2016-07-01 17:35:27 +00:00
btTransform transform ;
transform . setIdentity ( ) ;
transform . setOrigin ( localRootBodyPosition ) ;
2016-09-06 20:30:46 +00:00
2016-09-11 20:25:22 +00:00
btTransform originTransform = transform ;
2016-11-01 14:34:22 +00:00
m_bodies [ 0 ] = localCreateRigidBody ( btScalar ( fixedBodyPosition ? 0. : 1. ) , bodyOffset * transform , m_shapes [ 0 ] ) ;
2016-09-06 20:30:46 +00:00
m_ownerWorld - > addRigidBody ( m_bodies [ 0 ] ) ;
2016-10-19 19:20:57 +00:00
m_bodyRelativeTransforms [ 0 ] = btTransform : : getIdentity ( ) ;
2016-09-06 20:30:46 +00:00
m_bodies [ 0 ] - > setUserPointer ( this ) ;
2016-10-19 19:56:09 +00:00
m_bodyTouchSensorIndexMap . insert ( btHashPtr ( m_bodies [ 0 ] ) , 0 ) ;
2016-07-01 17:35:27 +00:00
btHingeConstraint * hingeC ;
btTransform localA , localB , localC ;
// legs
2016-11-01 14:34:22 +00:00
for ( i = 0 ; i < NUM_WALKER_LEGS ; i + + )
2016-07-01 17:35:27 +00:00
{
2016-11-01 14:34:22 +00:00
float footAngle = 2 * SIMD_PI * i / NUM_WALKER_LEGS ; // legs are uniformly distributed around the root body
2016-07-01 17:35:27 +00:00
float footYUnitPosition = sin ( footAngle ) ; // y position of the leg on the unit circle
float footXUnitPosition = cos ( footAngle ) ; // x position of the leg on the unit circle
transform . setIdentity ( ) ;
2016-11-01 14:34:22 +00:00
btVector3 legCOM = btVector3 ( btScalar ( footXUnitPosition * ( rootBodyRadius + 0.5 * legLength ) ) , btScalar ( rootAboveGroundHeight ) , btScalar ( footYUnitPosition * ( rootBodyRadius + 0.5 * legLength ) ) ) ;
2016-07-01 17:35:27 +00:00
transform . setOrigin ( legCOM ) ;
// thigh
btVector3 legDirection = ( legCOM - localRootBodyPosition ) . normalize ( ) ;
btVector3 kneeAxis = legDirection . cross ( vUp ) ;
2016-07-03 17:54:47 +00:00
transform . setRotation ( btQuaternion ( kneeAxis , SIMD_HALF_PI ) ) ;
2016-07-01 17:35:27 +00:00
m_bodies [ 1 + 2 * i ] = localCreateRigidBody ( btScalar ( 1. ) , bodyOffset * transform , m_shapes [ 1 + 2 * i ] ) ;
2016-09-11 20:25:22 +00:00
m_bodyRelativeTransforms [ 1 + 2 * i ] = transform ;
2016-09-06 20:30:46 +00:00
m_bodies [ 1 + 2 * i ] - > setUserPointer ( this ) ;
2016-10-19 19:56:09 +00:00
m_bodyTouchSensorIndexMap . insert ( btHashPtr ( m_bodies [ 1 + 2 * i ] ) , 1 + 2 * i ) ;
2016-07-01 17:35:27 +00:00
// shin
transform . setIdentity ( ) ;
2016-11-01 14:34:22 +00:00
transform . setOrigin ( btVector3 ( btScalar ( footXUnitPosition * ( rootBodyRadius + legLength ) ) , btScalar ( rootAboveGroundHeight - 0.5 * foreLegLength ) , btScalar ( footYUnitPosition * ( rootBodyRadius + legLength ) ) ) ) ;
2016-07-01 17:35:27 +00:00
m_bodies [ 2 + 2 * i ] = localCreateRigidBody ( btScalar ( 1. ) , bodyOffset * transform , m_shapes [ 2 + 2 * i ] ) ;
2016-09-11 20:25:22 +00:00
m_bodyRelativeTransforms [ 2 + 2 * i ] = transform ;
2016-09-06 20:30:46 +00:00
m_bodies [ 2 + 2 * i ] - > setUserPointer ( this ) ;
2016-10-19 19:56:09 +00:00
m_bodyTouchSensorIndexMap . insert ( btHashPtr ( m_bodies [ 2 + 2 * i ] ) , 2 + 2 * i ) ;
2016-07-01 17:35:27 +00:00
// hip joints
localA . setIdentity ( ) ; localB . setIdentity ( ) ;
2016-11-01 14:34:22 +00:00
localA . getBasis ( ) . setEulerZYX ( 0 , - footAngle , 0 ) ; localA . setOrigin ( btVector3 ( btScalar ( footXUnitPosition * rootBodyRadius ) , btScalar ( 0. ) , btScalar ( footYUnitPosition * rootBodyRadius ) ) ) ;
2016-09-11 20:25:22 +00:00
localB = b3ReferenceFrameHelper : : getTransformWorldToLocal ( m_bodies [ 1 + 2 * i ] - > getWorldTransform ( ) , b3ReferenceFrameHelper : : getTransformLocalToWorld ( m_bodies [ 0 ] - > getWorldTransform ( ) , localA ) ) ;
2016-07-01 17:35:27 +00:00
hingeC = new btHingeConstraint ( * m_bodies [ 0 ] , * m_bodies [ 1 + 2 * i ] , localA , localB ) ;
2016-07-03 17:54:47 +00:00
hingeC - > setLimit ( btScalar ( - 0.75 * SIMD_PI_4 ) , btScalar ( SIMD_PI_8 ) ) ;
2016-07-01 17:35:27 +00:00
//hingeC->setLimit(btScalar(-0.1), btScalar(0.1));
m_joints [ 2 * i ] = hingeC ;
// knee joints
localA . setIdentity ( ) ; localB . setIdentity ( ) ; localC . setIdentity ( ) ;
2016-11-01 14:34:22 +00:00
localA . getBasis ( ) . setEulerZYX ( 0 , - footAngle , 0 ) ; localA . setOrigin ( btVector3 ( btScalar ( footXUnitPosition * ( rootBodyRadius + legLength ) ) , btScalar ( 0. ) , btScalar ( footYUnitPosition * ( rootBodyRadius + legLength ) ) ) ) ;
2016-09-11 20:25:22 +00:00
localB = b3ReferenceFrameHelper : : getTransformWorldToLocal ( m_bodies [ 1 + 2 * i ] - > getWorldTransform ( ) , b3ReferenceFrameHelper : : getTransformLocalToWorld ( m_bodies [ 0 ] - > getWorldTransform ( ) , localA ) ) ;
localC = b3ReferenceFrameHelper : : getTransformWorldToLocal ( m_bodies [ 2 + 2 * i ] - > getWorldTransform ( ) , b3ReferenceFrameHelper : : getTransformLocalToWorld ( m_bodies [ 0 ] - > getWorldTransform ( ) , localA ) ) ;
2016-07-01 17:35:27 +00:00
hingeC = new btHingeConstraint ( * m_bodies [ 1 + 2 * i ] , * m_bodies [ 2 + 2 * i ] , localB , localC ) ;
//hingeC->setLimit(btScalar(-0.01), btScalar(0.01));
2016-07-03 17:54:47 +00:00
hingeC - > setLimit ( btScalar ( - SIMD_PI_8 ) , btScalar ( 0.2 ) ) ;
2016-07-01 17:35:27 +00:00
m_joints [ 1 + 2 * i ] = hingeC ;
2016-09-06 20:30:46 +00:00
2016-11-01 20:03:46 +00:00
//test if we cause a collision with priorly inserted bodies. This prevents the walkers from having to resolve collisions on startup
2016-09-06 20:30:46 +00:00
2016-11-01 14:34:22 +00:00
m_ownerWorld - > addRigidBody ( m_bodies [ 1 + 2 * i ] ) ; // add thigh bone
2016-09-06 20:30:46 +00:00
m_ownerWorld - > addConstraint ( m_joints [ 2 * i ] , true ) ; // connect thigh bone with root
2016-09-11 20:25:22 +00:00
if ( nnWalkersDemo - > detectCollisions ( ) ) { // if thigh bone causes collision, remove it again
2016-09-06 20:30:46 +00:00
m_ownerWorld - > removeConstraint ( m_joints [ 2 * i ] ) ; // disconnect thigh bone from root
2016-12-30 00:46:36 +00:00
delete m_joints [ 2 * i ] ;
m_joints [ 2 * i ] = NULL ;
2016-11-01 14:34:22 +00:00
m_ownerWorld - > removeRigidBody ( m_bodies [ 1 + 2 * i ] ) ;
2016-12-30 00:46:36 +00:00
delete m_bodies [ 1 + 2 * i ] ;
m_bodies [ 1 + 2 * i ] = NULL ;
delete m_joints [ 1 + 2 * i ] ;
m_joints [ 1 + 2 * i ] = NULL ;
delete m_bodies [ 2 + 2 * i ] ;
m_bodies [ 2 + 2 * i ] = NULL ;
2016-09-06 20:30:46 +00:00
}
else {
m_ownerWorld - > addRigidBody ( m_bodies [ 2 + 2 * i ] ) ; // add shin bone
2016-09-11 20:25:22 +00:00
m_ownerWorld - > addConstraint ( m_joints [ 1 + 2 * i ] , true ) ; // connect shin bone with thigh
2016-09-06 20:30:46 +00:00
2016-09-11 20:25:22 +00:00
if ( nnWalkersDemo - > detectCollisions ( ) ) { // if shin bone causes collision, remove it again
2016-09-06 20:30:46 +00:00
m_ownerWorld - > removeConstraint ( m_joints [ 1 + 2 * i ] ) ; // disconnect shin bone from thigh
2016-12-30 00:46:36 +00:00
delete m_joints [ 1 + 2 * i ] ;
m_joints [ 1 + 2 * i ] = NULL ;
2016-11-01 14:34:22 +00:00
m_ownerWorld - > removeRigidBody ( m_bodies [ 2 + 2 * i ] ) ;
2016-12-30 00:46:36 +00:00
delete m_bodies [ 2 + 2 * i ] ;
m_bodies [ 2 + 2 * i ] = NULL ;
2016-09-06 20:30:46 +00:00
}
}
2016-07-01 17:35:27 +00:00
}
// Setup some damping on the m_bodies
for ( i = 0 ; i < BODYPART_COUNT ; + + i )
{
2016-12-30 00:46:36 +00:00
if ( m_bodies [ i ] ! = NULL ) {
m_bodies [ i ] - > setDamping ( 0.05 , 0.85 ) ;
m_bodies [ i ] - > setDeactivationTime ( 0.8 ) ;
m_bodies [ i ] - > setSleepingThresholds ( 0.5f , 0.5f ) ;
m_bodies [ i ] - > setActivationState ( DISABLE_DEACTIVATION ) ;
}
2016-07-01 17:35:27 +00:00
}
2016-09-11 20:25:22 +00:00
2016-12-30 00:46:36 +00:00
// Properly remove rigidbodies and joints
removeJoints ( ) ;
removeRigidbodies ( ) ;
2016-11-01 20:03:46 +00:00
clearTouchSensors ( ) ; // set touch sensors to zero
randomizeSensoryMotorWeights ( ) ; // set random sensory motor weights for neural network layer
2016-07-01 17:35:27 +00:00
}
virtual ~ NNWalker ( )
{
int i ;
2016-12-30 00:46:36 +00:00
removeFromWorld ( ) ;
2016-07-01 17:35:27 +00:00
// Remove all constraints
for ( i = 0 ; i < JOINT_COUNT ; + + i )
{
2016-12-30 00:46:36 +00:00
if ( m_joints [ i ] ! = NULL ) {
delete m_joints [ i ] ; m_joints [ i ] = 0 ;
}
2016-07-01 17:35:27 +00:00
}
// Remove all bodies and shapes
for ( i = 0 ; i < BODYPART_COUNT ; + + i )
{
2016-12-30 00:46:36 +00:00
if ( m_bodies [ i ] ! = NULL ) {
delete m_bodies [ i ] - > getMotionState ( ) ;
2016-07-01 17:35:27 +00:00
2016-12-30 00:46:36 +00:00
delete m_bodies [ i ] ; m_bodies [ i ] = 0 ;
delete m_shapes [ i ] ; m_shapes [ i ] = 0 ;
}
2016-07-01 17:35:27 +00:00
}
2016-12-30 00:46:36 +00:00
m_ownerWorld = NULL ;
2016-07-01 17:35:27 +00:00
}
2016-09-11 20:25:22 +00:00
btTypedConstraint * * getJoints ( ) {
return & m_joints [ 0 ] ;
}
2016-07-04 17:17:10 +00:00
void setTouchSensor ( void * bodyPointer ) {
2016-10-19 19:56:09 +00:00
m_touchSensors [ * m_bodyTouchSensorIndexMap . find ( btHashPtr ( bodyPointer ) ) ] = true ;
2016-07-04 17:17:10 +00:00
}
void clearTouchSensors ( ) {
for ( int i = 0 ; i < BODYPART_COUNT ; i + + ) {
2016-07-04 17:43:26 +00:00
m_touchSensors [ i ] = false ;
2016-07-04 17:17:10 +00:00
}
}
2016-09-11 20:25:22 +00:00
bool getTouchSensor ( int i ) {
return m_touchSensors [ i ] ;
}
2016-07-01 17:35:27 +00:00
2016-09-11 20:25:22 +00:00
btScalar * getSensoryMotorWeights ( ) {
2016-07-04 17:43:26 +00:00
return m_sensoryMotorWeights ;
2016-07-04 17:17:10 +00:00
}
2016-07-01 17:35:27 +00:00
2016-11-01 14:34:22 +00:00
void copySensoryMotorWeights ( btScalar * sensoryMotorWeights ) {
for ( int i = 0 ; i < BODYPART_COUNT ; i + + ) {
for ( int j = 0 ; j < JOINT_COUNT ; j + + ) {
m_sensoryMotorWeights [ i + j * BODYPART_COUNT ] = sensoryMotorWeights [ i + j * BODYPART_COUNT ] ;
}
}
}
2016-09-11 20:25:22 +00:00
void addToWorld ( ) {
2016-12-30 00:46:36 +00:00
if ( ! isInEvaluation ( ) ) {
2016-07-01 17:35:27 +00:00
2016-12-30 00:46:36 +00:00
addRigidbodies ( ) ;
addJoints ( ) ;
setInEvaluation ( true ) ;
2016-09-11 20:25:22 +00:00
}
}
2016-07-01 17:35:27 +00:00
2016-12-27 20:00:22 +00:00
void removeFromWorld ( ) {
2016-12-30 00:46:36 +00:00
if ( isInEvaluation ( ) ) {
2016-07-01 17:35:27 +00:00
2016-12-30 00:46:36 +00:00
removeJoints ( ) ;
removeRigidbodies ( ) ;
2016-09-11 20:25:22 +00:00
2016-12-30 00:46:36 +00:00
setInEvaluation ( false ) ;
2016-09-11 20:25:22 +00:00
}
}
btVector3 getPosition ( ) const {
btVector3 finalPosition ( 0 , 0 , 0 ) ;
2016-12-30 00:46:36 +00:00
int j = 0 ;
2016-09-11 20:25:22 +00:00
for ( int i = 0 ; i < BODYPART_COUNT ; i + + )
{
2016-12-30 00:46:36 +00:00
if ( m_bodies [ i ] ! = NULL ) {
finalPosition + = m_bodies [ i ] - > getCenterOfMassPosition ( ) ;
j + + ;
}
2016-09-11 20:25:22 +00:00
}
2016-12-30 00:46:36 +00:00
finalPosition / = btScalar ( j ) ;
2016-09-11 20:25:22 +00:00
return finalPosition ;
}
btScalar getDistanceFitness ( ) const
{
btScalar distance = 0 ;
distance = ( getPosition ( ) - m_startPosition ) . length2 ( ) ;
return distance ;
}
btScalar getFitness ( ) const
{
return getDistanceFitness ( ) ; // for now it is only distance
}
2016-10-19 16:35:01 +00:00
void resetAt ( const btVector3 & position ) {
2016-11-01 20:03:46 +00:00
removeFromWorld ( ) ;
2016-09-12 21:59:42 +00:00
btTransform resetPosition ( btQuaternion : : getIdentity ( ) , position ) ;
2016-11-01 14:34:22 +00:00
2016-11-01 20:03:46 +00:00
for ( int i = 0 ; i < JOINT_COUNT ; i + + )
2016-11-01 14:34:22 +00:00
{
2016-11-01 20:03:46 +00:00
btHingeConstraint * hingeC = static_cast < btHingeConstraint * > ( getJoints ( ) [ i ] ) ;
2016-12-27 20:00:22 +00:00
hingeC - > enableAngularMotor ( false , 0 , 0 ) ;
2016-11-01 14:34:22 +00:00
}
2016-09-11 20:25:22 +00:00
for ( int i = 0 ; i < BODYPART_COUNT ; + + i )
{
m_bodies [ i ] - > clearForces ( ) ;
m_bodies [ i ] - > setAngularVelocity ( btVector3 ( 0 , 0 , 0 ) ) ;
m_bodies [ i ] - > setLinearVelocity ( btVector3 ( 0 , 0 , 0 ) ) ;
2016-11-01 14:34:22 +00:00
m_bodies [ i ] - > setWorldTransform ( resetPosition * m_bodyRelativeTransforms [ i ] ) ;
if ( m_bodies [ i ] - > getMotionState ( ) ) {
m_bodies [ i ] - > getMotionState ( ) - > setWorldTransform ( resetPosition * m_bodyRelativeTransforms [ i ] ) ;
}
2016-09-11 20:25:22 +00:00
}
2016-11-01 20:03:46 +00:00
m_startPosition = position ; // the starting position of the walker
2016-11-01 14:34:22 +00:00
m_legUpdateAccumulator = 0 ;
2016-09-11 20:25:22 +00:00
clearTouchSensors ( ) ;
}
2016-09-12 21:59:42 +00:00
btScalar getEvaluationTime ( ) const {
2016-09-11 20:25:22 +00:00
return m_evaluationTime ;
}
2016-09-12 21:59:42 +00:00
void setEvaluationTime ( btScalar evaluationTime ) {
2016-09-11 20:25:22 +00:00
m_evaluationTime = evaluationTime ;
}
bool isInEvaluation ( ) const {
return m_inEvaluation ;
}
void setInEvaluation ( bool inEvaluation ) {
m_inEvaluation = inEvaluation ;
}
bool isReaped ( ) const {
return m_reaped ;
}
void setReaped ( bool reaped ) {
m_reaped = reaped ;
}
2016-09-12 17:42:07 +00:00
int getIndex ( ) const {
return m_index ;
}
2016-11-01 14:34:22 +00:00
btScalar getLegUpdateAccumulator ( ) const {
return m_legUpdateAccumulator ;
}
void setLegUpdateAccumulator ( btScalar legUpdateAccumulator ) {
m_legUpdateAccumulator = legUpdateAccumulator ;
}
2016-12-27 20:00:22 +00:00
void setOwnerWorld ( btDynamicsWorld * ownerWorld ) {
m_ownerWorld = ownerWorld ;
}
2016-12-30 00:46:36 +00:00
private :
void addJoints ( ) {
// add all constraints
for ( int i = 0 ; i < JOINT_COUNT ; + + i )
{
if ( m_joints [ i ] ! = NULL ) {
m_ownerWorld - > addConstraint ( m_joints [ i ] , true ) ; // important! If you add constraints back, you must set bullet physics to disable collision between constrained bodies
}
}
}
void addRigidbodies ( ) {
// add all bodies
for ( int i = 0 ; i < BODYPART_COUNT ; + + i )
{
if ( m_bodies [ i ] ! = NULL ) {
m_ownerWorld - > addRigidBody ( m_bodies [ i ] ) ;
}
}
}
void removeJoints ( ) {
// remove all constraints
for ( int i = 0 ; i < JOINT_COUNT ; + + i )
{
if ( m_joints [ i ] ! = NULL ) {
m_ownerWorld - > removeConstraint ( m_joints [ i ] ) ;
}
}
}
void removeRigidbodies ( ) {
// remove all bodies
for ( int i = 0 ; i < BODYPART_COUNT ; + + i )
{
if ( m_bodies [ i ] ! = NULL ) {
m_ownerWorld - > removeRigidBody ( m_bodies [ i ] ) ;
}
}
}
2016-09-11 20:25:22 +00:00
} ;
void evaluationUpdatePreTickCallback ( btDynamicsWorld * world , btScalar timeStep ) ;
bool legContactProcessedCallback ( btManifoldPoint & cp , void * body0 , void * body1 )
2016-07-03 17:54:47 +00:00
{
btCollisionObject * o1 = static_cast < btCollisionObject * > ( body0 ) ;
btCollisionObject * o2 = static_cast < btCollisionObject * > ( body1 ) ;
2016-07-04 17:17:10 +00:00
void * ID1 = o1 - > getUserPointer ( ) ;
void * ID2 = o2 - > getUserPointer ( ) ;
2016-07-03 17:54:47 +00:00
2016-12-30 00:46:36 +00:00
if ( ID1 ! = GROUND_ID | | ID2 ! = GROUND_ID ) { // if one of the contacts is not ground
2016-07-03 17:54:47 +00:00
// Make a circle with a 0.9 radius at (0,0,0)
// with RGB color (1,0,0).
2016-11-01 21:11:12 +00:00
if ( nn3DWalkers - > m_dynamicsWorld - > getDebugDrawer ( ) ! = NULL & & ! nn3DWalkers - > mIsHeadless ) {
nn3DWalkers - > m_dynamicsWorld - > getDebugDrawer ( ) - > drawSphere ( cp . getPositionWorldOnA ( ) , 0.1 , btVector3 ( 1. , 0. , 0. ) ) ;
2016-09-06 20:30:46 +00:00
}
2016-07-04 17:17:10 +00:00
2016-12-30 00:46:36 +00:00
if ( ID1 ! = GROUND_ID & & ID1 ) { // if ID1 is not ground
2016-07-04 17:17:10 +00:00
( ( NNWalker * ) ID1 ) - > setTouchSensor ( o1 ) ;
}
2016-12-30 00:46:36 +00:00
if ( ID2 ! = GROUND_ID & & ID2 ) { // if ID2 is not ground
2016-07-04 17:17:10 +00:00
( ( NNWalker * ) ID2 ) - > setTouchSensor ( o2 ) ;
}
2016-07-03 17:54:47 +00:00
}
return false ;
}
2016-12-27 20:00:22 +00:00
struct WalkerFilterCallback : public btOverlapFilterCallback // avoids collisions among the walkers
2016-09-12 17:42:07 +00:00
{
// return true when pairs need collision
virtual bool needBroadphaseCollision ( btBroadphaseProxy * proxy0 , btBroadphaseProxy * proxy1 ) const
{
btCollisionObject * obj0 = static_cast < btCollisionObject * > ( proxy0 - > m_clientObject ) ;
btCollisionObject * obj1 = static_cast < btCollisionObject * > ( proxy1 - > m_clientObject ) ;
if ( obj0 - > getUserPointer ( ) = = GROUND_ID | | obj1 - > getUserPointer ( ) = = GROUND_ID ) { // everything collides with ground
return true ;
}
2016-11-01 14:34:22 +00:00
else if ( ( NNWalker * ) obj0 - > getUserPointer ( ) & & ( NNWalker * ) obj1 - > getUserPointer ( ) ) {
2016-09-12 17:42:07 +00:00
return ( ( NNWalker * ) obj0 - > getUserPointer ( ) ) - > getIndex ( ) = = ( ( NNWalker * ) obj1 - > getUserPointer ( ) ) - > getIndex ( ) ;
}
2016-11-01 14:34:22 +00:00
return true ;
2016-09-12 17:42:07 +00:00
}
} ;
2016-09-06 20:30:46 +00:00
void NN3DWalkersExample : : initPhysics ( )
2016-07-01 17:35:27 +00:00
{
2016-09-16 07:49:18 +00:00
2016-09-17 22:42:34 +00:00
setupBasicParamInterface ( ) ; // parameter interface to use timewarp
2016-09-16 07:49:18 +00:00
2016-07-03 17:54:47 +00:00
gContactProcessedCallback = legContactProcessedCallback ;
2016-07-01 17:35:27 +00:00
m_guiHelper - > setUpAxis ( 1 ) ;
// Setup the basic world
2016-11-01 14:34:22 +00:00
m_SimulationTime = 0 ;
2016-07-01 17:35:27 +00:00
createEmptyDynamicsWorld ( ) ;
2016-09-11 20:25:22 +00:00
m_dynamicsWorld - > setInternalTickCallback ( evaluationUpdatePreTickCallback , this , true ) ;
2016-07-01 17:35:27 +00:00
m_guiHelper - > createPhysicsDebugDrawer ( m_dynamicsWorld ) ;
2016-12-30 00:46:36 +00:00
m_dynamicsWorld - > getDebugDrawer ( ) - > setDebugMode ( 0 ) ;
2016-07-04 17:17:10 +00:00
2016-11-01 21:11:12 +00:00
gWalkerLegTargetFrequency = 3 ; // Hz
2016-07-04 17:17:10 +00:00
// new SIMD solver for joints clips accumulated impulse, so the new limits for the motor
// should be (numberOfsolverIterations * oldLimits)
2016-11-01 21:11:12 +00:00
gWalkerMotorStrength = 0.05f * m_dynamicsWorld - > getSolverInfo ( ) . m_numIterations ;
2016-07-04 17:17:10 +00:00
{ // create a slider to change the motor update frequency
2016-11-01 21:11:12 +00:00
SliderParams slider ( " Motor update frequency " , & gWalkerLegTargetFrequency ) ;
2016-07-04 17:17:10 +00:00
slider . m_minVal = 0 ;
slider . m_maxVal = 10 ;
slider . m_clampToNotches = false ;
m_guiHelper - > getParameterInterface ( ) - > registerSliderFloatParameter (
slider ) ;
}
{ // create a slider to change the motor torque
2016-11-01 21:11:12 +00:00
SliderParams slider ( " Motor force " , & gWalkerMotorStrength ) ;
2016-07-04 17:17:10 +00:00
slider . m_minVal = 1 ;
slider . m_maxVal = 50 ;
slider . m_clampToNotches = false ;
m_guiHelper - > getParameterInterface ( ) - > registerSliderFloatParameter (
slider ) ;
}
2016-07-01 17:35:27 +00:00
2016-07-04 17:43:26 +00:00
{ // create a slider to change the root body radius
2016-11-01 21:11:12 +00:00
SliderParams slider ( " Root body radius " , & gRootBodyRadius ) ;
2016-07-04 17:43:26 +00:00
slider . m_minVal = 0.01f ;
slider . m_maxVal = 10 ;
slider . m_clampToNotches = false ;
m_guiHelper - > getParameterInterface ( ) - > registerSliderFloatParameter (
slider ) ;
}
{ // create a slider to change the root body height
2016-11-01 21:11:12 +00:00
SliderParams slider ( " Root body height " , & gRootBodyHeight ) ;
2016-07-04 17:43:26 +00:00
slider . m_minVal = 0.01f ;
slider . m_maxVal = 10 ;
slider . m_clampToNotches = false ;
m_guiHelper - > getParameterInterface ( ) - > registerSliderFloatParameter (
slider ) ;
}
{ // create a slider to change the leg radius
2016-11-01 21:11:12 +00:00
SliderParams slider ( " Leg radius " , & gLegRadius ) ;
2016-07-04 17:43:26 +00:00
slider . m_minVal = 0.01f ;
slider . m_maxVal = 10 ;
slider . m_clampToNotches = false ;
m_guiHelper - > getParameterInterface ( ) - > registerSliderFloatParameter (
slider ) ;
}
{ // create a slider to change the leg length
2016-11-01 21:11:12 +00:00
SliderParams slider ( " Leg length " , & gLegLength ) ;
2016-07-04 17:43:26 +00:00
slider . m_minVal = 0.01f ;
slider . m_maxVal = 10 ;
slider . m_clampToNotches = false ;
m_guiHelper - > getParameterInterface ( ) - > registerSliderFloatParameter (
slider ) ;
}
{ // create a slider to change the fore leg radius
2016-11-01 21:11:12 +00:00
SliderParams slider ( " Fore Leg radius " , & gForeLegRadius ) ;
2016-09-06 20:30:46 +00:00
slider . m_minVal = 0.01f ;
slider . m_maxVal = 10 ;
slider . m_clampToNotches = false ;
m_guiHelper - > getParameterInterface ( ) - > registerSliderFloatParameter (
slider ) ;
}
2016-07-04 17:43:26 +00:00
2016-09-06 20:30:46 +00:00
{ // create a slider to change the fore leg length
2016-11-01 21:11:12 +00:00
SliderParams slider ( " Fore Leg length " , & gForeLegLength ) ;
2016-09-06 20:30:46 +00:00
slider . m_minVal = 0.01f ;
slider . m_maxVal = 10 ;
slider . m_clampToNotches = false ;
m_guiHelper - > getParameterInterface ( ) - > registerSliderFloatParameter (
slider ) ;
}
2016-07-04 17:43:26 +00:00
2016-11-01 14:34:22 +00:00
if ( POPULATION_SIZE > 1 )
2016-09-12 17:42:07 +00:00
{ // create a slider to change the number of parallel evaluations
2016-11-01 21:11:12 +00:00
SliderParams slider ( " Parallel evaluations " , & gParallelEvaluations ) ;
2016-09-12 17:42:07 +00:00
slider . m_minVal = 1 ;
2016-11-01 14:34:22 +00:00
slider . m_maxVal = POPULATION_SIZE ;
2016-12-30 00:46:36 +00:00
slider . m_clampToIntegers = true ;
2016-09-12 17:42:07 +00:00
m_guiHelper - > getParameterInterface ( ) - > registerSliderFloatParameter (
slider ) ;
}
2016-11-01 20:03:46 +00:00
{ // Setup a big ground box
2016-07-01 17:35:27 +00:00
btCollisionShape * groundShape = new btBoxShape ( btVector3 ( btScalar ( 200. ) , btScalar ( 10. ) , btScalar ( 200. ) ) ) ;
m_collisionShapes . push_back ( groundShape ) ;
btTransform groundTransform ;
groundTransform . setIdentity ( ) ;
groundTransform . setOrigin ( btVector3 ( 0 , - 10 , 0 ) ) ;
2016-12-27 20:00:22 +00:00
m_ground = createRigidBody ( btScalar ( 0. ) , groundTransform , groundShape ) ;
m_ground - > setFriction ( 5 ) ;
m_ground - > setUserPointer ( GROUND_ID ) ;
2016-07-01 17:35:27 +00:00
}
2016-11-01 14:34:22 +00:00
// add walker filter making the walkers never collide with each other
2016-12-27 20:00:22 +00:00
m_filterCallback = new WalkerFilterCallback ( ) ;
m_dynamicsWorld - > getPairCache ( ) - > setOverlapFilterCallback ( m_filterCallback ) ;
2016-09-12 17:42:07 +00:00
2016-11-01 14:34:22 +00:00
// setup data sources for walkers in time series canvas
2016-11-01 18:48:39 +00:00
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 ) ;
2016-11-01 14:34:22 +00:00
for ( int i = 0 ; i < POPULATION_SIZE ; i + + ) {
2016-12-27 20:00:22 +00:00
m_timeSeriesCanvas - > addDataSource ( " " , 100 * i / POPULATION_SIZE , 100 * ( POPULATION_SIZE - i ) / POPULATION_SIZE , 100 * i / POPULATION_SIZE ) ;
2016-09-12 14:36:37 +00:00
}
2016-07-01 17:35:27 +00:00
2016-11-01 20:03:46 +00:00
m_walkersInPopulation . resize ( POPULATION_SIZE , NULL ) ;
2016-12-30 00:46:36 +00:00
for ( int i = 0 ; i < POPULATION_SIZE ; i + + ) { // spawn walkers
2016-11-01 20:03:46 +00:00
resetWalkerAt ( i , m_resetPosition ) ;
}
2016-07-01 17:35:27 +00:00
}
2016-12-27 20:00:22 +00:00
void NN3DWalkersExample : : performModelUpdate ( float deltaTime ) {
2016-12-30 00:46:36 +00:00
if ( m_rebuildWorldNeeded ) {
2016-12-27 20:00:22 +00:00
recreateWorld ( ) ;
2016-12-30 00:46:36 +00:00
m_rebuildWorldNeeded = false ;
2016-12-27 20:00:22 +00:00
}
}
void NN3DWalkersExample : : recreateWorld ( ) {
2016-12-30 00:46:36 +00:00
for ( int i = 0 ; i < POPULATION_SIZE ; i + + ) { // remove walkers
2016-12-27 20:00:22 +00:00
m_walkersInPopulation [ i ] - > removeFromWorld ( ) ;
}
2016-12-30 00:46:36 +00:00
m_dynamicsWorld - > removeRigidBody ( m_ground ) ; // remove ground
// delete world
2016-12-27 20:00:22 +00:00
delete m_dynamicsWorld ;
m_dynamicsWorld = 0 ;
delete m_solver ;
m_solver = 0 ;
delete m_broadphase ;
m_broadphase = 0 ;
delete m_dispatcher ;
m_dispatcher = 0 ;
delete m_collisionConfiguration ;
m_collisionConfiguration = 0 ;
2016-12-30 00:46:36 +00:00
createEmptyDynamicsWorld ( ) ; // create new world
2016-12-27 20:00:22 +00:00
2016-12-30 00:46:36 +00:00
// add all filters and callbacks
2016-12-27 20:00:22 +00:00
m_dynamicsWorld - > setInternalTickCallback ( evaluationUpdatePreTickCallback , this , true ) ; // set evolution update pretick callback
m_dynamicsWorld - > getPairCache ( ) - > setOverlapFilterCallback ( m_filterCallback ) ; // avoid collisions between walkers
m_guiHelper - > createPhysicsDebugDrawer ( m_dynamicsWorld ) ;
2016-12-30 00:46:36 +00:00
m_dynamicsWorld - > getDebugDrawer ( ) - > setDebugMode ( 0 ) ;
2016-12-27 20:00:22 +00:00
m_dynamicsWorld - > addRigidBody ( m_ground ) ; // readd ground
2016-12-30 00:46:36 +00:00
for ( int i = 0 ; i < POPULATION_SIZE ; i + + ) { // readd walkers
2016-12-27 20:00:22 +00:00
m_walkersInPopulation [ i ] - > setOwnerWorld ( m_dynamicsWorld ) ;
if ( m_walkersInPopulation [ i ] - > isInEvaluation ( ) ) {
m_walkersInPopulation [ i ] - > addToWorld ( ) ;
}
}
}
2016-09-11 20:25:22 +00:00
bool NN3DWalkersExample : : detectCollisions ( )
2016-07-01 17:35:27 +00:00
{
2016-09-11 20:25:22 +00:00
bool collisionDetected = false ;
if ( m_dynamicsWorld ) {
m_dynamicsWorld - > performDiscreteCollisionDetection ( ) ; // let the collisions be calculated
}
2016-07-01 17:35:27 +00:00
2016-09-11 20:25:22 +00:00
int numManifolds = m_dynamicsWorld - > getDispatcher ( ) - > getNumManifolds ( ) ;
2016-12-30 00:46:36 +00:00
for ( int i = 0 ; i < numManifolds ; i + + ) // for each collision
2016-09-11 20:25:22 +00:00
{
btPersistentManifold * contactManifold = m_dynamicsWorld - > getDispatcher ( ) - > getManifoldByIndexInternal ( i ) ;
2016-12-30 00:46:36 +00:00
// get collision objects of collision
2016-09-11 20:25:22 +00:00
const btCollisionObject * obA = contactManifold - > getBody0 ( ) ;
const btCollisionObject * obB = contactManifold - > getBody1 ( ) ;
2016-07-01 17:35:27 +00:00
2016-12-30 00:46:36 +00:00
if ( obA - > getUserPointer ( ) ! = GROUND_ID & & obB - > getUserPointer ( ) ! = GROUND_ID ) { // if one of them is not ground
2016-07-03 17:54:47 +00:00
2016-09-11 20:25:22 +00:00
int numContacts = contactManifold - > getNumContacts ( ) ;
2016-12-30 00:46:36 +00:00
for ( int j = 0 ; j < numContacts ; j + + ) // for each collision contact
2016-07-03 17:54:47 +00:00
{
2016-09-11 20:25:22 +00:00
collisionDetected = true ;
btManifoldPoint & pt = contactManifold - > getContactPoint ( j ) ;
2016-12-30 00:46:36 +00:00
if ( pt . getDistance ( ) < 0.f ) // if collision is penetrating
2016-09-11 20:25:22 +00:00
{
const btVector3 & ptA = pt . getPositionWorldOnA ( ) ;
const btVector3 & ptB = pt . getPositionWorldOnB ( ) ;
const btVector3 & normalOnB = pt . m_normalWorldOnB ;
2016-07-04 17:17:10 +00:00
2016-09-11 20:25:22 +00:00
if ( ! DRAW_INTERPENETRATIONS ) {
return collisionDetected ;
2016-07-04 17:17:10 +00:00
}
2016-11-01 21:11:12 +00:00
if ( m_dynamicsWorld - > getDebugDrawer ( ) & & ! mIsHeadless ) { // draw self collisions
2016-09-11 20:25:22 +00:00
m_dynamicsWorld - > getDebugDrawer ( ) - > drawSphere ( pt . getPositionWorldOnA ( ) , 0.1 , btVector3 ( 0. , 0. , 1. ) ) ;
m_dynamicsWorld - > getDebugDrawer ( ) - > drawSphere ( pt . getPositionWorldOnB ( ) , 0.1 , btVector3 ( 0. , 0. , 1. ) ) ;
}
2016-07-04 17:17:10 +00:00
}
2016-07-03 17:54:47 +00:00
}
2016-07-01 17:35:27 +00:00
}
}
2016-09-11 20:25:22 +00:00
return collisionDetected ;
2016-07-01 17:35:27 +00:00
}
2016-09-06 20:30:46 +00:00
bool NN3DWalkersExample : : keyboardCallback ( int key , int state )
2016-07-01 17:35:27 +00:00
{
switch ( key )
{
case ' [ ' :
2016-11-01 21:11:12 +00:00
gWalkerMotorStrength / = 1.1f ;
2016-07-01 17:35:27 +00:00
return true ;
case ' ] ' :
2016-11-01 21:11:12 +00:00
gWalkerMotorStrength * = 1.1f ;
2016-07-01 17:35:27 +00:00
return true ;
2016-09-12 14:36:37 +00:00
case ' l ' :
2016-12-27 20:00:22 +00:00
// printWalkerConfigs();
2016-09-17 22:42:34 +00:00
return true ;
2016-07-01 17:35:27 +00:00
default :
break ;
}
2016-10-22 20:50:08 +00:00
return NN3DWalkersTimeWarpBase : : keyboardCallback ( key , state ) ;
2016-07-01 17:35:27 +00:00
}
2016-09-06 20:30:46 +00:00
void NN3DWalkersExample : : exitPhysics ( )
2016-07-01 17:35:27 +00:00
{
2016-08-02 18:38:36 +00:00
gContactProcessedCallback = NULL ; // clear contact processed callback on exiting
2016-11-01 14:34:22 +00:00
for ( int i = 0 ; i < POPULATION_SIZE ; i + + )
2016-07-01 17:35:27 +00:00
{
2016-09-11 20:25:22 +00:00
NNWalker * walker = m_walkersInPopulation [ i ] ;
2016-07-01 17:35:27 +00:00
delete walker ;
}
CommonRigidBodyBase : : exitPhysics ( ) ;
}
2016-09-11 20:25:22 +00:00
class CommonExampleInterface * ET_NN3DWalkersCreateFunc ( struct CommonExampleOptions & options )
2016-07-01 17:35:27 +00:00
{
2016-09-06 20:30:46 +00:00
nn3DWalkers = new NN3DWalkersExample ( options . m_guiHelper ) ;
2016-07-03 17:54:47 +00:00
return nn3DWalkers ;
2016-07-01 17:35:27 +00:00
}
2016-09-11 20:25:22 +00:00
bool fitnessComparator ( const NNWalker * a , const NNWalker * b )
{
2016-09-12 14:36:37 +00:00
return a - > getFitness ( ) > b - > getFitness ( ) ; // sort walkers descending
2016-09-11 20:25:22 +00:00
}
void NN3DWalkersExample : : rateEvaluations ( ) {
m_walkersInPopulation . quickSort ( fitnessComparator ) ; // Sort walkers by fitness
2016-07-01 17:35:27 +00:00
2016-09-11 20:25:22 +00:00
b3Printf ( " Best performing walker: %f meters " , btSqrt ( m_walkersInPopulation [ 0 ] - > getDistanceFitness ( ) ) ) ;
2016-12-27 20:00:22 +00:00
// if not all walkers are reaped and the best walker is worse than is had been in the previous round
if ( ( POPULATION_SIZE - 1 ) * ( 1 - REAP_QTY ) ! = 0 & & btSqrt ( m_walkersInPopulation [ 0 ] - > getDistanceFitness ( ) ) < m_bestWalkerFitness ) {
2016-11-01 14:34:22 +00:00
b3Printf ( " ################Simulation not deterministic########################### " ) ;
2016-09-12 14:36:37 +00:00
}
2016-11-01 14:34:22 +00:00
else {
m_bestWalkerFitness = btSqrt ( m_walkersInPopulation [ 0 ] - > getDistanceFitness ( ) ) ;
}
for ( int i = 0 ; i < POPULATION_SIZE ; i + + ) { // plot walker fitnesses for this round
m_timeSeriesCanvas - > insertDataAtCurrentTime ( btSqrt ( m_walkersInPopulation [ i ] - > getDistanceFitness ( ) ) , i , true ) ;
}
2016-12-30 00:46:36 +00:00
m_timeSeriesCanvas - > nextTick ( ) ; // move to next tick of graph
2016-09-12 14:36:37 +00:00
2016-11-01 14:34:22 +00:00
for ( int i = 0 ; i < POPULATION_SIZE ; i + + ) { // reset all walkers
2016-09-11 20:25:22 +00:00
m_walkersInPopulation [ i ] - > setEvaluationTime ( 0 ) ;
}
2016-11-01 14:34:22 +00:00
m_nextReapedIndex = 0 ;
2016-07-01 17:35:27 +00:00
}
2016-09-11 20:25:22 +00:00
void NN3DWalkersExample : : reap ( ) {
int reaped = 0 ;
2016-11-01 14:34:22 +00:00
for ( int i = POPULATION_SIZE - 1 ; i > = ( POPULATION_SIZE - 1 ) * ( 1 - REAP_QTY ) ; i - - ) { // reap a certain percentage of walkers to replace them afterwards
2016-09-11 20:25:22 +00:00
m_walkersInPopulation [ i ] - > setReaped ( true ) ;
reaped + + ;
}
2016-11-01 14:34:22 +00:00
b3Printf ( " %i Walker(s) reaped. " , reaped ) ;
2016-07-01 17:35:27 +00:00
}
2016-11-01 14:34:22 +00:00
/**
* Return a random elitist walker ( one that is not mutated at all because it performs well ) .
* @ return Random elitist walker .
*/
2016-09-11 20:25:22 +00:00
NNWalker * NN3DWalkersExample : : getRandomElite ( ) {
2016-11-01 14:34:22 +00:00
return m_walkersInPopulation [ ( ( POPULATION_SIZE - 1 ) * SOW_ELITE_QTY ) * ( rand ( ) / RAND_MAX ) ] ;
2016-07-01 17:35:27 +00:00
}
2016-11-01 14:34:22 +00:00
/**
* Return a random non - elitist walker ( a mutated walker ) .
* @ return
*/
2016-09-11 20:25:22 +00:00
NNWalker * NN3DWalkersExample : : getRandomNonElite ( ) {
2016-11-01 14:34:22 +00:00
return m_walkersInPopulation [ ( POPULATION_SIZE - 1 ) * SOW_ELITE_QTY + ( POPULATION_SIZE - 1 ) * ( 1.0f - SOW_ELITE_QTY ) * ( rand ( ) / RAND_MAX ) ] ;
2016-07-01 17:35:27 +00:00
}
2016-07-03 17:54:47 +00:00
2016-11-01 14:34:22 +00:00
/**
* Get the next reaped walker to be replaced .
* @ return
*/
2016-09-11 20:25:22 +00:00
NNWalker * NN3DWalkersExample : : getNextReaped ( ) {
2016-11-01 14:34:22 +00:00
if ( ( POPULATION_SIZE - 1 ) - m_nextReapedIndex > = ( POPULATION_SIZE - 1 ) * ( 1 - REAP_QTY ) ) {
m_nextReapedIndex + + ;
2016-09-11 20:25:22 +00:00
}
2016-11-01 14:34:22 +00:00
if ( m_walkersInPopulation [ ( POPULATION_SIZE - 1 ) - m_nextReapedIndex + 1 ] - > isReaped ( ) ) {
return m_walkersInPopulation [ ( POPULATION_SIZE - 1 ) - m_nextReapedIndex + 1 ] ;
2016-09-12 14:36:37 +00:00
}
else {
return NULL ; // we asked for too many
}
2016-09-11 20:25:22 +00:00
}
2016-11-01 14:34:22 +00:00
/**
* Sow new walkers .
*/
2016-09-11 20:25:22 +00:00
void NN3DWalkersExample : : sow ( ) {
int sow = 0 ;
2016-11-01 14:34:22 +00:00
for ( int i = 0 ; i < POPULATION_SIZE * ( SOW_CROSSOVER_QTY ) ; i + + ) { // create number of new crossover creatures
2016-09-11 20:25:22 +00:00
sow + + ;
2016-09-12 21:59:42 +00:00
NNWalker * mother = getRandomElite ( ) ; // Get elite partner (mother)
NNWalker * father = ( SOW_ELITE_PARTNER < rand ( ) / RAND_MAX ) ? getRandomElite ( ) : getRandomNonElite ( ) ; //Get elite or random partner (father)
2016-09-11 20:25:22 +00:00
NNWalker * offspring = getNextReaped ( ) ;
crossover ( mother , father , offspring ) ;
}
2016-11-01 14:34:22 +00:00
for ( int i = POPULATION_SIZE * SOW_ELITE_QTY ; i < POPULATION_SIZE * ( SOW_ELITE_QTY + SOW_MUTATION_QTY ) ; i + + ) { // create mutants
mutate ( m_walkersInPopulation [ i ] , btScalar ( MUTATION_RATE / ( POPULATION_SIZE * SOW_MUTATION_QTY ) * ( i - POPULATION_SIZE * SOW_ELITE_QTY ) ) ) ;
2016-09-11 20:25:22 +00:00
}
2016-11-01 14:34:22 +00:00
for ( int i = 0 ; i < ( POPULATION_SIZE - 1 ) * ( REAP_QTY - SOW_CROSSOVER_QTY ) ; i + + ) {
2016-09-11 20:25:22 +00:00
sow + + ;
NNWalker * reaped = getNextReaped ( ) ;
reaped - > setReaped ( false ) ;
reaped - > randomizeSensoryMotorWeights ( ) ;
}
2016-11-01 14:34:22 +00:00
b3Printf ( " %i Walker(s) sown. " , sow ) ;
2016-09-11 20:25:22 +00:00
}
2016-11-01 14:34:22 +00:00
/**
* Crossover mother and father into the child .
* @ param mother
* @ param father
* @ param child
*/
2016-09-11 20:25:22 +00:00
void NN3DWalkersExample : : crossover ( NNWalker * mother , NNWalker * father , NNWalker * child ) {
for ( int i = 0 ; i < BODYPART_COUNT * JOINT_COUNT ; i + + ) {
btScalar random = ( ( double ) rand ( ) / ( RAND_MAX ) ) ;
if ( random > = 0.5f ) {
child - > getSensoryMotorWeights ( ) [ i ] = mother - > getSensoryMotorWeights ( ) [ i ] ;
}
else
{
child - > getSensoryMotorWeights ( ) [ i ] = father - > getSensoryMotorWeights ( ) [ i ] ;
}
}
2016-07-03 17:54:47 +00:00
}
2016-11-01 14:34:22 +00:00
/**
* Mutate the mutant .
* @ param mutant
* @ param mutationRate
*/
2016-09-12 21:59:42 +00:00
void NN3DWalkersExample : : mutate ( NNWalker * mutant , btScalar mutationRate ) {
2016-09-11 20:25:22 +00:00
for ( int i = 0 ; i < BODYPART_COUNT * JOINT_COUNT ; i + + ) {
btScalar random = ( ( double ) rand ( ) / ( RAND_MAX ) ) ;
if ( random > = mutationRate ) {
mutant - > getSensoryMotorWeights ( ) [ i ] = ( ( double ) rand ( ) / ( RAND_MAX ) ) * 2.0f - 1.0f ;
}
}
}
2016-11-01 14:34:22 +00:00
/**
* Update the demo via pretick callback to be precise .
* @ param world
* @ param timeStep
*/
2016-09-11 20:25:22 +00:00
void evaluationUpdatePreTickCallback ( btDynamicsWorld * world , btScalar timeStep ) {
NN3DWalkersExample * nnWalkersDemo = ( NN3DWalkersExample * ) world - > getWorldUserInfo ( ) ;
nnWalkersDemo - > update ( timeStep ) ;
}
2016-11-01 14:34:22 +00:00
/**
* Update cycle .
* @ param timeSinceLastTick
*/
2016-09-12 21:59:42 +00:00
void NN3DWalkersExample : : update ( const btScalar timeSinceLastTick ) {
2016-09-11 20:25:22 +00:00
updateEvaluations ( timeSinceLastTick ) ; /**!< We update all evaluations that are in the loop */
scheduleEvaluations ( ) ; /**!< Start new evaluations and finish the old ones. */
2016-09-12 14:36:37 +00:00
2016-09-12 21:59:42 +00:00
drawMarkings ( ) ; /**!< Draw markings on the ground */
2016-09-17 22:42:34 +00:00
2016-12-30 00:46:36 +00:00
if ( m_SimulationTime > m_LastSpeedupPrintTimestamp + TIMESTAMP_TIME ) { // print effective speedup every x seconds
2016-09-17 22:52:08 +00:00
b3Printf ( " Avg Effective speedup: %f real time " , calculatePerformedSpeedup ( ) ) ;
2016-11-01 14:34:22 +00:00
m_LastSpeedupPrintTimestamp = m_SimulationTime ;
2016-09-17 22:52:08 +00:00
}
2016-09-11 20:25:22 +00:00
}
2016-11-01 14:34:22 +00:00
/**
* Update the evaluations .
* @ param timeSinceLastTick
*/
2016-09-11 20:25:22 +00:00
void NN3DWalkersExample : : updateEvaluations ( const btScalar timeSinceLastTick ) {
btScalar delta = timeSinceLastTick ;
2016-09-12 21:59:42 +00:00
btScalar minFPS = 1.f / 60.f ;
2016-09-11 20:25:22 +00:00
if ( delta > minFPS ) {
delta = minFPS ;
}
2016-11-01 14:34:22 +00:00
m_SimulationTime + = delta ;
2016-09-11 20:25:22 +00:00
2016-11-01 20:03:46 +00:00
for ( int r = 0 ; r < POPULATION_SIZE ; r + + ) // evaluation time passes
2016-09-11 20:25:22 +00:00
{
2016-11-01 20:03:46 +00:00
if ( m_walkersInPopulation [ r ] ! = NULL & & m_walkersInPopulation [ r ] - > isInEvaluation ( ) ) {
m_walkersInPopulation [ r ] - > setEvaluationTime ( m_walkersInPopulation [ r ] - > getEvaluationTime ( ) + delta ) ; // increase evaluation time
2016-09-11 20:25:22 +00:00
2016-11-01 14:34:22 +00:00
m_walkersInPopulation [ r ] - > setLegUpdateAccumulator ( m_walkersInPopulation [ r ] - > getLegUpdateAccumulator ( ) + delta ) ;
2016-12-30 00:46:36 +00:00
if ( m_walkersInPopulation [ r ] - > getLegUpdateAccumulator ( ) > = btScalar ( 1.0f ) / gWalkerLegTargetFrequency ) // we update the leg movement with leg target frequency
2016-09-11 20:25:22 +00:00
{
2016-11-01 14:34:22 +00:00
m_walkersInPopulation [ r ] - > setLegUpdateAccumulator ( 0 ) ;
for ( int i = 0 ; i < 2 * NUM_WALKER_LEGS ; i + + )
2016-09-11 20:25:22 +00:00
{
2016-11-01 14:34:22 +00:00
btScalar targetAngle = 0 ; // angle in range [0,1]
2016-09-11 20:25:22 +00:00
btHingeConstraint * hingeC = static_cast < btHingeConstraint * > ( m_walkersInPopulation [ r ] - > getJoints ( ) [ i ] ) ;
2016-11-01 20:03:46 +00:00
2016-12-30 00:46:36 +00:00
if ( hingeC ! = NULL ) { // if hinge exists
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 ) ;
}
2016-09-11 20:25:22 +00:00
2016-12-30 00:46:36 +00:00
targetAngle = ( tanh ( targetAngle ) + 1.0f ) * 0.5f ; // apply the activation function (threshold) [0;1]
2016-09-11 20:25:22 +00:00
2016-12-30 00:46:36 +00:00
btScalar targetLimitAngle = hingeC - > getLowerLimit ( ) + targetAngle * ( hingeC - > getUpperLimit ( ) - hingeC - > getLowerLimit ( ) ) ; // [lowerLimit;upperLimit]
btScalar currentAngle = hingeC - > getHingeAngle ( ) ;
btScalar angleError = targetLimitAngle - currentAngle ; // target current delta
btScalar desiredAngularVel = angleError / ( ( delta > 0 ) ? delta : btScalar ( 0.0001f ) ) ; // division by zero safety
2016-09-11 20:25:22 +00:00
2016-12-30 00:46:36 +00:00
hingeC - > enableAngularMotor ( true , desiredAngularVel , gWalkerMotorStrength ) ; // set new target velocity
}
2016-11-01 14:34:22 +00:00
}
2016-09-11 20:25:22 +00:00
}
2016-11-01 14:34:22 +00:00
// clear sensor signals after usage
m_walkersInPopulation [ r ] - > clearTouchSensors ( ) ;
2016-09-11 20:25:22 +00:00
}
}
}
2016-11-01 14:34:22 +00:00
/**
* Schedule the walker evaluations .
*/
2016-09-11 20:25:22 +00:00
void NN3DWalkersExample : : scheduleEvaluations ( ) {
2016-11-01 14:34:22 +00:00
for ( int i = 0 ; i < POPULATION_SIZE ; i + + ) {
2016-09-11 20:25:22 +00:00
2016-11-01 14:34:22 +00:00
if ( m_walkersInPopulation [ i ] - > isInEvaluation ( ) & & m_walkersInPopulation [ i ] - > getEvaluationTime ( ) > = EVALUATION_DURATION ) { /**!< tear down evaluations */
b3Printf ( " An evaluation finished at %f s. Distance: %f m " , m_SimulationTime , btSqrt ( m_walkersInPopulation [ i ] - > getDistanceFitness ( ) ) ) ;
2016-09-11 20:25:22 +00:00
m_walkersInPopulation [ i ] - > removeFromWorld ( ) ;
2016-11-01 14:34:22 +00:00
m_walkersInEvaluation - - ;
2016-09-11 20:25:22 +00:00
}
2016-11-01 21:11:12 +00:00
if ( m_walkersInEvaluation < gParallelEvaluations & & ! m_walkersInPopulation [ i ] - > isInEvaluation ( ) & & m_walkersInPopulation [ i ] - > getEvaluationTime ( ) = = 0 ) { /**!< Setup the new evaluations */
2016-11-01 14:34:22 +00:00
b3Printf ( " An evaluation started at %f s. " , m_SimulationTime ) ;
m_walkersInEvaluation + + ;
2016-09-12 17:42:07 +00:00
2016-11-01 14:34:22 +00:00
if ( REBUILD_WALKER ) { // deletes and recreates the walker in the position
2017-05-28 13:10:45 +00:00
// m_guiHelper->removeAllGraphicsInstances();
// m_ground->setUserIndex(-1); // reset to get a new graphics object
// m_ground->setUserIndex2(-1); // reset to get a new graphics object
// m_ground->getCollisionShape()->setUserIndex(-1); // reset to get a new graphics object
2016-12-27 20:00:22 +00:00
2016-11-01 14:34:22 +00:00
resetWalkerAt ( i , m_resetPosition ) ;
2016-09-12 17:42:07 +00:00
}
2016-11-01 14:34:22 +00:00
else { // resets the position of the walker without deletion
m_walkersInPopulation [ i ] - > resetAt ( m_resetPosition ) ;
}
2016-09-11 20:25:22 +00:00
m_walkersInPopulation [ i ] - > addToWorld ( ) ;
}
}
2016-12-27 20:00:22 +00:00
if ( ! mIsHeadless ) { // after all changes, regenerate graphics objects
m_guiHelper - > autogenerateGraphicsObjects ( m_dynamicsWorld ) ;
}
2016-11-01 14:34:22 +00:00
if ( m_walkersInEvaluation = = 0 ) { // if there are no more evaluations possible
2016-12-27 20:00:22 +00:00
if ( ! REBUILD_WALKER ) {
2016-12-30 00:46:36 +00:00
m_rebuildWorldNeeded = true ;
2016-12-27 20:00:22 +00:00
}
2016-09-11 20:25:22 +00:00
rateEvaluations ( ) ; // rate evaluations by sorting them based on their fitness
reap ( ) ; // reap worst performing walkers
2016-12-27 20:00:22 +00:00
sow ( ) ; // crossover, mutate and sow new walkers
2016-09-11 20:25:22 +00:00
b3Printf ( " ### A new generation started. ### " ) ;
}
2016-07-03 17:54:47 +00:00
}
2016-09-12 14:36:37 +00:00
2016-11-01 14:34:22 +00:00
void NN3DWalkersExample : : resetWalkerAt ( int i , const btVector3 & resetPosition ) {
2016-11-01 20:03:46 +00:00
NNWalker * newWalker = new NNWalker ( i , m_dynamicsWorld , resetPosition ,
2016-11-01 21:11:12 +00:00
gRootBodyRadius ,
gRootBodyHeight ,
gLegRadius ,
gLegLength ,
gForeLegRadius ,
gForeLegLength ,
2016-11-01 20:03:46 +00:00
false ) ;
if ( m_walkersInPopulation [ i ] ! = NULL ) {
newWalker - > copySensoryMotorWeights ( m_walkersInPopulation [ i ] - > getSensoryMotorWeights ( ) ) ;
delete m_walkersInPopulation [ i ] ;
}
2016-11-01 14:34:22 +00:00
m_walkersInPopulation [ i ] = newWalker ;
}
/**
* Draw distance markings on the ground .
*/
2016-09-12 14:36:37 +00:00
void NN3DWalkersExample : : drawMarkings ( ) {
2016-09-17 23:03:41 +00:00
if ( ! mIsHeadless ) {
2016-11-01 14:34:22 +00:00
for ( int i = 0 ; i < POPULATION_SIZE ; i + + ) // draw current distance plates of moving walkers
2016-09-17 22:42:34 +00:00
{
if ( m_walkersInPopulation [ i ] - > isInEvaluation ( ) ) {
btVector3 walkerPosition = m_walkersInPopulation [ i ] - > getPosition ( ) ;
2016-10-19 19:20:57 +00:00
char performance [ 20 ] ;
2016-09-17 22:42:34 +00:00
sprintf ( performance , " %.2f m " , btSqrt ( m_walkersInPopulation [ i ] - > getDistanceFitness ( ) ) ) ;
2016-10-21 15:52:11 +00:00
m_guiHelper - > drawText3D ( performance , walkerPosition . x ( ) , walkerPosition . y ( ) + 1 , walkerPosition . z ( ) , 1 ) ;
2016-09-17 22:42:34 +00:00
}
2016-09-12 14:36:37 +00:00
}
2016-11-01 21:11:12 +00:00
if ( m_dynamicsWorld - > getDebugDrawer ( ) & & ! mIsHeadless ) {
for ( int i = 2 ; i < 50 ; i + = 2 ) { // draw distance circles
2016-09-17 22:42:34 +00:00
m_dynamicsWorld - > getDebugDrawer ( ) - > drawArc ( btVector3 ( 0 , 0 , 0 ) , btVector3 ( 0 , 1 , 0 ) , btVector3 ( 1 , 0 , 0 ) , btScalar ( i ) , btScalar ( i ) , btScalar ( 0 ) , btScalar ( SIMD_2_PI ) , btVector3 ( 10 * i , 0 , 0 ) , false ) ;
}
2016-09-12 14:36:37 +00:00
}
}
}
2016-11-01 14:34:22 +00:00
/**
* Print walker neural network layer configurations .
2016-12-27 20:00:22 +00:00
*/
//void NN3DWalkersExample::printWalkerConfigs(){
// char configString[25 + POPULATION_SIZE*BODYPART_COUNT*JOINT_COUNT*(3+15+1) + POPULATION_SIZE*4 + 1]; // 15 precision + [],\n
// char* runner = configString;
// sprintf(runner,"Population configuration:");
// runner +=25;
// for(int i = 0;i < POPULATION_SIZE;i++) {
// runner[0] = '\n';
// runner++;
// runner[0] = '[';
// runner++;
// for(int j = 0; j < BODYPART_COUNT*JOINT_COUNT;j++) {
// sprintf(runner,"%.15f", m_walkersInPopulation[i]->getSensoryMotorWeights()[j]);
// runner +=15;
// if(j + 1 < BODYPART_COUNT*JOINT_COUNT){
// runner[0] = ',';
// }
// else{
// runner[0] = ']';
// }
// runner++;
// }
// }
// runner[0] = '\0';
// b3Printf(configString);
//}