just a test

Dependencies:   mbed

Fork of scoreLight_Advanced by Alvaro Cassinelli

Committer:
mbedalvaro
Date:
Tue Apr 01 11:34:37 2014 +0000
Revision:
46:90516893793a
Parent:
45:a3b984a79d5d
Child:
47:2312a8dc9658
added show parameters function to calibrate (including integration steps)

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mbedalvaro 31:5f039cbddee8 1 /*
mbedalvaro 31:5f039cbddee8 2 * elasticLoop.cpp
mbedalvaro 31:5f039cbddee8 3 * laserBlobPure
mbedalvaro 31:5f039cbddee8 4 *
mbedalvaro 31:5f039cbddee8 5 * Created by CASSINELLI ALVARO on 5/20/11.
mbedalvaro 31:5f039cbddee8 6 * Copyright 2011 TOKYO UNIVERSITY. All rights reserved.
mbedalvaro 31:5f039cbddee8 7 *
mbedalvaro 31:5f039cbddee8 8 */
mbedalvaro 31:5f039cbddee8 9
mbedalvaro 31:5f039cbddee8 10 #include "elasticLoop.h"
mbedalvaro 31:5f039cbddee8 11
mbedalvaro 31:5f039cbddee8 12 // SHOULD NOT BE HERE: (only because I am using AD_MIRRIOR... max and min in the set region function that should not be here)
mbedalvaro 31:5f039cbddee8 13 #include "hardwareIO.h"
mbedalvaro 31:5f039cbddee8 14
mbedalvaro 31:5f039cbddee8 15 elasticLoop::elasticLoop() {
mbedalvaro 31:5f039cbddee8 16 }
mbedalvaro 31:5f039cbddee8 17
mbedalvaro 31:5f039cbddee8 18 elasticLoop::~elasticLoop() {
mbedalvaro 31:5f039cbddee8 19 // no need to do clear, this is done by default when clearing the vector container?
mbedalvaro 31:5f039cbddee8 20 massesLoop.clear();
mbedalvaro 31:5f039cbddee8 21 loopSpringArray.clear();
mbedalvaro 31:5f039cbddee8 22 hairVector.clear();
mbedalvaro 31:5f039cbddee8 23 lightForce.clear();
mbedalvaro 31:5f039cbddee8 24 centralSpringArray.clear();
mbedalvaro 31:5f039cbddee8 25 displaySensingBuffer.lsdTrajectory.clear();
mbedalvaro 31:5f039cbddee8 26 }
mbedalvaro 31:5f039cbddee8 27
mbedalvaro 46:90516893793a 28 void elasticLoop::showParameters() {
mbedalvaro 46:90516893793a 29 pc.printf("Mirror delay :%d\n", displaySensingBuffer.delayMirrorSamples);
mbedalvaro 46:90516893793a 30 pc.printf("Angle correction force :%d\n", angleCorrectionForceLoop);
mbedalvaro 46:90516893793a 31 pc.printf("Fraction display :%d\n", angleCorrectionForceLoop);
mbedalvaro 46:90516893793a 32 pc.printf("Integration Step Loop :%d\n", integrationStepLoop);
mbedalvaro 46:90516893793a 33 pc.printf("Integration Step Anchor :%d\n", integrationStepAnchor);
mbedalvaro 46:90516893793a 34 }
mbedalvaro 31:5f039cbddee8 35
mbedalvaro 31:5f039cbddee8 36 void elasticLoop::createBlob(int _id, ElasticLoopMode _elasticBlobMode, vector2Df _initPos, vector2Df _initSpeed) {
mbedalvaro 31:5f039cbddee8 37 // (1) set ID:
mbedalvaro 31:5f039cbddee8 38 identifier=_id;
mbedalvaro 31:5f039cbddee8 39
mbedalvaro 31:5f039cbddee8 40 startCenter=_initPos;
mbedalvaro 31:5f039cbddee8 41 startSpeed=_initSpeed;
mbedalvaro 31:5f039cbddee8 42
mbedalvaro 31:5f039cbddee8 43 // (2) Initialize common variables of all blobs (base class):
mbedalvaro 45:a3b984a79d5d 44 // initCommonVariables();
mbedalvaro 31:5f039cbddee8 45
mbedalvaro 31:5f039cbddee8 46 // (3) initialize common variables for the elastic blob types:
mbedalvaro 46:90516893793a 47 integrationStepLoop=0.22;
mbedalvaro 46:90516893793a 48 integrationStepAnchor=0.4;
mbedalvaro 46:90516893793a 49
mbedalvaro 31:5f039cbddee8 50 slidingDirection=true; // (will change when touching wall)
mbedalvaro 31:5f039cbddee8 51 // Sending data:
mbedalvaro 31:5f039cbddee8 52 periodSendingData=15; // in ms
mbedalvaro 31:5f039cbddee8 53 sendingLoopPositions=false;
mbedalvaro 31:5f039cbddee8 54 sendingBlobArea=true;
mbedalvaro 31:5f039cbddee8 55 sendingKineticEnergy=true;
mbedalvaro 32:52273c3291fe 56 sendingBlobMaxMin=true;
mbedalvaro 32:52273c3291fe 57 // send ALWAYS, regardless of the fact the blob is being touched or not, in case of elastic loops:
mbedalvaro 32:52273c3291fe 58 sendingOnlyWhenTouch=false;
mbedalvaro 31:5f039cbddee8 59
mbedalvaro 31:5f039cbddee8 60 // (3) Initialize secondary variables depending on the blob type and mode:
mbedalvaro 31:5f039cbddee8 61
mbedalvaro 31:5f039cbddee8 62 // NOTE (!): the mode does not affect the update method; in fact, all these elastic loops have different behaviours because of different parameters (but the booleans modes could
mbedalvaro 31:5f039cbddee8 63 // actually be "condensed" in a mode...)
mbedalvaro 31:5f039cbddee8 64
mbedalvaro 31:5f039cbddee8 65 switch (_elasticBlobMode) {
mbedalvaro 31:5f039cbddee8 66 case RELAX:
mbedalvaro 31:5f039cbddee8 67
mbedalvaro 31:5f039cbddee8 68 // Name of this kind of spot:
mbedalvaro 31:5f039cbddee8 69 sprintf(spotName,"loop_relax"); //this is an relaxing elastic loop
mbedalvaro 31:5f039cbddee8 70
mbedalvaro 31:5f039cbddee8 71 // Color: (use parameter in the future):
mbedalvaro 31:5f039cbddee8 72 //setColor(0x07);//0x04+0x02>>i);
mbedalvaro 31:5f039cbddee8 73 setColor(0x04);
mbedalvaro 45:a3b984a79d5d 74 blueTouch=true;
mbedalvaro 31:5f039cbddee8 75
mbedalvaro 31:5f039cbddee8 76 // default (initial) shape (the scafold belongs to the base class):
mbedalvaro 31:5f039cbddee8 77 startRadius=400;
mbedalvaro 31:5f039cbddee8 78 bluePrint.buildCircularScafold(startRadius, vector2Dd(0,0), 40); //(float _radius, vector2Dd _pos, int _numScafoldPoints);
mbedalvaro 31:5f039cbddee8 79
mbedalvaro 31:5f039cbddee8 80 // Numeric parameters for the simulated mechanical system:
mbedalvaro 31:5f039cbddee8 81 massLoopParticle=0.25;
mbedalvaro 31:5f039cbddee8 82 dampMotionMassesLoop=0.025;//0.17;
mbedalvaro 31:5f039cbddee8 83 massAnchor=2.0;
mbedalvaro 31:5f039cbddee8 84 dampMotionAnchorMass=0.001;
mbedalvaro 31:5f039cbddee8 85 // Springs:
mbedalvaro 31:5f039cbddee8 86 centralSpringK=0.3;
mbedalvaro 31:5f039cbddee8 87 centralSpringRelax=startRadius;// use the radius of the scafold
mbedalvaro 31:5f039cbddee8 88 interSpringK=0.46;
mbedalvaro 31:5f039cbddee8 89 interSpringRelax=20;
mbedalvaro 31:5f039cbddee8 90 // for "zack-like" blob:
mbedalvaro 31:5f039cbddee8 91 interParticleRange=100;
mbedalvaro 31:5f039cbddee8 92 factorInterParticleForce=18.0;
mbedalvaro 31:5f039cbddee8 93
mbedalvaro 31:5f039cbddee8 94 searchActive=false;
mbedalvaro 31:5f039cbddee8 95 pseudopodesMode=false; // this is for contour following.
mbedalvaro 31:5f039cbddee8 96
mbedalvaro 31:5f039cbddee8 97 // Active/inactive forces:
mbedalvaro 31:5f039cbddee8 98 springForcesOnLoop=true;
mbedalvaro 31:5f039cbddee8 99 lightForcesOnLoop=true;
mbedalvaro 31:5f039cbddee8 100 forceBorderOnLoop=false;
mbedalvaro 31:5f039cbddee8 101 nuclearForceOnLoop=false;//true;
mbedalvaro 31:5f039cbddee8 102 interParticleForceOnLoop=false;
mbedalvaro 31:5f039cbddee8 103 forceInternalPressureOnLoop=false; // (when true, either constant force or calculated area using Green function or approximation by bounding box)
mbedalvaro 31:5f039cbddee8 104
mbedalvaro 31:5f039cbddee8 105 // Recentering vector:
mbedalvaro 31:5f039cbddee8 106 angleCorrectionForceLoop=0;// in deg
mbedalvaro 31:5f039cbddee8 107 recenteringForceOnLoop=false;
mbedalvaro 31:5f039cbddee8 108 angleCorrectionForceNucleus=0;// in deg
mbedalvaro 31:5f039cbddee8 109 recenteringForceOnNucleus=false;//true;
mbedalvaro 31:5f039cbddee8 110
mbedalvaro 31:5f039cbddee8 111 factorLightForce=4.0;//3.0;//8.0;
mbedalvaro 31:5f039cbddee8 112 factorRecenteringAnchorMass=20.0/bluePrint.scafold.size(); // use number of points in the scafold
mbedalvaro 31:5f039cbddee8 113 factorRecenteringLoopMass=0.3;
mbedalvaro 31:5f039cbddee8 114 factorPressureLoopMass=1.0;
mbedalvaro 31:5f039cbddee8 115 factorForceBorder=4.5;
mbedalvaro 31:5f039cbddee8 116
mbedalvaro 31:5f039cbddee8 117 // per-blob mirror delay (if things were well adjusted - in particular mirror waiting times, then this could be 0.
mbedalvaro 31:5f039cbddee8 118 //But in case of unique blobs, it may be interesting to accelerate display AND correct the delay by software):
mbedalvaro 31:5f039cbddee8 119 displaySensingBuffer.setDelayMirrors(2);
mbedalvaro 31:5f039cbddee8 120
mbedalvaro 31:5f039cbddee8 121 break;
mbedalvaro 31:5f039cbddee8 122
mbedalvaro 31:5f039cbddee8 123 case CONTRACT:
mbedalvaro 31:5f039cbddee8 124
mbedalvaro 31:5f039cbddee8 125 sprintf(spotName,"loop_contract"); //this is an relaxing elastic loop
mbedalvaro 31:5f039cbddee8 126
mbedalvaro 31:5f039cbddee8 127 setColor(0x07);//0x04+0x02>>i);
mbedalvaro 45:a3b984a79d5d 128 blueTouch=true;
mbedalvaro 45:a3b984a79d5d 129
mbedalvaro 31:5f039cbddee8 130 // default (initial) shape:
mbedalvaro 31:5f039cbddee8 131 startRadius =400;
mbedalvaro 31:5f039cbddee8 132 bluePrint.buildCircularScafold(startRadius, vector2Dd(0,0), 40); //(float _radius, vector2Dd _pos,vector2D _vel, int _numScafoldPoints);
mbedalvaro 31:5f039cbddee8 133
mbedalvaro 31:5f039cbddee8 134 // Numeric parameters for the simulated mechanical system:
mbedalvaro 31:5f039cbddee8 135 massLoopParticle=0.25;
mbedalvaro 31:5f039cbddee8 136 dampMotionMassesLoop=0.024;//0.17;
mbedalvaro 31:5f039cbddee8 137 massAnchor=2.0;
mbedalvaro 31:5f039cbddee8 138 dampMotionAnchorMass=0.001;
mbedalvaro 31:5f039cbddee8 139 // Springs:
mbedalvaro 31:5f039cbddee8 140 centralSpringK=0.5;
mbedalvaro 31:5f039cbddee8 141 centralSpringRelax=startRadius;
mbedalvaro 31:5f039cbddee8 142 interSpringK=0.4;//46;
mbedalvaro 31:5f039cbddee8 143 interSpringRelax=30;
mbedalvaro 31:5f039cbddee8 144 // for "zack-like" blob:
mbedalvaro 31:5f039cbddee8 145 interParticleRange=100;
mbedalvaro 31:5f039cbddee8 146 factorInterParticleForce=18.0;
mbedalvaro 31:5f039cbddee8 147
mbedalvaro 31:5f039cbddee8 148 searchActive=false;
mbedalvaro 31:5f039cbddee8 149 pseudopodesMode=false; // this is for contour following.
mbedalvaro 31:5f039cbddee8 150
mbedalvaro 31:5f039cbddee8 151 // Active/Inactive Forces:
mbedalvaro 31:5f039cbddee8 152 springForcesOnLoop=true;
mbedalvaro 31:5f039cbddee8 153 lightForcesOnLoop=true;
mbedalvaro 31:5f039cbddee8 154 forceBorderOnLoop=false;
mbedalvaro 31:5f039cbddee8 155 nuclearForceOnLoop=true;//true;
mbedalvaro 31:5f039cbddee8 156 interParticleForceOnLoop=false;
mbedalvaro 31:5f039cbddee8 157 forceInternalPressureOnLoop=false; // (when true, either constant force or calculated area using Green function or approximation by bounding box)
mbedalvaro 31:5f039cbddee8 158 // Recentering vector:
mbedalvaro 31:5f039cbddee8 159 angleCorrectionForceLoop=0;// in deg
mbedalvaro 31:5f039cbddee8 160 recenteringForceOnLoop=false;
mbedalvaro 31:5f039cbddee8 161 angleCorrectionForceNucleus=0;// in deg
mbedalvaro 31:5f039cbddee8 162 recenteringForceOnNucleus=false;//true;
mbedalvaro 31:5f039cbddee8 163
mbedalvaro 31:5f039cbddee8 164 factorLightForce=6.0;//3.0;//8.0;
mbedalvaro 31:5f039cbddee8 165 factorRecenteringAnchorMass=20.0/bluePrint.scafold.size();
mbedalvaro 31:5f039cbddee8 166 factorRecenteringLoopMass=0.3;
mbedalvaro 31:5f039cbddee8 167 factorPressureLoopMass=1.0;
mbedalvaro 31:5f039cbddee8 168 factorForceBorder=4.5;
mbedalvaro 31:5f039cbddee8 169
mbedalvaro 31:5f039cbddee8 170 // per-blob mirror delay (if things were well adjusted - in particular mirror waiting times, then this could be 0.
mbedalvaro 31:5f039cbddee8 171 //But in case of unique blobs, it may be interesting to accelerate display AND correct the delay by software):
mbedalvaro 31:5f039cbddee8 172 displaySensingBuffer.setDelayMirrors(2); // per-blob mirror delay (if things were well adjusted - in particular mirror waiting times, then this could be 0.
mbedalvaro 31:5f039cbddee8 173
mbedalvaro 31:5f039cbddee8 174 break;
mbedalvaro 46:90516893793a 175 case CONTRACT_CENTRAL: // this is the "big mouth"
mbedalvaro 31:5f039cbddee8 176
mbedalvaro 46:90516893793a 177 integrationStepLoop=0.5;
mbedalvaro 46:90516893793a 178 integrationStepAnchor=0.4;
mbedalvaro 46:90516893793a 179
mbedalvaro 31:5f039cbddee8 180 sprintf(spotName,"contract_central");
mbedalvaro 31:5f039cbddee8 181
mbedalvaro 31:5f039cbddee8 182 //setColor(0x07);//0x04+0x02>>i);
mbedalvaro 31:5f039cbddee8 183 setColor(0x04);
mbedalvaro 45:a3b984a79d5d 184 blueTouch=true;
mbedalvaro 31:5f039cbddee8 185
mbedalvaro 31:5f039cbddee8 186 // default (initial) shape:
mbedalvaro 31:5f039cbddee8 187 startRadius=400;
mbedalvaro 31:5f039cbddee8 188 bluePrint.buildCircularScafold(startRadius, vector2Dd(0,0), 45); //(float _radius, vector2Dd _pos,vector2D _vel, int _numScafoldPoints);
mbedalvaro 31:5f039cbddee8 189
mbedalvaro 31:5f039cbddee8 190 // Numeric parameters for the simulated mechanical system:
mbedalvaro 31:5f039cbddee8 191 massLoopParticle=0.3;
mbedalvaro 31:5f039cbddee8 192 dampMotionMassesLoop=0.023;//0.17;
mbedalvaro 31:5f039cbddee8 193 massAnchor=0.5;
mbedalvaro 31:5f039cbddee8 194 dampMotionAnchorMass=0.001;
mbedalvaro 31:5f039cbddee8 195 // Springs:
mbedalvaro 31:5f039cbddee8 196 centralSpringK=0.3;
mbedalvaro 31:5f039cbddee8 197 centralSpringRelax=startRadius;
mbedalvaro 31:5f039cbddee8 198 interSpringK=0.54;//46;
mbedalvaro 31:5f039cbddee8 199 interSpringRelax=30;
mbedalvaro 31:5f039cbddee8 200 // for "zack-like" blob:
mbedalvaro 31:5f039cbddee8 201 interParticleRange=100;
mbedalvaro 31:5f039cbddee8 202 factorInterParticleForce=18.0;
mbedalvaro 31:5f039cbddee8 203
mbedalvaro 31:5f039cbddee8 204 searchActive=false;
mbedalvaro 31:5f039cbddee8 205 pseudopodesMode=false; // this is for contour following.
mbedalvaro 31:5f039cbddee8 206
mbedalvaro 31:5f039cbddee8 207 // Active/Inactive Forces:
mbedalvaro 31:5f039cbddee8 208 springForcesOnLoop= true;
mbedalvaro 31:5f039cbddee8 209 lightForcesOnLoop= true;
mbedalvaro 31:5f039cbddee8 210 forceBorderOnLoop=false;
mbedalvaro 31:5f039cbddee8 211 nuclearForceOnLoop=false;//true;
mbedalvaro 31:5f039cbddee8 212 interParticleForceOnLoop=false;
mbedalvaro 31:5f039cbddee8 213 forceInternalPressureOnLoop=false; // (when true, either constant force or calculated area using Green function or approximation by bounding box)
mbedalvaro 31:5f039cbddee8 214 // Recentering vector:
mbedalvaro 31:5f039cbddee8 215 angleCorrectionForceLoop=0;// in deg
mbedalvaro 31:5f039cbddee8 216 recenteringForceOnLoop=false ; //true; !!!!!!!!!!!!!!!
mbedalvaro 31:5f039cbddee8 217 angleCorrectionForceNucleus=0;// in deg
mbedalvaro 31:5f039cbddee8 218 recenteringForceOnNucleus=false;//true;
mbedalvaro 31:5f039cbddee8 219
mbedalvaro 46:90516893793a 220 factorLightForce=8.3;//4.3;
mbedalvaro 31:5f039cbddee8 221 factorRecenteringAnchorMass= 20.0/bluePrint.scafold.size();
mbedalvaro 31:5f039cbddee8 222 factorRecenteringLoopMass=0.045;
mbedalvaro 31:5f039cbddee8 223 factorPressureLoopMass=1.5;
mbedalvaro 31:5f039cbddee8 224 factorForceBorder=150;
mbedalvaro 31:5f039cbddee8 225
mbedalvaro 31:5f039cbddee8 226 // per-blob mirror delay (if things were well adjusted - in particular mirror waiting times, then this could be 0.
mbedalvaro 31:5f039cbddee8 227 //But in case of unique blobs, it may be interesting to accelerate display AND correct the delay by software):
mbedalvaro 44:46e25fa1669b 228 displaySensingBuffer.setDelayMirrors(1);
mbedalvaro 31:5f039cbddee8 229
mbedalvaro 31:5f039cbddee8 230 break;
mbedalvaro 31:5f039cbddee8 231
mbedalvaro 31:5f039cbddee8 232 case CONTRACT_CENTRAL_FAST:
mbedalvaro 31:5f039cbddee8 233
mbedalvaro 31:5f039cbddee8 234 //setColor(0x07);//0x04+0x02>>i);
mbedalvaro 31:5f039cbddee8 235 setColor(0x04);
mbedalvaro 45:a3b984a79d5d 236 blueTouch=true;
mbedalvaro 31:5f039cbddee8 237
mbedalvaro 31:5f039cbddee8 238 // default (initial) shape:
mbedalvaro 31:5f039cbddee8 239 startRadius=150;
mbedalvaro 31:5f039cbddee8 240 bluePrint.buildCircularScafold(startRadius, vector2Dd(0,0), 40); //(float _radius, vector2Dd _pos,vector2D _vel, int _numScafoldPoints);
mbedalvaro 31:5f039cbddee8 241
mbedalvaro 31:5f039cbddee8 242 // Numeric parameters for the simulated mechanical system:
mbedalvaro 31:5f039cbddee8 243 massLoopParticle=0.06;
mbedalvaro 31:5f039cbddee8 244 dampMotionMassesLoop=0.021;//0.17;
mbedalvaro 31:5f039cbddee8 245 massAnchor=0.5;
mbedalvaro 31:5f039cbddee8 246 dampMotionAnchorMass=0.01;
mbedalvaro 31:5f039cbddee8 247 // Springs:
mbedalvaro 31:5f039cbddee8 248 centralSpringK=0.3;
mbedalvaro 31:5f039cbddee8 249 centralSpringRelax=startRadius;
mbedalvaro 31:5f039cbddee8 250 interSpringK=0.54;//46;
mbedalvaro 31:5f039cbddee8 251 interSpringRelax=40;
mbedalvaro 31:5f039cbddee8 252 // for "zack-like" blob:
mbedalvaro 31:5f039cbddee8 253 interParticleRange=150;
mbedalvaro 31:5f039cbddee8 254 factorInterParticleForce=160.0;
mbedalvaro 31:5f039cbddee8 255
mbedalvaro 31:5f039cbddee8 256 searchActive=false;
mbedalvaro 31:5f039cbddee8 257 pseudopodesMode=false; // this is for contour following.
mbedalvaro 31:5f039cbddee8 258
mbedalvaro 31:5f039cbddee8 259 // Active/Inactive Forces:
mbedalvaro 31:5f039cbddee8 260 springForcesOnLoop= true;
mbedalvaro 31:5f039cbddee8 261 lightForcesOnLoop= true;
mbedalvaro 31:5f039cbddee8 262 forceBorderOnLoop=false;
mbedalvaro 31:5f039cbddee8 263 nuclearForceOnLoop=false;
mbedalvaro 31:5f039cbddee8 264 interParticleForceOnLoop=true; //!!!
mbedalvaro 31:5f039cbddee8 265 forceInternalPressureOnLoop=false; // (when true, either constant force or calculated area using Green function or approximation by bounding box)
mbedalvaro 31:5f039cbddee8 266 // Recentering vector:
mbedalvaro 31:5f039cbddee8 267 angleCorrectionForceLoop=90;// in deg
mbedalvaro 31:5f039cbddee8 268 recenteringForceOnLoop=true;
mbedalvaro 31:5f039cbddee8 269 angleCorrectionForceNucleus=0;// in deg
mbedalvaro 31:5f039cbddee8 270 recenteringForceOnNucleus=false;//true;
mbedalvaro 31:5f039cbddee8 271
mbedalvaro 31:5f039cbddee8 272 factorLightForce=-4;//3.0;//8.0;
mbedalvaro 31:5f039cbddee8 273 factorRecenteringAnchorMass= 20.0/bluePrint.scafold.size();
mbedalvaro 31:5f039cbddee8 274 factorRecenteringLoopMass=0.06;
mbedalvaro 31:5f039cbddee8 275 factorPressureLoopMass=1.5;
mbedalvaro 31:5f039cbddee8 276 factorForceBorder=150;
mbedalvaro 31:5f039cbddee8 277
mbedalvaro 44:46e25fa1669b 278 displaySensingBuffer.setDelayMirrors(1);
mbedalvaro 31:5f039cbddee8 279 break;
mbedalvaro 31:5f039cbddee8 280
mbedalvaro 31:5f039cbddee8 281 case CONTOUR_FOLLOWING:
mbedalvaro 31:5f039cbddee8 282 sprintf(spotName,"following"); //this is a contour-following loop
mbedalvaro 31:5f039cbddee8 283
mbedalvaro 46:90516893793a 284 integrationStepLoop=0.22;
mbedalvaro 46:90516893793a 285 integrationStepAnchor=0.4;
mbedalvaro 46:90516893793a 286
mbedalvaro 31:5f039cbddee8 287 //setColor(0x07);//0x04+0x02>>i);
mbedalvaro 31:5f039cbddee8 288 setColor(0x04);
mbedalvaro 45:a3b984a79d5d 289 blueTouch=true;
mbedalvaro 31:5f039cbddee8 290
mbedalvaro 31:5f039cbddee8 291 // default (initial) shape:
mbedalvaro 31:5f039cbddee8 292 startRadius=100;
mbedalvaro 31:5f039cbddee8 293 bluePrint.buildCircularScafold(startRadius, vector2Dd(0,0), 20); //(float _radius, vector2Dd _pos,vector2D _vel, int _numScafoldPoints);
mbedalvaro 31:5f039cbddee8 294
mbedalvaro 31:5f039cbddee8 295 // Numeric parameters for the simulated mechanical system:
mbedalvaro 31:5f039cbddee8 296 massLoopParticle=0.05;
mbedalvaro 31:5f039cbddee8 297 dampMotionMassesLoop=0.27;//0.17;
mbedalvaro 31:5f039cbddee8 298 massAnchor=3.0;
mbedalvaro 31:5f039cbddee8 299 dampMotionAnchorMass=0.03;
mbedalvaro 31:5f039cbddee8 300 // Springs:
mbedalvaro 44:46e25fa1669b 301 centralSpringK=0.4;
mbedalvaro 31:5f039cbddee8 302 centralSpringRelax=100;//bluePrint.radius;
mbedalvaro 44:46e25fa1669b 303 interSpringK=0.4;
mbedalvaro 31:5f039cbddee8 304 interSpringRelax=0.7*startRadius*2*sin(1.0* PI/ bluePrint.scafold.size()); // if factor=1, this makes for a perfect polygon at relax for all springs...
mbedalvaro 31:5f039cbddee8 305 // for "zack-like" blob:
mbedalvaro 31:5f039cbddee8 306 interParticleRange=70;
mbedalvaro 31:5f039cbddee8 307 factorInterParticleForce=4.0;
mbedalvaro 31:5f039cbddee8 308
mbedalvaro 31:5f039cbddee8 309 searchActive=true;
mbedalvaro 31:5f039cbddee8 310 pseudopodesMode=true; // this is for contour following.
mbedalvaro 31:5f039cbddee8 311
mbedalvaro 31:5f039cbddee8 312 // Active/Inactive Forces:
mbedalvaro 31:5f039cbddee8 313 springForcesOnLoop=true;
mbedalvaro 31:5f039cbddee8 314 lightForcesOnLoop=true;
mbedalvaro 31:5f039cbddee8 315 forceBorderOnLoop=false;
mbedalvaro 31:5f039cbddee8 316 nuclearForceOnLoop=false;//true;
mbedalvaro 31:5f039cbddee8 317 interParticleForceOnLoop=true;
mbedalvaro 31:5f039cbddee8 318 forceInternalPressureOnLoop=false; // (when true, either constant force or calculated area using Green function or approximation by bounding box)
mbedalvaro 31:5f039cbddee8 319 // Recentering vector:
mbedalvaro 44:46e25fa1669b 320 angleCorrectionForceLoop=0;// in deg
mbedalvaro 31:5f039cbddee8 321 recenteringForceOnLoop=true;
mbedalvaro 31:5f039cbddee8 322 angleCorrectionForceNucleus=180;// in deg
mbedalvaro 31:5f039cbddee8 323 recenteringForceOnNucleus=false;//true;
mbedalvaro 31:5f039cbddee8 324
mbedalvaro 40:ee217eff826c 325 factorLightForce=2.4;//3.0;//8.0;
mbedalvaro 31:5f039cbddee8 326 factorRecenteringAnchorMass=1.0;//20.0/scafold.size();
mbedalvaro 44:46e25fa1669b 327 factorRecenteringLoopMass=0.2;
mbedalvaro 31:5f039cbddee8 328 factorPressureLoopMass=1.5;
mbedalvaro 31:5f039cbddee8 329 factorForceBorder=150;
mbedalvaro 31:5f039cbddee8 330 // per-blob mirror delay (if things were well adjusted - in particular mirror waiting times, then this could be 0.
mbedalvaro 31:5f039cbddee8 331 //But in case of unique blobs, it may be interesting to accelerate display AND correct the delay by software):
mbedalvaro 44:46e25fa1669b 332 displaySensingBuffer.setDelayMirrors(2);
mbedalvaro 31:5f039cbddee8 333
mbedalvaro 31:5f039cbddee8 334 break;
mbedalvaro 31:5f039cbddee8 335 case CONTOUR_FOLLOWING_FAST:
mbedalvaro 31:5f039cbddee8 336 sprintf(spotName,"following_fast");
mbedalvaro 31:5f039cbddee8 337
mbedalvaro 31:5f039cbddee8 338 setColor(0x07);//0x04+0x02>>i);
mbedalvaro 45:a3b984a79d5d 339 blueTouch=true;
mbedalvaro 45:a3b984a79d5d 340
mbedalvaro 31:5f039cbddee8 341 // default (initial) shape:
mbedalvaro 31:5f039cbddee8 342 startRadius=100;
mbedalvaro 31:5f039cbddee8 343 bluePrint.buildCircularScafold(startRadius, vector2Dd(0,0), 30); //(float _radius, vector2Dd _pos,vector2D _vel, int _numScafoldPoints);
mbedalvaro 31:5f039cbddee8 344
mbedalvaro 31:5f039cbddee8 345 // Numeric parameters for the simulated mechanical system:
mbedalvaro 31:5f039cbddee8 346 massLoopParticle=0.05;
mbedalvaro 31:5f039cbddee8 347 dampMotionMassesLoop=0.27;//0.17;
mbedalvaro 31:5f039cbddee8 348 massAnchor=3.0;
mbedalvaro 31:5f039cbddee8 349 dampMotionAnchorMass=0.03;
mbedalvaro 31:5f039cbddee8 350 // Springs:
mbedalvaro 31:5f039cbddee8 351 centralSpringK=-200;
mbedalvaro 31:5f039cbddee8 352 centralSpringRelax=100;//bluePrint.radius;
mbedalvaro 31:5f039cbddee8 353 interSpringK=0.5;//46;
mbedalvaro 31:5f039cbddee8 354 interSpringRelax=0.7*startRadius*2*sin(1.0* PI/bluePrint.scafold.size()); // if factor=1, this makes for a perfect polygon at relax for all springs...
mbedalvaro 31:5f039cbddee8 355 // for "zack-like" blob:
mbedalvaro 31:5f039cbddee8 356 interParticleRange=80;
mbedalvaro 31:5f039cbddee8 357 factorInterParticleForce=4.0;
mbedalvaro 31:5f039cbddee8 358
mbedalvaro 31:5f039cbddee8 359 searchActive=false;
mbedalvaro 31:5f039cbddee8 360 pseudopodesMode=true; // this is for contour following.
mbedalvaro 31:5f039cbddee8 361
mbedalvaro 31:5f039cbddee8 362 // Active/Inactive Forces:
mbedalvaro 31:5f039cbddee8 363 springForcesOnLoop=true;
mbedalvaro 31:5f039cbddee8 364 lightForcesOnLoop=true;
mbedalvaro 31:5f039cbddee8 365 forceBorderOnLoop=false;
mbedalvaro 31:5f039cbddee8 366 nuclearForceOnLoop=false;//true;
mbedalvaro 31:5f039cbddee8 367 interParticleForceOnLoop=false;
mbedalvaro 31:5f039cbddee8 368 forceInternalPressureOnLoop=false; // (when true, either constant force or calculated area using Green function or approximation by bounding box)
mbedalvaro 31:5f039cbddee8 369 // Recentering vector:
mbedalvaro 31:5f039cbddee8 370 angleCorrectionForceLoop=243;// in deg
mbedalvaro 31:5f039cbddee8 371 recenteringForceOnLoop=true;
mbedalvaro 31:5f039cbddee8 372 angleCorrectionForceNucleus=180;// in deg
mbedalvaro 31:5f039cbddee8 373 recenteringForceOnNucleus=false;//true;
mbedalvaro 31:5f039cbddee8 374
mbedalvaro 31:5f039cbddee8 375 factorLightForce=2.3;//3.0;//8.0;
mbedalvaro 31:5f039cbddee8 376 factorRecenteringAnchorMass=1.0;//20.0/bluePrint.scafold.size();
mbedalvaro 31:5f039cbddee8 377 factorRecenteringLoopMass=0.09;
mbedalvaro 31:5f039cbddee8 378 factorPressureLoopMass=1.5;
mbedalvaro 31:5f039cbddee8 379 factorForceBorder=150;
mbedalvaro 31:5f039cbddee8 380
mbedalvaro 31:5f039cbddee8 381 // per-blob mirror delay (if things were well adjusted - in particular mirror waiting times, then this could be 0.
mbedalvaro 31:5f039cbddee8 382 //But in case of unique blobs, it may be interesting to accelerate display AND correct the delay by software):
mbedalvaro 31:5f039cbddee8 383 displaySensingBuffer.setDelayMirrors(2);
mbedalvaro 31:5f039cbddee8 384 break;
mbedalvaro 31:5f039cbddee8 385 case BOUNCING:
mbedalvaro 31:5f039cbddee8 386 sprintf(spotName,"bouncing");
mbedalvaro 31:5f039cbddee8 387
mbedalvaro 31:5f039cbddee8 388 setColor(0x07);//0x04+0x02>>i);
mbedalvaro 45:a3b984a79d5d 389 blueTouch=true;
mbedalvaro 45:a3b984a79d5d 390
mbedalvaro 31:5f039cbddee8 391 // default (initial) shape:
mbedalvaro 31:5f039cbddee8 392 startRadius=70;
mbedalvaro 31:5f039cbddee8 393 bluePrint.buildCircularScafold(startRadius, vector2Dd(0,0), 20); //(float _radius, vector2Dd _pos,vector2D _vel, int _numScafoldPoints);
mbedalvaro 31:5f039cbddee8 394
mbedalvaro 31:5f039cbddee8 395 // Numeric parameters for the simulated mechanical system:
mbedalvaro 31:5f039cbddee8 396 massLoopParticle=5.0;
mbedalvaro 31:5f039cbddee8 397 dampMotionMassesLoop=0.001;//0.17;
mbedalvaro 31:5f039cbddee8 398 massAnchor=1.0;
mbedalvaro 31:5f039cbddee8 399 dampMotionAnchorMass=0.002;
mbedalvaro 31:5f039cbddee8 400 // Springs:
mbedalvaro 31:5f039cbddee8 401 centralSpringK=1.0;
mbedalvaro 31:5f039cbddee8 402 centralSpringRelax=70;//bluePrint.radius;
mbedalvaro 31:5f039cbddee8 403 interSpringK=0.4;//46;
mbedalvaro 31:5f039cbddee8 404 interSpringRelax==1.0*startRadius*2*sin(1.0* PI/bluePrint.scafold.size()); // if factor=1, this makes for a perfect polygon at relax for all springs...
mbedalvaro 31:5f039cbddee8 405 // for "zack-like" blob:
mbedalvaro 31:5f039cbddee8 406 interParticleRange=100;
mbedalvaro 31:5f039cbddee8 407 factorInterParticleForce=3.0;
mbedalvaro 31:5f039cbddee8 408
mbedalvaro 31:5f039cbddee8 409 searchActive=false;
mbedalvaro 31:5f039cbddee8 410 pseudopodesMode=false; // this is for contour following.
mbedalvaro 31:5f039cbddee8 411
mbedalvaro 31:5f039cbddee8 412 // Active/Inactive Forces:
mbedalvaro 31:5f039cbddee8 413 springForcesOnLoop=true;
mbedalvaro 31:5f039cbddee8 414 lightForcesOnLoop=true;
mbedalvaro 31:5f039cbddee8 415 forceBorderOnLoop=true;
mbedalvaro 31:5f039cbddee8 416 nuclearForceOnLoop=true;//true;
mbedalvaro 31:5f039cbddee8 417 interParticleForceOnLoop=false;
mbedalvaro 31:5f039cbddee8 418 forceInternalPressureOnLoop=false; // (when true, either constant force or calculated area using Green function or approximation by bounding box)
mbedalvaro 31:5f039cbddee8 419 // Recentering vector:
mbedalvaro 31:5f039cbddee8 420 angleCorrectionForceLoop=0;// in deg
mbedalvaro 31:5f039cbddee8 421 recenteringForceOnLoop=false;
mbedalvaro 31:5f039cbddee8 422 angleCorrectionForceNucleus=0;// in deg
mbedalvaro 31:5f039cbddee8 423 recenteringForceOnNucleus=false;//true;
mbedalvaro 31:5f039cbddee8 424
mbedalvaro 31:5f039cbddee8 425 factorLightForce=0.6;//3.0;//8.0;
mbedalvaro 31:5f039cbddee8 426 factorRecenteringAnchorMass=100.0/bluePrint.scafold.size();
mbedalvaro 31:5f039cbddee8 427 factorRecenteringLoopMass=5.0;
mbedalvaro 31:5f039cbddee8 428 factorPressureLoopMass=2.0;
mbedalvaro 31:5f039cbddee8 429 factorForceBorder=4.5;
mbedalvaro 31:5f039cbddee8 430
mbedalvaro 31:5f039cbddee8 431 // per-blob mirror delay (if things were well adjusted - in particular mirror waiting times, then this could be 0.
mbedalvaro 31:5f039cbddee8 432 //But in case of unique blobs, it may be interesting to accelerate display AND correct the delay by software):
mbedalvaro 31:5f039cbddee8 433 displaySensingBuffer.setDelayMirrors(2);
mbedalvaro 31:5f039cbddee8 434 break;
mbedalvaro 31:5f039cbddee8 435 }
mbedalvaro 31:5f039cbddee8 436
mbedalvaro 31:5f039cbddee8 437 // Finally, we can create the loop using these parameters, and the positions given in the scafold:
mbedalvaro 31:5f039cbddee8 438 createLoopFromScafold(); // this sets the number of masses
mbedalvaro 31:5f039cbddee8 439
mbedalvaro 31:5f039cbddee8 440 // Excursion limits (ATTN!!! this will set the limits for all the masses, so we need FIRT to call to createLoopFromScafold - NO NEEDED ANYMORE: now calling to static member method of pointMass...)
mbedalvaro 31:5f039cbddee8 441 setRegionMotion(MIN_AD_MIRRORS, MIN_AD_MIRRORS, MAX_AD_MIRRORS, MAX_AD_MIRRORS);
mbedalvaro 31:5f039cbddee8 442
mbedalvaro 31:5f039cbddee8 443 // draw it once on the display buffer for good initialization:
mbedalvaro 31:5f039cbddee8 444 draw();
mbedalvaro 31:5f039cbddee8 445 }
mbedalvaro 31:5f039cbddee8 446
mbedalvaro 31:5f039cbddee8 447 void elasticLoop::speedFactor(float speedfactor) {
mbedalvaro 31:5f039cbddee8 448 // This method is more appropiate for rigid loop, but we can "simulate" speed up in case of elastic loop by changing some parameters, even if the loop is not
mbedalvaro 31:5f039cbddee8 449 // set in "contour following" mode.
mbedalvaro 31:5f039cbddee8 450 factorRecenteringLoopMass*=speedfactor;
mbedalvaro 31:5f039cbddee8 451 }
mbedalvaro 31:5f039cbddee8 452
mbedalvaro 31:5f039cbddee8 453 void elasticLoop::initSizeBlob(int _numMasses) {
mbedalvaro 31:5f039cbddee8 454 // Iinitialize blob size (number of points for the loop, as well as other structures such as lsdTrajectory)
mbedalvaro 31:5f039cbddee8 455 numMasses=_numMasses;
mbedalvaro 31:5f039cbddee8 456 // Since this is an elastic loop object, let's create an elastic loop of masses:
mbedalvaro 31:5f039cbddee8 457 massesLoop.resize(numMasses);
mbedalvaro 31:5f039cbddee8 458 loopSpringArray.resize(numMasses); // springs connecting consecutive masses
mbedalvaro 31:5f039cbddee8 459 // NOTE: to save memory, we can drop hairVector (use lightForce instead)
mbedalvaro 31:5f039cbddee8 460 hairVector.resize(numMasses); // the perpendiculars to the loop
mbedalvaro 31:5f039cbddee8 461 lightForce.resize(numMasses); // light force in each particle
mbedalvaro 31:5f039cbddee8 462 //vector2D totalLightForce; // this belongs to the base class now
mbedalvaro 31:5f039cbddee8 463 centralSpringArray.resize(numMasses); // springs connecting each mass to the anchorMass.
mbedalvaro 31:5f039cbddee8 464
mbedalvaro 31:5f039cbddee8 465 // Sensing and Display trajectory:
mbedalvaro 31:5f039cbddee8 466 displaySensingBuffer.lsdTrajectory.resize(numMasses); // the lsdTrajectory and the elastic loop will have the same number of points (this could be different - decimation?).
mbedalvaro 31:5f039cbddee8 467 }
mbedalvaro 31:5f039cbddee8 468
mbedalvaro 31:5f039cbddee8 469 // We will build the masses from the scafold shape (and maybe render it once on the lsdTrajectory to initialize this array?)
mbedalvaro 31:5f039cbddee8 470 void elasticLoop::createLoopFromScafold(void) {
mbedalvaro 31:5f039cbddee8 471 initSizeBlob(bluePrint.scafold.size()); // important: we will have here the same number of points in the scafold and the elastic loop (massLoop)
mbedalvaro 31:5f039cbddee8 472
mbedalvaro 31:5f039cbddee8 473 // Initial conditions for the loop masses:
mbedalvaro 31:5f039cbddee8 474 for (int i = 0; i < numMasses; i++) {
mbedalvaro 46:90516893793a 475 massesLoop[i].setIntegrationStep(integrationStepLoop);//22);//19); // VERY IMPORTANT! in the case of verlet integration, we need to set dt BEFORE setting the initial speed.
mbedalvaro 31:5f039cbddee8 476 massesLoop[i].setInitialCondition(startCenter.x+bluePrint.scafold[i].x,startCenter.y+bluePrint.scafold[i].y, startSpeed.x, startSpeed.y);
mbedalvaro 31:5f039cbddee8 477 massesLoop[i].mass=massLoopParticle;
mbedalvaro 31:5f039cbddee8 478 massesLoop[i].dampMotion=dampMotionMassesLoop;
mbedalvaro 31:5f039cbddee8 479 }
mbedalvaro 31:5f039cbddee8 480
mbedalvaro 31:5f039cbddee8 481 // Springs for the loop:
mbedalvaro 31:5f039cbddee8 482 for (int i = 0; i<numMasses; i++) {
mbedalvaro 31:5f039cbddee8 483 loopSpringArray[i].distance =interSpringRelax;
mbedalvaro 31:5f039cbddee8 484 // if we want an perfect polygon: =startRadius*2*sin(1.0* PI/ numMasses);
mbedalvaro 31:5f039cbddee8 485 // loopSpringArray[i].distance = startRadius*2*sin(1.0* PI/ numMasses);
mbedalvaro 31:5f039cbddee8 486 loopSpringArray[i].springiness = interSpringK;//*(i%5==0? .6 : 1);//0.4;//4f;
mbedalvaro 31:5f039cbddee8 487 loopSpringArray[i].massA = & (massesLoop[i ]);
mbedalvaro 31:5f039cbddee8 488 loopSpringArray[i].massB = & (massesLoop[(i+1) % numMasses]);
mbedalvaro 31:5f039cbddee8 489 }
mbedalvaro 31:5f039cbddee8 490
mbedalvaro 31:5f039cbddee8 491 // Central (anchor mass):
mbedalvaro 31:5f039cbddee8 492 anchorMass.setIntegrationStep(0.3); // VERY IMPORTANT! in the case of verlet integration, we need to set dt BEFORE setting the initial speed.
mbedalvaro 31:5f039cbddee8 493 anchorMass.setInitialCondition(startCenter, startSpeed);
mbedalvaro 31:5f039cbddee8 494 anchorMass.mass=massAnchor;
mbedalvaro 31:5f039cbddee8 495 anchorMass.dampMotion = dampMotionAnchorMass;
mbedalvaro 31:5f039cbddee8 496
mbedalvaro 31:5f039cbddee8 497
mbedalvaro 31:5f039cbddee8 498 // Initial conditions for central springs:
mbedalvaro 31:5f039cbddee8 499 for (int i = 0; i<numMasses; i++) {
mbedalvaro 31:5f039cbddee8 500 centralSpringArray[i].distance =centralSpringRelax;// + 60* cos ( (1.0*i / numMasses) * 7* 2 * PI);
mbedalvaro 31:5f039cbddee8 501 centralSpringArray[i].springiness =centralSpringK;// 0.4f;
mbedalvaro 31:5f039cbddee8 502 centralSpringArray[i].massA = & (anchorMass);
mbedalvaro 31:5f039cbddee8 503 centralSpringArray[i].massB = & (massesLoop[i]);
mbedalvaro 31:5f039cbddee8 504 }
mbedalvaro 31:5f039cbddee8 505 }
mbedalvaro 31:5f039cbddee8 506
mbedalvaro 31:5f039cbddee8 507
mbedalvaro 31:5f039cbddee8 508 void elasticLoop::setRegionMotion(float mmix, float mmiy, float mmax, float mmay) { // Attention: the initial position should be INSIDE this...
mbedalvaro 31:5f039cbddee8 509 /*
mbedalvaro 31:5f039cbddee8 510 for (int i = 0; i<numMasses; i++) {
mbedalvaro 31:5f039cbddee8 511 massesLoop[i].setWallLimits(mmix, mmiy, mmax, mmay);
mbedalvaro 31:5f039cbddee8 512 }
mbedalvaro 31:5f039cbddee8 513 anchorMass.setWallLimits(mmix+10, mmiy+10, mmax-10, mmay-10);
mbedalvaro 31:5f039cbddee8 514 */
mbedalvaro 31:5f039cbddee8 515
mbedalvaro 31:5f039cbddee8 516 // Use the static method of the class pointMass:
mbedalvaro 31:5f039cbddee8 517 // pointMass::setWallLimits(mmix+10, mmiy+10, mmax-10, mmay-10);
mbedalvaro 31:5f039cbddee8 518 pointMass::setWallLimits(mmix+10, mmiy+10, mmax-10, mmay-10);
mbedalvaro 31:5f039cbddee8 519 }
mbedalvaro 31:5f039cbddee8 520
mbedalvaro 31:5f039cbddee8 521 void elasticLoop::update(vector2Df referencePos) {
mbedalvaro 31:5f039cbddee8 522
mbedalvaro 31:5f039cbddee8 523 // (I) Process loop geometry (compute "hair vectors", area and first order moment):
mbedalvaro 31:5f039cbddee8 524 processLoopData();
mbedalvaro 31:5f039cbddee8 525
mbedalvaro 31:5f039cbddee8 526 // (II) Process sensing buffer and compute light forces
mbedalvaro 44:46e25fa1669b 527 // displaySensingBuffer.processSensedData();
mbedalvaro 31:5f039cbddee8 528
mbedalvaro 31:5f039cbddee8 529 // (III) Reset all forces:
mbedalvaro 31:5f039cbddee8 530 for (int i = 0; i < numMasses; i++) {
mbedalvaro 31:5f039cbddee8 531 massesLoop[i].resetForce();
mbedalvaro 31:5f039cbddee8 532 }
mbedalvaro 31:5f039cbddee8 533 anchorMass.resetForce();
mbedalvaro 31:5f039cbddee8 534
mbedalvaro 31:5f039cbddee8 535 // (IV) COMPUTE FORCES (motion is not update yet):
mbedalvaro 31:5f039cbddee8 536 //== (1) Compute each particle light force as well as total light force (this will be stored separatedly from the final total particle force to send to OSC):
mbedalvaro 31:5f039cbddee8 537 totalLightForce.set(0,0);
mbedalvaro 31:5f039cbddee8 538 for (int i = 0; i < numMasses; i++) {
mbedalvaro 31:5f039cbddee8 539 // NOTE: to save memory, we can drop hairVector...
mbedalvaro 31:5f039cbddee8 540 lightForce[i]=hairVector[i]*factorLightForce*displaySensingBuffer.lsdTrajectory[i].lightZone;
mbedalvaro 44:46e25fa1669b 541 lightForce[i].rotateDeg(angleCorrectionForceLoop); // correction by hand (interactive)
mbedalvaro 31:5f039cbddee8 542 // lightForce[i]=lightForce[i]*factorLightForce*displaySensingBuffer.lsdTrajectory[i].lightZone;
mbedalvaro 31:5f039cbddee8 543 //compute total light force, not only on lighted zones, because it will mean AWAY from black zones:
mbedalvaro 31:5f039cbddee8 544 totalLightForce+=lightForce[i]; // note: bad value choice (negative means TOUCH, and equal to -1), TO CHANGE this in future implementations
mbedalvaro 31:5f039cbddee8 545 }
mbedalvaro 44:46e25fa1669b 546 recenteringVectorLoop=totalLightForce;//.getRotated(angleCorrectionForceLoop);
mbedalvaro 44:46e25fa1669b 547 //== (2) Compute the "recentering vector" from the total light force:
mbedalvaro 31:5f039cbddee8 548 // Compute redundant quantities:
mbedalvaro 31:5f039cbddee8 549 normRecenteringVector=recenteringVectorLoop.length();
mbedalvaro 31:5f039cbddee8 550 angleRecenteringVector=recenteringVectorLoop.angleDegHoriz();
mbedalvaro 31:5f039cbddee8 551 recenteringVectorNucleus=totalLightForce.getRotatedDeg(angleCorrectionForceNucleus);
mbedalvaro 31:5f039cbddee8 552 //== (3) Compute forces on the loop:
mbedalvaro 31:5f039cbddee8 553 //----(a) Nearest neighbour inter-particle springs on the loop (always? we can have still another mode, following the center mass only, etc...)
mbedalvaro 31:5f039cbddee8 554 if (springForcesOnLoop) {
mbedalvaro 31:5f039cbddee8 555 for (int i = 0; i < numMasses; i++) { // if putting -1, the loop is broken
mbedalvaro 31:5f039cbddee8 556 loopSpringArray[i].update();// this add forces to the particles
mbedalvaro 31:5f039cbddee8 557 }
mbedalvaro 31:5f039cbddee8 558 }
mbedalvaro 31:5f039cbddee8 559 //----(b) Direct forces from light pressure (COULD BE MERGED WITH FORCE RECENTERING!!)
mbedalvaro 31:5f039cbddee8 560 if (pseudopodesMode) {
mbedalvaro 44:46e25fa1669b 561 // special "patches" on blob membrane, to "ATTACH" like a zip to the black drawing:
mbedalvaro 31:5f039cbddee8 562 if (lightForcesOnLoop) {
mbedalvaro 31:5f039cbddee8 563 int sign=1;
mbedalvaro 31:5f039cbddee8 564 for (int i = 0; i < numMasses; i++) {
mbedalvaro 31:5f039cbddee8 565 if ((i%2)==0) sign*=-1;
mbedalvaro 44:46e25fa1669b 566 //sign=5*cos(6*2*PI*1.0*i/(numMasses-1))-2;
mbedalvaro 31:5f039cbddee8 567 if (displaySensingBuffer.lsdTrajectory[i].lightZone>0) // this means touching something black: make SOME points attracted by it (pseudopodes!!) - but not all!
mbedalvaro 44:46e25fa1669b 568 massesLoop[i].addForce(lightForce[i]*(sign<0? -1.24 : 1.4)); // sign<0 means this is a pseudopode attracted by dark zones
mbedalvaro 31:5f039cbddee8 569 else // this means something white: do nothing, all forces are towards the exterior
mbedalvaro 46:90516893793a 570 massesLoop[i].addForce(lightForce[i]*2.3); // this force tends to make the blob "inflate", but is not "directional"
mbedalvaro 31:5f039cbddee8 571 }
mbedalvaro 31:5f039cbddee8 572 }
mbedalvaro 44:46e25fa1669b 573 //----(c) Forces from the recentering vector on each particle (WITH PATCHES on the loop?): THIS IS RESPONSIBLE FOR THE "FOLLOWING" BEHAVIOUR
mbedalvaro 31:5f039cbddee8 574 if (recenteringForceOnLoop) {
mbedalvaro 31:5f039cbddee8 575
mbedalvaro 44:46e25fa1669b 576 vector2Df auxForce= (slidingDirection? recenteringVectorLoop.getRotatedDeg(-145) : recenteringVectorLoop.getRotatedDeg(145))*factorRecenteringLoopMass*1;
mbedalvaro 40:ee217eff826c 577 //vector2Df auxForce2= (slidingDirection? totalLightForce.getRotatedDeg(-90) : totalLightForce.getRotatedDeg(90))*factorRecenteringLoopMass*1.5;
mbedalvaro 40:ee217eff826c 578 //vector2Df auxForce3= (slidingDirection? totalLightForce.getRotatedDeg(-90) : totalLightForce.getRotatedDeg(90))*factorRecenteringLoopMass*1.5;
mbedalvaro 44:46e25fa1669b 579 vector2Df auxForce2= (slidingDirection? recenteringVectorLoop.getRotatedDeg(-50) : recenteringVectorLoop.getRotatedDeg(50))*factorRecenteringLoopMass*0.5;//*1.8;
mbedalvaro 44:46e25fa1669b 580 vector2Df auxForce3= (slidingDirection? recenteringVectorLoop.getRotatedDeg(-30) : recenteringVectorLoop.getRotatedDeg(30))*factorRecenteringLoopMass*0.6;//1.2;
mbedalvaro 44:46e25fa1669b 581
mbedalvaro 40:ee217eff826c 582
mbedalvaro 31:5f039cbddee8 583 int sign=1;
mbedalvaro 31:5f039cbddee8 584 for (int i = 0; i < numMasses; i++) {
mbedalvaro 31:5f039cbddee8 585 if ((i%2)==0) sign*=-1;
mbedalvaro 31:5f039cbddee8 586 if (displaySensingBuffer.lsdTrajectory[i].lightZone>0) {// this means touching something black: behaviour may depend on the pseudopode presence:
mbedalvaro 44:46e25fa1669b 587 massesLoop[i].addForce((sign<0? auxForce2 : auxForce3)); // auxForce3: nothing, or sign, or corrected angle
mbedalvaro 44:46e25fa1669b 588 }
mbedalvaro 44:46e25fa1669b 589 else massesLoop[i].addForce(auxForce); // this force is responsible for the behaviour (contour following or not)
mbedalvaro 31:5f039cbddee8 590 }
mbedalvaro 31:5f039cbddee8 591 }
mbedalvaro 31:5f039cbddee8 592 } else { // no special zones in the "cell membrane":
mbedalvaro 31:5f039cbddee8 593 if (lightForcesOnLoop) {
mbedalvaro 31:5f039cbddee8 594 for (int i = 0; i < numMasses; i++) {
mbedalvaro 31:5f039cbddee8 595 massesLoop[i].addForce(lightForce[i]);
mbedalvaro 31:5f039cbddee8 596 }
mbedalvaro 31:5f039cbddee8 597 }
mbedalvaro 31:5f039cbddee8 598 //----(c') Forces from the recentering vector on each particle:
mbedalvaro 31:5f039cbddee8 599 if (recenteringForceOnLoop) {
mbedalvaro 44:46e25fa1669b 600 vector2Df auxForce= (slidingDirection? recenteringVectorLoop.getRotatedDeg(-90) : recenteringVectorLoop.getRotatedDeg(90))*factorRecenteringLoopMass;
mbedalvaro 31:5f039cbddee8 601 for (int i = 0; i < numMasses; i++) massesLoop[i].addForce(auxForce);
mbedalvaro 31:5f039cbddee8 602 }
mbedalvaro 31:5f039cbddee8 603 }
mbedalvaro 31:5f039cbddee8 604
mbedalvaro 31:5f039cbddee8 605 //----(d) Forces from the anchorMass (depending on how we set the equilibrium position for each central spring, we can have a nice blob shape at equilibrium... like a gear for instance)
mbedalvaro 31:5f039cbddee8 606 if (nuclearForceOnLoop) {
mbedalvaro 31:5f039cbddee8 607 // Springs:
mbedalvaro 31:5f039cbddee8 608 for (int i = 0; i < numMasses; i++) centralSpringArray[i].update();//assymetricUpdate();
mbedalvaro 31:5f039cbddee8 609 // note: if using centralSpringArray[i].update(), we will add forces to the particles AND to the anchor mass...
mbedalvaro 31:5f039cbddee8 610 // Inverse square (attractive):
mbedalvaro 31:5f039cbddee8 611 //for (int i = 0; i < numMasses; i++) massesLoop[i].addInterInvSquareForce(anchorMass, 10, 300, centralSpringK);
mbedalvaro 31:5f039cbddee8 612 }
mbedalvaro 31:5f039cbddee8 613 //----(d) Inter loop-particles forces (Zach-Liebermann-like blob):
mbedalvaro 31:5f039cbddee8 614 if (interParticleForceOnLoop) {
mbedalvaro 31:5f039cbddee8 615 for (int i = 0; i < numMasses; i++) {
mbedalvaro 31:5f039cbddee8 616 for (int j = 0; j < i-1; j++) massesLoop[i].addInterSpringForce(massesLoop[j], interParticleRange, factorInterParticleForce);
mbedalvaro 31:5f039cbddee8 617 }
mbedalvaro 31:5f039cbddee8 618 }
mbedalvaro 31:5f039cbddee8 619 //----(e) Internal blob pressure force (my faster method to have a blob-like behaviour):
mbedalvaro 31:5f039cbddee8 620 if (forceInternalPressureOnLoop) {
mbedalvaro 31:5f039cbddee8 621 // NOTE on the Physics of the thing: the force on the membrane of a ballon is proportional to the DIFFERENCE of pressures (outside and inside):
mbedalvaro 31:5f039cbddee8 622 // so: f= factor/area - cte, with cte=factor/area0, with area0 being the area at equilibrium.
mbedalvaro 31:5f039cbddee8 623 // (And of course, to make it even more exact, we should do pressure*surface, but this will be considered constant)
mbedalvaro 31:5f039cbddee8 624 // float area0=30000; // area in pixels when at equilibrium
mbedalvaro 31:5f039cbddee8 625 //float factorPressureLoopMass=-0.1*(1.0/area-1.0/area0);
mbedalvaro 31:5f039cbddee8 626 //float factorPressureLoopMass=500000.0*(1.0/(area*area)-1.0/(area0*area0));
mbedalvaro 31:5f039cbddee8 627 //float factorPressureLoopMass=20000.0*(1.0/sqrt(area)-1.0/sqrt(area0));
mbedalvaro 31:5f039cbddee8 628 // Constant force seems to work well too... but produces an annoying blob reversal (probably solved by using negative light forces instead of internal blob pressure):
mbedalvaro 31:5f039cbddee8 629 //float factorPressureLoopMass=2.5;//4.8;
mbedalvaro 31:5f039cbddee8 630 // Now, add the pressure force proportional to the inverse of the area to all particles, or just a signed constant:
mbedalvaro 31:5f039cbddee8 631 int auxsign=(area>=0? -1: 1);
mbedalvaro 31:5f039cbddee8 632 auxsign=-1;
mbedalvaro 31:5f039cbddee8 633 for (int i = 0; i < numMasses; i++) massesLoop[i].addForce( hairVector[i] * factorPressureLoopMass* auxsign);
mbedalvaro 31:5f039cbddee8 634 }
mbedalvaro 31:5f039cbddee8 635 //----(f) force from border:
mbedalvaro 31:5f039cbddee8 636 if (forceBorderOnLoop) {
mbedalvaro 31:5f039cbddee8 637 for (int i = 0; i < numMasses; i++) {
mbedalvaro 31:5f039cbddee8 638 if (massesLoop[i].bWallCollision) massesLoop[i].addForce(massesLoop[i].innerCollitionDirection*factorForceBorder);
mbedalvaro 31:5f039cbddee8 639 }
mbedalvaro 31:5f039cbddee8 640 }
mbedalvaro 31:5f039cbddee8 641
mbedalvaro 31:5f039cbddee8 642 //== (4) Compute forces on the anchor mass:
mbedalvaro 31:5f039cbddee8 643 //----(a) Force from data send by OSC? (ex: from mouse?)
mbedalvaro 31:5f039cbddee8 644 // anchorMass.addSpringForce(mx, my, 500, -10.2f);
mbedalvaro 31:5f039cbddee8 645 // or direct control:
mbedalvaro 31:5f039cbddee8 646 // anchorMass.pos.x=mx;anchorMass.pos.y=my;
mbedalvaro 31:5f039cbddee8 647 //----(b) Force from the total light force (aka, the "recentering vector"!):
mbedalvaro 31:5f039cbddee8 648 if (recenteringForceOnNucleus) {
mbedalvaro 31:5f039cbddee8 649 anchorMass.addForce(recenteringVectorNucleus*factorRecenteringAnchorMass);
mbedalvaro 31:5f039cbddee8 650 }
mbedalvaro 31:5f039cbddee8 651
mbedalvaro 31:5f039cbddee8 652 // when nothing is touching it for a while:
mbedalvaro 31:5f039cbddee8 653 if (searchActive) {
mbedalvaro 31:5f039cbddee8 654 if (!displaySensingBuffer.lightTouched) {
mbedalvaro 31:5f039cbddee8 655 if (firstTimeNoTouch) {
mbedalvaro 31:5f039cbddee8 656 firstTimeNoTouch=false;
mbedalvaro 31:5f039cbddee8 657 computeBoundingBox();
mbedalvaro 31:5f039cbddee8 658 randomForce.set(2000-cx,2000-cy);
mbedalvaro 31:5f039cbddee8 659 randomForce.normalize();
mbedalvaro 31:5f039cbddee8 660 randomForce= randomForce.getRotatedDeg(rand()%50-25);
mbedalvaro 31:5f039cbddee8 661 }
mbedalvaro 31:5f039cbddee8 662 if (noTouchedCounter>0) {
mbedalvaro 31:5f039cbddee8 663 // add random force, modulated:
mbedalvaro 31:5f039cbddee8 664 float aux=1.0*noTouchedCounter/1150;
mbedalvaro 31:5f039cbddee8 665 vector2Df randf=randomForce.getRotatedDeg(40.0*sin(aux*2*PI*2))*20.0;//*(1.0-aux)*0.3;
mbedalvaro 44:46e25fa1669b 666 for (int i = 0; i < 1; i=i+1) { // only on some of the particles (or only one...), and better if these are in the "black attractive" patch!
mbedalvaro 31:5f039cbddee8 667 massesLoop[i].addForce(randf);
mbedalvaro 31:5f039cbddee8 668 }
mbedalvaro 31:5f039cbddee8 669 // and a special point?
mbedalvaro 31:5f039cbddee8 670 //massesLoop[numMasses/2].addForce(randf);
mbedalvaro 31:5f039cbddee8 671 // plus amoeba effect ?
mbedalvaro 31:5f039cbddee8 672 // for (int i = 0; i < numMasses; i++) {
mbedalvaro 31:5f039cbddee8 673 // massesLoop[i].addForce(hairVector[i]*18*cos( (0.0*noTouchedCounter/1000 + 1.0*i/(numMasses-1)*2*PI*3)));
mbedalvaro 31:5f039cbddee8 674 //}
mbedalvaro 31:5f039cbddee8 675
mbedalvaro 31:5f039cbddee8 676 if ((noTouchedCounter>1150)||(blobWallCollision)) {
mbedalvaro 31:5f039cbddee8 677 noTouchedCounter=0;
mbedalvaro 31:5f039cbddee8 678 // compute force towards the center, slightly rotated to make the blob wander about:
mbedalvaro 31:5f039cbddee8 679 computeBoundingBox();
mbedalvaro 31:5f039cbddee8 680 randomForce.set(2000-cx,2000-cy);
mbedalvaro 31:5f039cbddee8 681 randomForce.normalize();
mbedalvaro 31:5f039cbddee8 682 randomForce= randomForce.getRotatedDeg(rand()%50-25);
mbedalvaro 31:5f039cbddee8 683 }
mbedalvaro 31:5f039cbddee8 684 }
mbedalvaro 31:5f039cbddee8 685 } else {
mbedalvaro 31:5f039cbddee8 686 firstTimeNoTouch=true;
mbedalvaro 31:5f039cbddee8 687 noTouchedCounter=0;
mbedalvaro 31:5f039cbddee8 688 }
mbedalvaro 31:5f039cbddee8 689 noTouchedCounter++;
mbedalvaro 31:5f039cbddee8 690 }
mbedalvaro 31:5f039cbddee8 691
mbedalvaro 31:5f039cbddee8 692 // (V) UPDATE DYNAMICS
mbedalvaro 31:5f039cbddee8 693 //== (1) particules on the loop:
mbedalvaro 31:5f039cbddee8 694 for (int i = 0; i < numMasses; i++) {
mbedalvaro 31:5f039cbddee8 695 #ifndef VERLET_METHOD
mbedalvaro 31:5f039cbddee8 696 massesLoop[i].addDampingForce(); // only in case of EULER method (damping in VERLET mode is done automatically when updating)
mbedalvaro 31:5f039cbddee8 697 #endif
mbedalvaro 31:5f039cbddee8 698 massesLoop[i].update(); // unconstrained
mbedalvaro 31:5f039cbddee8 699 massesLoop[i].bounceOffWalls(); // constrain position (and compute wall "hit")
mbedalvaro 31:5f039cbddee8 700 }
mbedalvaro 31:5f039cbddee8 701 //== (2) For the anchorMass:
mbedalvaro 31:5f039cbddee8 702 #ifndef VERLET_METHOD
mbedalvaro 31:5f039cbddee8 703 anchorMass.addDampingForce(); // // only in case of EULER method (damping in VERLET mode is done automatically when updating)
mbedalvaro 31:5f039cbddee8 704 #endif
mbedalvaro 31:5f039cbddee8 705 anchorMass.update(); // unconstrained
mbedalvaro 31:5f039cbddee8 706 anchorMass.bounceOffWalls(); // constrain position (and compute wall "hit")
mbedalvaro 31:5f039cbddee8 707
mbedalvaro 31:5f039cbddee8 708 // OTHER PARTICULAR THINGS:
mbedalvaro 31:5f039cbddee8 709 // (1) current color: change with touch? NO
mbedalvaro 31:5f039cbddee8 710 // if (displaySensingBuffer.lightTouched)
mbedalvaro 31:5f039cbddee8 711 // transientBlobColor=blobColor|0x02; // set green ON on the trajectory, regardless of the initial color
mbedalvaro 31:5f039cbddee8 712 // else
mbedalvaro 31:5f039cbddee8 713 transientBlobColor=blobColor; // just the original blob color
mbedalvaro 31:5f039cbddee8 714
mbedalvaro 31:5f039cbddee8 715 // change sliding direction (for countour following):
mbedalvaro 31:5f039cbddee8 716 if (blobWallCollision) {
mbedalvaro 31:5f039cbddee8 717 if (wallCounter>10) {
mbedalvaro 31:5f039cbddee8 718 slidingDirection=!slidingDirection;
mbedalvaro 31:5f039cbddee8 719 wallCounter=0;
mbedalvaro 31:5f039cbddee8 720 }
mbedalvaro 31:5f039cbddee8 721 }
mbedalvaro 31:5f039cbddee8 722 wallCounter++;
mbedalvaro 31:5f039cbddee8 723 }
mbedalvaro 31:5f039cbddee8 724
mbedalvaro 31:5f039cbddee8 725 // Drawing the graphics - this will in fact use the graphic renderer - if any - and produce the trajectory to be displayed by the laser
mbedalvaro 31:5f039cbddee8 726 void elasticLoop::draw() {
mbedalvaro 31:5f039cbddee8 727 // for the time being, there is no "opengl" like renderer, so we just copy the coordinates of the mass into the lsdTrajectory:
mbedalvaro 31:5f039cbddee8 728 for (int i = 0; i < numMasses; i++) {
mbedalvaro 31:5f039cbddee8 729 displaySensingBuffer.lsdTrajectory[i].x= (unsigned short)( massesLoop[i].pos.x ); // note: it should be an unsigned short
mbedalvaro 31:5f039cbddee8 730 displaySensingBuffer.lsdTrajectory[i].y= (unsigned short)( massesLoop[i].pos.y );
mbedalvaro 31:5f039cbddee8 731
mbedalvaro 31:5f039cbddee8 732 //displaySensingBuffer.lsdTrajectory[i]= massesLoop[i].pos.y; // NOTE: doing this means converting from unsigned short to float (vector2Dd to vector2Df)
mbedalvaro 31:5f039cbddee8 733
mbedalvaro 31:5f039cbddee8 734 //displaySensingBuffer.lsdTrajectory[i].color=blobColor; // perhaps per point color is not a good idea for the time being...
mbedalvaro 31:5f039cbddee8 735 }
mbedalvaro 31:5f039cbddee8 736
mbedalvaro 31:5f039cbddee8 737 // Global color for the whole loop:
mbedalvaro 31:5f039cbddee8 738 displaySensingBuffer.displayColor=transientBlobColor;
mbedalvaro 31:5f039cbddee8 739 }
mbedalvaro 31:5f039cbddee8 740
mbedalvaro 31:5f039cbddee8 741 void elasticLoop::processLoopData() {
mbedalvaro 31:5f039cbddee8 742
mbedalvaro 31:5f039cbddee8 743 // (0) Check if the blob touched the borders:
mbedalvaro 31:5f039cbddee8 744 blobWallCollision=false;
mbedalvaro 31:5f039cbddee8 745 for (int i = 0; i < numMasses; i++) blobWallCollision= (blobWallCollision || massesLoop[i].bWallCollision);
mbedalvaro 31:5f039cbddee8 746
mbedalvaro 31:5f039cbddee8 747 // (1) Compute all the "hairvectors" for the loop (this is, the normals to the particles, pointing outwards).
mbedalvaro 31:5f039cbddee8 748 // This will be approximated by taking the 90 deg rotated difference between contiguous particles positions.
mbedalvaro 31:5f039cbddee8 749 for (int i = 0; i < numMasses; i++) {
mbedalvaro 31:5f039cbddee8 750 vector2Df diff;
mbedalvaro 31:5f039cbddee8 751 diff.set(massesLoop[(i+1)%numMasses].pos-massesLoop[i].pos);
mbedalvaro 31:5f039cbddee8 752 // normalize and rotate 90 deg:
mbedalvaro 31:5f039cbddee8 753 // NOTE: to save memory, we can drop hairVector...
mbedalvaro 31:5f039cbddee8 754 hairVector[i]=diff.getPerpendicularNormed(CW);
mbedalvaro 31:5f039cbddee8 755 //lightForce[i]=diff.getPerpendicularNormed(CW);
mbedalvaro 31:5f039cbddee8 756 }
mbedalvaro 31:5f039cbddee8 757
mbedalvaro 31:5f039cbddee8 758 // (2) Compute area:
mbedalvaro 31:5f039cbddee8 759 // (a) using Green method:
mbedalvaro 31:5f039cbddee8 760 area=0;
mbedalvaro 31:5f039cbddee8 761 float dx;
mbedalvaro 31:5f039cbddee8 762 for (int i = 0; i < numMasses-1; i++){
mbedalvaro 31:5f039cbddee8 763 dx=massesLoop[i].pos.x-massesLoop[i+1].pos.x;
mbedalvaro 31:5f039cbddee8 764 area+=dx*massesLoop[i].pos.y;
mbedalvaro 31:5f039cbddee8 765 }
mbedalvaro 31:5f039cbddee8 766 // to avoid computation problems:
mbedalvaro 31:5f039cbddee8 767 // if (area<=0) area=1; // or just norm: area CAN be negative! (a loop that is larger than the original blob...)
mbedalvaro 31:5f039cbddee8 768
mbedalvaro 31:5f039cbddee8 769 // (b) Compute approximate area from enclosing rectangle:
mbedalvaro 31:5f039cbddee8 770 computeBoundingBox();
mbedalvaro 31:5f039cbddee8 771
mbedalvaro 31:5f039cbddee8 772 // (c) Compute kinetic energy:
mbedalvaro 31:5f039cbddee8 773 totalKineticEnergy=0;
mbedalvaro 31:5f039cbddee8 774 for (int i = 0; i < numMasses; i++){
mbedalvaro 31:5f039cbddee8 775 totalKineticEnergy+=massesLoop[i].getSpeed().squareLength();
mbedalvaro 31:5f039cbddee8 776 }
mbedalvaro 31:5f039cbddee8 777 }
mbedalvaro 31:5f039cbddee8 778
mbedalvaro 31:5f039cbddee8 779
mbedalvaro 31:5f039cbddee8 780 void elasticLoop::computeBoundingBox() {
mbedalvaro 31:5f039cbddee8 781 float minx=4096, maxx=-1, miny=4096, maxy=-1;
mbedalvaro 31:5f039cbddee8 782 for (int i = 0; i < numMasses; i++) {
mbedalvaro 31:5f039cbddee8 783 if (i == 0) {
mbedalvaro 31:5f039cbddee8 784 minx = massesLoop[i].pos.x;
mbedalvaro 31:5f039cbddee8 785 maxx = massesLoop[i].pos.x;
mbedalvaro 31:5f039cbddee8 786 miny = massesLoop[i].pos.y;
mbedalvaro 31:5f039cbddee8 787 maxy = massesLoop[i].pos.y;
mbedalvaro 31:5f039cbddee8 788 } else {
mbedalvaro 31:5f039cbddee8 789
mbedalvaro 31:5f039cbddee8 790 minx = min(minx, massesLoop[i].pos.x);
mbedalvaro 31:5f039cbddee8 791 maxx = max(maxx, massesLoop[i].pos.x);
mbedalvaro 31:5f039cbddee8 792 miny = min(miny, massesLoop[i].pos.y);
mbedalvaro 31:5f039cbddee8 793 maxy = max(maxy, massesLoop[i].pos.y);
mbedalvaro 31:5f039cbddee8 794 }
mbedalvaro 31:5f039cbddee8 795 }
mbedalvaro 31:5f039cbddee8 796
mbedalvaro 31:5f039cbddee8 797 // final results:
mbedalvaro 31:5f039cbddee8 798 w = maxx - minx;
mbedalvaro 31:5f039cbddee8 799 h = maxy - miny;
mbedalvaro 31:5f039cbddee8 800 cx = minx+0.5*w; // note: center will be initialized with posX and posY when calling setInitialPos() of blobConfig
mbedalvaro 31:5f039cbddee8 801 cy = miny+0.5*h;
mbedalvaro 31:5f039cbddee8 802
mbedalvaro 31:5f039cbddee8 803 // approx area:
mbedalvaro 31:5f039cbddee8 804 approxArea=w*h;
mbedalvaro 31:5f039cbddee8 805 }
mbedalvaro 31:5f039cbddee8 806
mbedalvaro 31:5f039cbddee8 807 void elasticLoop::sendDataSpecific() {
mbedalvaro 31:5f039cbddee8 808 char auxstring[10];
mbedalvaro 31:5f039cbddee8 809 myled2=1; // for tests...
mbedalvaro 31:5f039cbddee8 810
mbedalvaro 31:5f039cbddee8 811 // First, set the top address of the message to the ID of the blob (not the name):
mbedalvaro 31:5f039cbddee8 812 // sprintf(auxstring, "%d", identifier);
mbedalvaro 31:5f039cbddee8 813 // sendMes.setTopAddress("0");//auxstring);
mbedalvaro 31:5f039cbddee8 814
mbedalvaro 31:5f039cbddee8 815 // ===================== OSC ======================
mbedalvaro 31:5f039cbddee8 816 if (sendOSC) {
mbedalvaro 31:5f039cbddee8 817
mbedalvaro 31:5f039cbddee8 818 // (new) Total kinetic energy:
mbedalvaro 31:5f039cbddee8 819 if (sendingKineticEnergy) {
mbedalvaro 31:5f039cbddee8 820 sprintf(auxstring, "/k %d",identifier);
mbedalvaro 31:5f039cbddee8 821 sendMes.setSubAddress(auxstring);
mbedalvaro 31:5f039cbddee8 822 long x; //ATTENTION: parameters to setArgs should be long or unsigned long only (not int!!)
mbedalvaro 31:5f039cbddee8 823 x=(long)(totalKineticEnergy);
mbedalvaro 31:5f039cbddee8 824 sendMes.setArgs( "i", &x);
mbedalvaro 31:5f039cbddee8 825 osc.sendOsc( &sendMes );
mbedalvaro 31:5f039cbddee8 826 }
mbedalvaro 31:5f039cbddee8 827 // (a) Anchor mass:
mbedalvaro 31:5f039cbddee8 828 if (sendingAnchorPosition) {
mbedalvaro 31:5f039cbddee8 829 sprintf(auxstring, "/p %d",identifier);
mbedalvaro 31:5f039cbddee8 830 sendMes.setSubAddress(auxstring);
mbedalvaro 31:5f039cbddee8 831 long x, y; //ATTENTION: parameters to setArgs should be long or unsigned long only (not int!!)
mbedalvaro 31:5f039cbddee8 832 x=(long)(anchorMass.pos.x);
mbedalvaro 31:5f039cbddee8 833 y=(long)(anchorMass.pos.y);
mbedalvaro 31:5f039cbddee8 834 sendMes.setArgs( "ii", &x, &y);
mbedalvaro 31:5f039cbddee8 835 osc.sendOsc( &sendMes );
mbedalvaro 31:5f039cbddee8 836 }
mbedalvaro 31:5f039cbddee8 837 if (sendingAnchorForce) {
mbedalvaro 31:5f039cbddee8 838 sendMes.setSubAddress("/aforce");
mbedalvaro 31:5f039cbddee8 839 long x, y; //ATTENTION: parameters to setArgs should be long or unsigned long only (not int!!)
mbedalvaro 31:5f039cbddee8 840 x=(long)(anchorMass.totalForce.x);
mbedalvaro 31:5f039cbddee8 841 y=(long)(anchorMass.totalForce.y);
mbedalvaro 31:5f039cbddee8 842 sendMes.setArgs( "ii", &x, &y);
mbedalvaro 31:5f039cbddee8 843 osc.sendOsc( &sendMes );
mbedalvaro 31:5f039cbddee8 844 }
mbedalvaro 31:5f039cbddee8 845 if (sendingAnchorTouchWall) {// note: not an else (we can send different data simultaneously)
mbedalvaro 31:5f039cbddee8 846 sendMes.setSubAddress("/awall");
mbedalvaro 31:5f039cbddee8 847 long wall=(long)(anchorMass.bWallCollision? 1 : 0);
mbedalvaro 31:5f039cbddee8 848 sendMes.setArgs( "i", &wall);
mbedalvaro 31:5f039cbddee8 849 osc.sendOsc( &sendMes );
mbedalvaro 31:5f039cbddee8 850 }
mbedalvaro 31:5f039cbddee8 851 // (b) data from blob points:
mbedalvaro 31:5f039cbddee8 852 if (sendingLoopPositions) {
mbedalvaro 31:5f039cbddee8 853 #ifdef SEND_AS_POINTS
mbedalvaro 31:5f039cbddee8 854 long x, y; //ATTENTION: parameters to setArgs should be long or unsigned long only (not int!!)
mbedalvaro 31:5f039cbddee8 855 for (int i = 0; i < numMasses; i++) {
mbedalvaro 31:5f039cbddee8 856 sprintf(auxstring, "/p %d", i); // auxstring read as "/p1", "/p2", ...
mbedalvaro 31:5f039cbddee8 857 sendMes.setSubAddress(auxstring); // ATTENTION: the host computer needs to know in advance how many points are in the loop (I did not implement "bundle" messages yet...)
mbedalvaro 31:5f039cbddee8 858 x=(long)(massesLoop[i].pos.x);
mbedalvaro 31:5f039cbddee8 859 y=(long)(massesLoop[i].pos.y);
mbedalvaro 31:5f039cbddee8 860 sendMes.setArgs( "ii", &x, &y);
mbedalvaro 31:5f039cbddee8 861 osc.sendOsc( &sendMes );
mbedalvaro 31:5f039cbddee8 862 }
mbedalvaro 31:5f039cbddee8 863 #endif
mbedalvaro 31:5f039cbddee8 864 #ifdef SEND_AS_BLOB
mbedalvaro 31:5f039cbddee8 865 sendMes.clearArgs(); // no need, we won't use osc.sendOsc()...
mbedalvaro 31:5f039cbddee8 866 uint8_t blobdata[4*numMasses]; // 2 bytes per coordinate, and 2 coordinates
mbedalvaro 31:5f039cbddee8 867 for (int i = 0; i < numMasses; i++ ) {
mbedalvaro 31:5f039cbddee8 868 // note: massesLoop[i].pos.x is a "float"
mbedalvaro 31:5f039cbddee8 869 uint16_t x=(uint16_t)(massesLoop[i].pos.x);
mbedalvaro 31:5f039cbddee8 870 blobdata[4*i]=(uint8_t)x>>8; // BIG ENDIAN (send FIRST the MOST SIGNIFICANT BYTE)
mbedalvaro 31:5f039cbddee8 871 blobdata[4*i+1]=(uint8_t)x;
mbedalvaro 31:5f039cbddee8 872
mbedalvaro 31:5f039cbddee8 873 uint16_t y=(uint16_t)(massesLoop[i].pos.y);
mbedalvaro 31:5f039cbddee8 874 blobdata[4*i+2]=(uint8_t)y>>8; // BIG ENDIAN (send FIRST the MOST SIGNIFICANT BYTE)
mbedalvaro 31:5f039cbddee8 875 blobdata[4*i+3]=(uint8_t)y;
mbedalvaro 31:5f039cbddee8 876 }
mbedalvaro 31:5f039cbddee8 877 osc.sendOscBlob(&(blobdata[0]), 4*numMasses, &sendMes ); // second parameter is osc blob size in bytes
mbedalvaro 31:5f039cbddee8 878 #endif
mbedalvaro 31:5f039cbddee8 879 #ifdef SEND_AS_STRING
mbedalvaro 31:5f039cbddee8 880 sendMes.clearArgs(); // no need, we won't use osc.sendOsc()...
mbedalvaro 31:5f039cbddee8 881 uint8_t blobdata[4*numMasses]; // 2 bytes per coordinate, and 2 coordinates
mbedalvaro 31:5f039cbddee8 882 for (int i = 0; i < numMasses; i++ ) {
mbedalvaro 31:5f039cbddee8 883 // note: massesLoop[i].pos.x is a "float"
mbedalvaro 31:5f039cbddee8 884 uint16_t x=(uint16_t)(massesLoop[i].pos.x);
mbedalvaro 31:5f039cbddee8 885 blobdata[4*i]=(uint8_t)x>>8; // BIG ENDIAN (send FIRST the MOST SIGNIFICANT BYTE)
mbedalvaro 31:5f039cbddee8 886 blobdata[4*i+1]=(uint8_t)x;
mbedalvaro 31:5f039cbddee8 887
mbedalvaro 31:5f039cbddee8 888 uint16_t y=(uint16_t)(massesLoop[i].pos.y);
mbedalvaro 31:5f039cbddee8 889 blobdata[4*i+2]=(uint8_t)y>>8; // BIG ENDIAN (send FIRST the MOST SIGNIFICANT BYTE)
mbedalvaro 31:5f039cbddee8 890 blobdata[4*i+3]=(uint8_t)y;
mbedalvaro 31:5f039cbddee8 891 }
mbedalvaro 31:5f039cbddee8 892 osc.sendOscString(blobdata, 4*numMasses, &sendMes ); // second parameter is osc blob size in bytes
mbedalvaro 31:5f039cbddee8 893 #endif
mbedalvaro 31:5f039cbddee8 894 }
mbedalvaro 31:5f039cbddee8 895 if (sendingLoopForces) { // ATTN: the force is the TOTAL force on the point (interesting perhaps for making sound...)
mbedalvaro 31:5f039cbddee8 896 long x, y; //ATTENTION: parameters to setArgs should be long or unsigned long only (not int!!)
mbedalvaro 31:5f039cbddee8 897 for (int i = 0; i < numMasses; i++) {
mbedalvaro 31:5f039cbddee8 898 sprintf(auxstring, "/f%d", i); // auxstring read as "/f1", "/f2", ...
mbedalvaro 31:5f039cbddee8 899 sendMes.setSubAddress(auxstring); // ATTENTION: the host computer needs to know in advance how many points are in the loop (I did not implement "bundle" messages yet...)
mbedalvaro 31:5f039cbddee8 900 x=(long)(massesLoop[i].totalForce.x);
mbedalvaro 31:5f039cbddee8 901 y=(long)(massesLoop[i].totalForce.y);
mbedalvaro 31:5f039cbddee8 902 sendMes.setArgs( "ii", &x, &y);
mbedalvaro 31:5f039cbddee8 903 osc.sendOsc( &sendMes );
mbedalvaro 31:5f039cbddee8 904 }
mbedalvaro 31:5f039cbddee8 905 }
mbedalvaro 31:5f039cbddee8 906 if (sendingLoopForcesLight) { // ATTN: the force is the TOTAL force on the point (interesting perhaps for making sound...)
mbedalvaro 31:5f039cbddee8 907 long x, y; //ATTENTION: parameters to setArgs should be long or unsigned long only (not int!!)
mbedalvaro 31:5f039cbddee8 908 for (int i = 0; i < numMasses; i++) {
mbedalvaro 31:5f039cbddee8 909 sprintf(auxstring, "/g%d", i); // auxstring read as "/f1", "/f2", ...
mbedalvaro 31:5f039cbddee8 910 sendMes.setSubAddress(auxstring); // ATTENTION: the host computer needs to know in advance how many points are in the loop (I did not implement "bundle" messages yet...)
mbedalvaro 31:5f039cbddee8 911 x=(long)(1000*lightForce[i].x);
mbedalvaro 31:5f039cbddee8 912 y=(long)(1000*lightForce[i].y);
mbedalvaro 31:5f039cbddee8 913 sendMes.setArgs( "ii", &x, &y);
mbedalvaro 31:5f039cbddee8 914 osc.sendOsc( &sendMes );
mbedalvaro 31:5f039cbddee8 915 }
mbedalvaro 31:5f039cbddee8 916 }
mbedalvaro 31:5f039cbddee8 917
mbedalvaro 31:5f039cbddee8 918 if (sendingLoopRegions) {
mbedalvaro 31:5f039cbddee8 919 long x; //ATTENTION: parameters to setArgs should be long or unsigned long only (not int!!)
mbedalvaro 31:5f039cbddee8 920 for (int i = 0; i < numMasses; i++) {
mbedalvaro 31:5f039cbddee8 921 sprintf(auxstring, "/r%d", i); // auxstring read as "/f1", "/f2", ...
mbedalvaro 31:5f039cbddee8 922 sendMes.setSubAddress(auxstring); // ATTENTION: the host computer needs to know in advance how many points are in the loop (I did not implement "bundle" messages yet...)
mbedalvaro 31:5f039cbddee8 923 x=(long)(displaySensingBuffer.lsdTrajectory[i].lightZone>0? 1 : 0);
mbedalvaro 31:5f039cbddee8 924 sendMes.setArgs( "i", &x);
mbedalvaro 31:5f039cbddee8 925 osc.sendOsc( &sendMes );
mbedalvaro 31:5f039cbddee8 926 }
mbedalvaro 31:5f039cbddee8 927 }
mbedalvaro 31:5f039cbddee8 928 if (sendingLoopTouchWall) { // global touch wall for the loop (not per point)
mbedalvaro 31:5f039cbddee8 929 long wall; //ATTENTION: parameters to setArgs should be long or unsigned long only (not int!!)
mbedalvaro 31:5f039cbddee8 930 sprintf(auxstring, "/bWall");
mbedalvaro 31:5f039cbddee8 931 sendMes.setSubAddress(auxstring);
mbedalvaro 31:5f039cbddee8 932 wall=(long)(blobWallCollision? 1 : 0);
mbedalvaro 31:5f039cbddee8 933 sendMes.setArgs( "i", &wall);
mbedalvaro 31:5f039cbddee8 934 osc.sendOsc( &sendMes );
mbedalvaro 31:5f039cbddee8 935 }
mbedalvaro 31:5f039cbddee8 936 // (c) Blob geometry:
mbedalvaro 31:5f039cbddee8 937 if (sendingBlobArea) {
mbedalvaro 31:5f039cbddee8 938 /* sendMes.setSubAddress("/a");
mbedalvaro 31:5f039cbddee8 939 long x; //ATTENTION: parameters to setArgs should be long or unsigned long only (not int!!)
mbedalvaro 31:5f039cbddee8 940 // x=(long)(area);//approxArea); // area or approxArea
mbedalvaro 31:5f039cbddee8 941 x=(long)(area>0? approxArea : -approxArea);
mbedalvaro 31:5f039cbddee8 942 sendMes.setArgs( "i", &x); // ATTENTION: AREA CAN BE NEGATIVE!!! (does MAX handles this well? test this!)
mbedalvaro 31:5f039cbddee8 943 */
mbedalvaro 31:5f039cbddee8 944 // HACK for the time being (for Daito):
mbedalvaro 31:5f039cbddee8 945 sendMes.setSubAddress("/a");
mbedalvaro 31:5f039cbddee8 946 long x, y; //ATTENTION: parameters to setArgs should be long or unsigned long only (not int!!)
mbedalvaro 31:5f039cbddee8 947 // x=(long)(area);//approxArea); // area or approxArea
mbedalvaro 31:5f039cbddee8 948 x=(long)(w); y=(long)(h);
mbedalvaro 31:5f039cbddee8 949 sendMes.setArgs( "ii", &x, &y); // ATTENTION: AREA CAN BE NEGATIVE!!! (does MAX handles this well? test this!)
mbedalvaro 31:5f039cbddee8 950
mbedalvaro 31:5f039cbddee8 951 osc.sendOsc( &sendMes );
mbedalvaro 31:5f039cbddee8 952 }
mbedalvaro 31:5f039cbddee8 953 if (sendingBlobNormals) {
mbedalvaro 31:5f039cbddee8 954 long x, y; //ATTENTION: parameters to setArgs should be long or unsigned long only (not int!!)
mbedalvaro 31:5f039cbddee8 955 for (int i = 0; i < numMasses; i++) {
mbedalvaro 31:5f039cbddee8 956 sprintf(auxstring, "nf%d", i); // auxstring read as "/f1", "/f2", ...
mbedalvaro 31:5f039cbddee8 957 sendMes.setSubAddress(auxstring); // ATTENTION: the host computer needs to know in advance how many points are in the loop (I did not implement "bundle" messages yet...)
mbedalvaro 31:5f039cbddee8 958 x=(long)(hairVector[i].x);
mbedalvaro 31:5f039cbddee8 959 y=(long)(hairVector[i].y);
mbedalvaro 31:5f039cbddee8 960 sendMes.setArgs( "ii", &x, &y);
mbedalvaro 31:5f039cbddee8 961 osc.sendOsc( &sendMes );
mbedalvaro 31:5f039cbddee8 962 }
mbedalvaro 31:5f039cbddee8 963 }
mbedalvaro 31:5f039cbddee8 964 if (sendingBlobAngles) {
mbedalvaro 31:5f039cbddee8 965 long x; //ATTENTION: parameters to setArgs should be long or unsigned long only (not int!!)
mbedalvaro 31:5f039cbddee8 966 for (int i = 0; i < numMasses; i++) {
mbedalvaro 31:5f039cbddee8 967 sprintf(auxstring, "/a%d", i); // auxstring read as "/f1", "/f2", ...
mbedalvaro 31:5f039cbddee8 968 sendMes.setSubAddress(auxstring); // ATTENTION: the host computer needs to know in advance how many points are in the loop (I did not implement "bundle" messages yet...)
mbedalvaro 31:5f039cbddee8 969 x=(long)(hairVector[i].angleDegHoriz());
mbedalvaro 31:5f039cbddee8 970 sendMes.setArgs( "i", &x);
mbedalvaro 31:5f039cbddee8 971 osc.sendOsc( &sendMes );
mbedalvaro 31:5f039cbddee8 972 }
mbedalvaro 31:5f039cbddee8 973 }
mbedalvaro 31:5f039cbddee8 974 // (d) Light sensing statistics:
mbedalvaro 31:5f039cbddee8 975 if (sendingBlobMaxMin) {
mbedalvaro 31:5f039cbddee8 976 sendMes.setSubAddress("/maxmin");
mbedalvaro 31:5f039cbddee8 977 long x, y; //ATTENTION: parameters to setArgs should be long or unsigned long only (not int!!)
mbedalvaro 31:5f039cbddee8 978 x=(long)(displaySensingBuffer.maxI);
mbedalvaro 31:5f039cbddee8 979 y=(long)(displaySensingBuffer.minI);
mbedalvaro 31:5f039cbddee8 980 sendMes.setArgs( "ii", &x, &y);
mbedalvaro 31:5f039cbddee8 981 osc.sendOsc( &sendMes );
mbedalvaro 31:5f039cbddee8 982 }
mbedalvaro 31:5f039cbddee8 983 if (sendingLightForce) {
mbedalvaro 31:5f039cbddee8 984 sendMes.setSubAddress("/lforce");
mbedalvaro 31:5f039cbddee8 985 long x, y; //ATTENTION: parameters to setArgs should be long or unsigned long only (not int!!)
mbedalvaro 31:5f039cbddee8 986 x=(long)(totalLightForce.x);
mbedalvaro 31:5f039cbddee8 987 y=(long)(totalLightForce.y);
mbedalvaro 31:5f039cbddee8 988 sendMes.setArgs( "ii", &x, &y);
mbedalvaro 31:5f039cbddee8 989 osc.sendOsc( &sendMes );
mbedalvaro 31:5f039cbddee8 990 }
mbedalvaro 31:5f039cbddee8 991 // (e) Recentering vector: (note: redundant with sendingLightForce, IF the correction angle is known).
mbedalvaro 31:5f039cbddee8 992 if (sendingRecenteringVector) {
mbedalvaro 31:5f039cbddee8 993 sendMes.setSubAddress("/rvector");
mbedalvaro 31:5f039cbddee8 994 long x, y; //ATTENTION: parameters to setArgs should be long or unsigned long only (not int!!)
mbedalvaro 31:5f039cbddee8 995 x=(long)(recenteringVectorLoop.x);
mbedalvaro 31:5f039cbddee8 996 y=(long)(recenteringVectorLoop.y);
mbedalvaro 31:5f039cbddee8 997 sendMes.setArgs( "ii", &x, &y);
mbedalvaro 31:5f039cbddee8 998 osc.sendOsc( &sendMes );
mbedalvaro 31:5f039cbddee8 999 }
mbedalvaro 31:5f039cbddee8 1000 if (sendingRecenteringAngle) {
mbedalvaro 31:5f039cbddee8 1001 sendMes.setSubAddress("/rangle");
mbedalvaro 31:5f039cbddee8 1002 long x; //ATTENTION: parameters to setArgs should be long or unsigned long only (not int!!)
mbedalvaro 31:5f039cbddee8 1003 x=(long)(angleRecenteringVector);
mbedalvaro 31:5f039cbddee8 1004 sendMes.setArgs( "i", &x);
mbedalvaro 31:5f039cbddee8 1005 osc.sendOsc( &sendMes );
mbedalvaro 31:5f039cbddee8 1006 }
mbedalvaro 31:5f039cbddee8 1007 if (sendingRecenteringNorm) {
mbedalvaro 31:5f039cbddee8 1008 sendMes.setSubAddress("/rnorm");
mbedalvaro 31:5f039cbddee8 1009 long x; //ATTENTION: parameters to setArgs should be long or unsigned long only (not int!!)
mbedalvaro 31:5f039cbddee8 1010 x=(long)(normRecenteringVector);
mbedalvaro 31:5f039cbddee8 1011 sendMes.setArgs( "i", &x);
mbedalvaro 31:5f039cbddee8 1012 osc.sendOsc( &sendMes );
mbedalvaro 31:5f039cbddee8 1013 }
mbedalvaro 31:5f039cbddee8 1014
mbedalvaro 31:5f039cbddee8 1015 if (sendingTouched) {
mbedalvaro 31:5f039cbddee8 1016 if (displaySensingBuffer.lightTouched) {
mbedalvaro 31:5f039cbddee8 1017 sendMes.clearArgs(); // there are no arguments to send
mbedalvaro 31:5f039cbddee8 1018 sendMes.setSubAddress("/touched");
mbedalvaro 31:5f039cbddee8 1019 osc.sendOsc( &sendMes );
mbedalvaro 31:5f039cbddee8 1020 }
mbedalvaro 31:5f039cbddee8 1021 }
mbedalvaro 31:5f039cbddee8 1022
mbedalvaro 31:5f039cbddee8 1023 } // end of OSC sending per-spot
mbedalvaro 31:5f039cbddee8 1024
mbedalvaro 31:5f039cbddee8 1025 // ===================== SERIAL ======================
mbedalvaro 31:5f039cbddee8 1026 if (sendSerial) {
mbedalvaro 31:5f039cbddee8 1027 //.. to do
mbedalvaro 31:5f039cbddee8 1028 }
mbedalvaro 31:5f039cbddee8 1029
mbedalvaro 31:5f039cbddee8 1030 myled2=0; // for tests...
mbedalvaro 31:5f039cbddee8 1031 }
mbedalvaro 31:5f039cbddee8 1032