#include "Arduino.h" #include "behaviour.h" SimplexNoise sn; Mood mood; float map_mode_rollpitch=0; float map_mode_walking=0; float map_mode_sleeping=0; float map_mode_noise=0; float matrix_weights_main[SERVO_COUNT_MAIN][WEIGHT_COUNT]; //mapping outputs, sensors/moods float matrix_weights_peripheralL[SERVO_COUNT_PERIPHERAL][WEIGHT_COUNT]; float matrix_weights_peripheralR[SERVO_COUNT_PERIPHERAL][WEIGHT_COUNT]; void initBehaviour() { mood.arousal=0; mood.valence=0; } void updateMood(unsigned long millis,float gyroX,float gyroY,float gyroZ,float maxAccX,float maxAccY,float maxAccZ,bool bellyup, bool body_present, bool contact_main, bool contact_peripheralL, bool contact_peripheralR,float height,float temp_ambient,float temp_object,float pumpspeed, float servoerror) { static unsigned long last_mood_update=0; if (millis-last_mood_update>MOOD_UPDATE_INTERVAL) { last_mood_update=millis; float step=MOOD_UPDATE_INTERVAL/1000.0; if (body_present && pumpspeed<0.8) { //body present and vacuum present (pump below speed 1.0) if (mood.valence<0.0) { //when attached, and valence low mood.valence=0.2; //jump valence up quickly } if (mood.valence<0.5) { //increase valence up to a certain point mood.valence+=step*0.05; } } if (!body_present) { if (mood.valence>-0.5) { //decrease valence down to a certain point mood.valence-=step*0.01; } } static unsigned long last_contact_time=0; static bool last_contact_main=false; static bool last_contact_peripheralR=false; static bool last_contact_peripheralL=false; if (contact_main || contact_peripheralL || contact_peripheralR) { if ((contact_main && !last_contact_main) || (contact_peripheralL && !last_contact_peripheralL) || (contact_peripheralR && !last_contact_peripheralR)) { //on first contact long _contacttime_min=1000; long _contacttime_max=20000; float _contact_increase_arousal=0.7; float _contact_increase_valence=0.1; if (mood.valence<-0.2) { long _contacttime_min=500; long _contacttime_max=2000; float _contact_increase_arousal=0.7; float _contact_increase_valence=-0.2; } float olda=mood.arousal; float oldv=mood.valence; mood.arousal+=constrain(mapfloat(millis-last_contact_time,_contacttime_min,_contacttime_max,0,_contact_increase_arousal),0,_contact_increase_arousal); mood.valence+=constrain(mapfloat(millis-last_contact_time,_contacttime_min,_contacttime_max,0,_contact_increase_valence),0,_contact_increase_valence); Serial.print("Contact. increase arousal:"); Serial.print(mood.arousal-olda); Serial.print(" valence:"); Serial.print(mood.valence-oldv); Serial.println(); } last_contact_time=millis; } last_contact_main=contact_main; last_contact_peripheralR=contact_peripheralR; last_contact_peripheralL=contact_peripheralL; static float last_height=0; static float heightdiffsmooth=0; //goes up to 0.2 when lifted or lowered quickly 1m and slowly deacreases to 0 heightdiffsmooth+=height-last_height; if (heightdiffsmooth>0) { heightdiffsmooth-=behaviour_confortable_lift*step; }else if (heightdiffsmooth<0) { heightdiffsmooth+=behaviour_confortable_lift*step; //0.1*step means 0.1m of heightchange per second does not affect heightdiffsmooth } //Serial.print("heightdiffsmooth:"); Serial.println(heightdiffsmooth,3); float maxAcc=sqrt(pow(maxAccX,2)+pow(maxAccY,2)+pow(maxAccZ,2)); float preferredMaxAcc=0.5; if (constrain(mapfloat(abs(preferredMaxAcc-maxAcc),0.0,0.3,1.0,0.0),0.0,1.0)>0.0) { digitalWrite(PIN_LED,LOW); //On }else{ digitalWrite(PIN_LED,HIGH); //Off } if (mood.arousal<-0.5) { mood.arousal+=constrain(mapfloat(abs(preferredMaxAcc-maxAcc),0.0,0.3,1.0,0.0),0.0,1.0)*step*0.2; }else{ mood.valence+=constrain(mapfloat(abs(preferredMaxAcc-maxAcc),0.0,0.3,1.0,0.0),0.0,1.0)*step*0.2; if (mood.arousal>0.7) { mood.arousal-=step*0.04; }else if(mood.arousal<0.3) { mood.arousal+=step*0.03; } } if (abs(heightdiffsmooth)>0.05) { mood.valence-=abs(heightdiffsmooth)*step*1.0; if (mood.arousal<0.9){ mood.arousal+=abs(heightdiffsmooth)*step*3.0; } } last_height=height; mood.arousal-=step*0.02; //slowly deacrease arousal if (mood.valence<0) { mood.valence+=step*0.03; }else if (mood.valence>0) { mood.valence-=step*0.01; } mood.arousal=constrain(mood.arousal,-1.0,1.0); mood.valence=constrain(mood.valence,-1.0,1.0); } } void updateMatrixWeights(unsigned long millis,bool bellyup, bool body_present, bool contact_main, bool contact_peripheralL, bool contact_peripheralR, float pitch, float roll){ static unsigned long last_weights_update=0; if (millis-last_weights_update>WEIGHT_UPDATE_INTERVAL) { last_weights_update=millis; //### Update Mode ### float aim_map_mode_rollpitch=0; float aim_map_mode_walking=0; float aim_map_mode_sleeping=0; float aim_map_mode_noise=0; if (body_present) { //attached aim_map_mode_rollpitch=constrain(mapfloat(mood.valence,-0.3,0.3,0,1.0),0,1.0); aim_map_mode_noise=constrain(mapfloat(mood.valence,-0.2,-1.0,0,1.0),0,1.0); }else{ //detached if (bellyup) { //belly up aim_map_mode_walking=1.0; }else{ //sitting on a level survace aim_map_mode_noise=constrain(mapfloat(mood.arousal,-0.5,0.5, 0.0,1.0),0,1.0); map_mode_sleeping=constrain(mapfloat(mood.arousal,-1.0,-0.6, 1.0,0.0),0,1.0); } } map_mode_rollpitch=interpolateTo(map_mode_rollpitch,aim_map_mode_rollpitch,WEIGHT_UPDATE_INTERVAL/1000.0,0.3); map_mode_walking=interpolateTo(map_mode_walking,aim_map_mode_walking,WEIGHT_UPDATE_INTERVAL/1000.0,0.3); map_mode_sleeping=interpolateTo(map_mode_sleeping,aim_map_mode_sleeping,WEIGHT_UPDATE_INTERVAL/1000.0,0.3); map_mode_noise=interpolateTo(map_mode_noise,aim_map_mode_noise,WEIGHT_UPDATE_INTERVAL/1000.0,0.3); float map_sum=map_mode_walking+map_mode_rollpitch+map_mode_sleeping+map_mode_noise; map_mode_walking/=map_sum; map_mode_rollpitch/=map_sum; map_mode_sleeping/=map_sum; map_mode_noise/=map_sum; //divide mapping so the sum will be 1.0 analogWrite(PIN_VIBRATION,contact_main?64:0); //reset all weights for (uint8_t i=0;iSERVOWEIGHT_UPDATE_INTERVAL) { last_servoweights_update=millis; static unsigned long millis_add; #define MILLISADD_MIN SERVOWEIGHT_UPDATE_INTERVAL*0.5 #define MILLISADD_MAX SERVOWEIGHT_UPDATE_INTERVAL*2 millis_add+=constrain(mapfloat(mood.arousal, -0.5,0.5 ,MILLISADD_MIN,MILLISADD_MAX),MILLISADD_MIN,MILLISADD_MAX); float vsin=sin((millis_add)/1000.0); float vcos=cos((millis_add)/1000.0); for (uint8_t i=0;i=0)?1:-1; //if angle positive, 1, else 0 if (iaimvalue) { result=aimvalue; } }else if (result>aimvalue){ result=result-timestep*speed; if (result