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 index numbers in the names 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 index in the names below is the simulation step, the second one 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 unless you prefer to provide its path when loading.
|
---|
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=[]; //in the creature's "data" dictionary, create the key "bodyrecording" and initialize its value to empty vector. Equivalent to cr.data["bodyrecording"]=[]
|
---|
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 given Genotype object once; if not, then we ignore (overwrite) recordings from previous evaluations of this genotype
|
---|
52 |
|
---|
53 | //Simulator.print("Recorded time steps: %d" % g.data->bodyrecording.size); //just for debugging
|
---|
54 | return g;
|
---|
55 | }
|
---|
56 |
|
---|
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
|
---|
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 | ~
|
---|