[1169] | 1 | # The recording of the "center of gravity" (or mass) of all Parts of a creature during its lifespan, and
|
---|
| 2 | # the recording of coordinates of all Parts are stored as data->bodyrecording.
|
---|
| 3 | # Use STORE_ALL_PART_COORDS below to decide how much data you need recorded - maybe only COG and no Parts.
|
---|
| 4 | #
|
---|
| 5 | # If STORE_ALL_PART_COORDS=0 below, only COG is stored and the format is
|
---|
| 6 | # [ [cog1x,cog1y,cog1z], [cog2x,cog2y,cog2z], [cog3x,cog3y,cog3z], ...]
|
---|
[1305] | 7 | # where index numbers in the names are simulation steps.
|
---|
[1169] | 8 | # So you get a vector of COG x,y,z coordinates repeated for every simulation step.
|
---|
| 9 | #
|
---|
| 10 | # If STORE_ALL_PART_COORDS=1 below, the format is more verbose with one more level of nesting, because after the COG,
|
---|
[1305] | 11 | # the list of coordinates of all Parts follows (the first index in the names below is the simulation step, the second one is Part number)
|
---|
[1169] | 12 | # [ [[cog1x,cog1y,cog1z], [p1_1x,p1_1y,p1_1z], [p1_2x,p1_2y,p1_2z], ...], ...]
|
---|
| 13 | #
|
---|
| 14 | # You can further limit the amount of stored data by recording coordinates less frequently - see onCreaturesStep() comment below.
|
---|
| 15 | # Adjust 'Energy0' to achieve the lifespan you need.
|
---|
| 16 | # 'evalcount' should likely be 1 unless you need other performance criteria (like vertpos or distance) averaged from multiple evaluations.
|
---|
[1221] | 17 | # Put this file in the "data" subdirectory within the Framsticks distribution unless you prefer to provide its path when loading.
|
---|
[1169] | 18 |
|
---|
| 19 | sim_params:
|
---|
| 20 | expdef:standard-eval
|
---|
| 21 | evalplan:~
|
---|
| 22 | :numparts,numjoints,numneurons,numconnections,instances,lifespan,velocity,distance,vertvel,vertpos,fit,fit_stdev,time,data->bodyrecording~
|
---|
| 23 | usercode:~
|
---|
| 24 | function onBorn(cr)
|
---|
| 25 | {
|
---|
| 26 | super_onBorn(cr);
|
---|
[1305] | 27 | cr.data->bodyrecording=[]; //in the creature's "data" dictionary, create the key "bodyrecording" and initialize its value to empty vector. Equivalent to cr.data["bodyrecording"]=[]
|
---|
[1169] | 28 | }
|
---|
| 29 |
|
---|
| 30 | function onCreaturesStep(cr) //change to onCreaturesUpdate(cr) if you want to record every "perfperiod" steps instead of every single step
|
---|
| 31 | {
|
---|
| 32 | //super_onCreaturesStep(cr); //there is no onCreaturesStep() defined in parent expdef
|
---|
| 33 | record(cr);
|
---|
| 34 | }
|
---|
| 35 |
|
---|
| 36 | function addGenotypePerformanceFromCreature(g, cr) //this function is called twice per one evaluation, see comments in super_addGenotypePerformanceFromCreature(). For each evaluation, it is called once with g.instances=0 and empty g.data (to collect a single copy of cr.data) and then once again for instances>=0 (to aggregate cr.data into g.data according to a custom logic implemented in this function).
|
---|
| 37 | /*
|
---|
| 38 | For example for evalcount=3, if we wanted to aggregate vectors by appending them:
|
---|
| 39 | evaluation #1, instances=0: we append [1,2,3] to empty
|
---|
| 40 | evaluation #1, instances=0: we append [1,2,3] to empty
|
---|
| 41 | evaluation #2, instances=0: we append [4,5,6] to empty
|
---|
| 42 | evaluation #2, instances=1: we append [4,5,6] to [1,2,3]
|
---|
| 43 | evaluation #3, instances=0: we append [7,8,9] to empty
|
---|
| 44 | evaluation #3, instances=2: we append [7,8,9] to [1,2,3],[4,5,6]
|
---|
| 45 | */
|
---|
| 46 | {
|
---|
| 47 | //In the code below, we do not support evalcount>1, i.e. we do not collect more information from more evaluations. The last evaluation wins, so we do not have any "aggregation logic" here.
|
---|
| 48 | //Simulator.print(g.instances); //for debugging double-calls if we ever wanted to have some aggregation logic (then also display g.data)
|
---|
| 49 | super_addGenotypePerformanceFromCreature(g, cr);
|
---|
| 50 |
|
---|
[1305] | 51 | g.data->bodyrecording = cr.data->bodyrecording; //no averaging or any other form of aggregation - here assuming we only evaluate a given Genotype object once; if not, then we ignore (overwrite) recordings from previous evaluations of this genotype
|
---|
[1169] | 52 |
|
---|
| 53 | //Simulator.print("Recorded time steps: %d" % g.data->bodyrecording.size); //just for debugging
|
---|
| 54 | return g;
|
---|
| 55 | }
|
---|
| 56 |
|
---|
[1170] | 57 |
|
---|
| 58 | // If needed, you can modify the function below to record the bounding box of the agent (to know the extreme values of Part coordinates
|
---|
| 59 | // without recording the coordinates of all Parts), to record MechJoint propertes, Neuro signals etc. See available fields in
|
---|
| 60 | // http://www.framsticks.com/files/classdoc/c_creature.html
|
---|
[1169] | 61 | function record(cr)
|
---|
| 62 | {
|
---|
| 63 | const STORE_ALL_PART_COORDS = 1; //set to 0 to significantly reduce the amount of data recorded (will only record COG, not all Parts)
|
---|
| 64 | if (cr.perf_measuring == 1) //record body position only when the creature is in the "performance measuring" period
|
---|
| 65 | {
|
---|
[1312] | 66 | var cog = cr.centerOfGravity.toVector; // toVector yields [centerOfGravity.x, centerOfGravity.y, centerOfGravityg.z]
|
---|
[1169] | 67 | if (STORE_ALL_PART_COORDS)
|
---|
| 68 | {
|
---|
| 69 | var now = [cog];
|
---|
| 70 | for (var j=0; j<cr.numparts; j++)
|
---|
| 71 | {
|
---|
| 72 | var part = cr.getMechPart(j);
|
---|
| 73 | now.add([part.x, part.y, part.z]);
|
---|
| 74 | }
|
---|
| 75 | cr.data->bodyrecording.add(now);
|
---|
| 76 | } else
|
---|
| 77 | cr.data->bodyrecording.add(cog);
|
---|
| 78 | }
|
---|
| 79 | }
|
---|
| 80 |
|
---|
| 81 | ~
|
---|