[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], ...]
|
---|
| 7 | # where numbers are simulation steps.
|
---|
| 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,
|
---|
| 11 | # the list of coordinates of all Parts follows (the first number below is the simulation step, the second is Part number)
|
---|
| 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.
|
---|
| 17 | # Put this file in the "data" subdirectory within the Framsticks distribution.
|
---|
| 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);
|
---|
| 27 | cr.data->bodyrecording=[]; //create key and initialize its value in the "data" dictionary
|
---|
| 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 |
|
---|
| 51 | g.data->bodyrecording = cr.data->bodyrecording; //no averaging or any other form of aggregation - here assuming we only evaluate a genotype once; if not, then we ignore (overwrite) recordings from previous evaluations
|
---|
| 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 | {
|
---|
| 66 | var cog = cr.centerOfGravity;
|
---|
| 67 | cog = [cog.x, cog.y, cog.z];
|
---|
| 68 | if (STORE_ALL_PART_COORDS)
|
---|
| 69 | {
|
---|
| 70 | var now = [cog];
|
---|
| 71 | for (var j=0; j<cr.numparts; j++)
|
---|
| 72 | {
|
---|
| 73 | var part = cr.getMechPart(j);
|
---|
| 74 | now.add([part.x, part.y, part.z]);
|
---|
| 75 | }
|
---|
| 76 | cr.data->bodyrecording.add(now);
|
---|
| 77 | } else
|
---|
| 78 | cr.data->bodyrecording.add(cog);
|
---|
| 79 | }
|
---|
| 80 | }
|
---|
| 81 |
|
---|
| 82 | ~
|
---|