/*** P control tries to add a force that reduces the distance between the current joint angles and the desired value in the lookup table THETA. ***/ void Pcontrol() { dReal kp = 2.0; //effects how quickly it tries to acheive the desired angle (original=2) // dReal kp = 10.0; //effects how quickly it tries to acheive the desired angle dReal fMax = 100.0; //fMax is the max for it can apply trying to acheive the desired angle //#define ANG_VELOCITY #ifndef ANG_VELOCITY for(int segment = 0; segment < BODY_SEGMENTS; ++segment) { for (int i = 0; i < num_legs; i++) { for (int j = 0; j < num_links; j++) { dReal tmp = dJointGetHingeAngle(leg[segment][i][j].joint); dReal diff = THETA[segment][i][j] - tmp; dReal u; u = kp * diff; //cout << "\n\n***" << u << "***\n\n\n\n" << endl; dJointSetHingeParam(leg[segment][i][j].joint, dParamVel, u); dJointSetHingeParam(leg[segment][i][j].joint, dParamFMax, fMax); } } #else //when using angular velocity for(int segment = 0; segment < BODY_SEGMENTS; ++segment) { for (int i = 0; i < num_legs; i++) { for (int j = 0; j < num_links; j++) { //dReal tmp = dJointGetHingeAngle(leg[segment][i][j].joint); //dReal diff = THETA[segment][i][j] - tmp; //dReal u; //u = kp * diff; dReal desiredValue = THETA[segment][i][j]; desiredValue *= 2.25; //cout << "\n\n***" << desiredValue << "***\n\n\n\n" << endl; dJointSetHingeParam(leg[segment][i][j].joint, dParamVel, desiredValue); dJointSetHingeParam(leg[segment][i][j].joint, dParamFMax, fMax); } } #endif #ifdef USE_NLEG_ROBOT if(segment < BODY_SEGMENTS-1) { // applying torso joint force dReal tmp = dJointGetHingeAngle(torso[segment].joint); //joints might start in segment 2 dReal diff = torsoJointDesiredAngle[segment] - tmp; dReal u; u = kp * diff; dJointSetHingeParam(torso[segment].joint, dParamVel, u); dJointSetHingeParam(torso[segment].joint, dParamFMax, fMax); } #endif } } /*** Control of walking ***/ void walk() { // int numSheets; // // #ifdef HIDDEN_LAYER // numSheets = 3; // #else // numSheets = 2; // #endif timeSteps++; //jmc added to print out joint angles if(printJointAngles){ static bool doOnce = true; if(doOnce){ doOnce=false; //remove the file if it is there already ofstream jangle_file; jangle_file.open ("jointAngles.txt", ios::trunc ); jangle_file.close(); } } //clear out the network //LHZ - When Recurrence is turned on, we multiply the input values by the recurrent values that were in //the input nodes to begin with, if they are all 0, the network will never take a value. So we start it with //all 1's, since this will act as if ther was no recurrence for the first update. substrate_pointer->reinitialize(); if(experimentType != 33) //If it is a NEAT experiment, the substrate can have an arbitrary number of layers, so we need to update 1+ExtraActivationUpdates num times { substrate_pointer->dummyActivation(); //dummyActivation sets a flag so that the first update does not add on ExtraActivationUdates num updates } dReal roll, pitch, yaw; for(int segment = 0; segment < BODY_SEGMENTS; ++segment) { roll = pitch = yaw = 0.0; const dReal * torsoRotation = dBodyGetRotation(torso[segment].body); get_euler(torsoRotation, roll, pitch, yaw); #if LEGSWING_ODE_DEBUG printf("roll: %f, pitch: %f, yaw: %f\n", roll, pitch, yaw); #endif for (int leg_no = 0; leg_no < num_legs; leg_no++) { for (int joint_no = 0; joint_no < num_joints; joint_no++) { dReal jangle = dJointGetHingeAngle(leg[segment][leg_no][joint_no].joint) - jointError[segment][leg_no][joint_no]; // hidding joint error for sensor int currDirectionPositive; if(jangle-lastJangle[segment][leg_no][joint_no] > 0.00001) currDirectionPositive =1; //we use a small positive number to ignore tinsy values else currDirectionPositive =0; //printf("jangle: %e, lastJangle_pneat[leg_no][joint_no]: %e, currDir: %i\n", jangle, lastJangle_pneat[leg_no][joint_no], currDirectionPositive); if(printJointAngles){ ofstream jangle_file; jangle_file.open ("jointAngles.txt", ios::app ); jangle_file << jangle << " "; if(leg_no==num_legs-1 and joint_no==num_joints-1) jangle_file << endl; jangle_file.close(); } if(currDirectionPositive and !lastJangleDirectionPositve[segment][leg_no][joint_no]) numDirectionChanges++; if(!currDirectionPositive and lastJangleDirectionPositve[segment][leg_no][joint_no]) numDirectionChanges++; //if(visualize_pneat) printf("numDirectionChanges_pneat %i \n", numDirectionChanges_pneat); lastJangleDirectionPositve[segment][leg_no][joint_no] =currDirectionPositive; lastJangle[segment][leg_no][joint_no] = jangle; int xInt =joint_no; //which node we will be setting or getting. x & y are within the sheet, z specifies which sheet (0=input, 1=hidden, 2=output) int yInt =leg_no+(segment*2); int zInt =0; #if LEGSWING_ODE_DEBUG printf("About to set input (x: %i,y: %i,z: %i) to joint angle: %f \n", xInt, yInt, zInt, jangle); #endif substrate_pointer->setValue(nameLookupGlobal[HCUBE::Node(xInt,yInt,zInt)],jangle); //<start> if inputting lastDesiredAngle //xInt = xInt+1; //bump it one, cause the last desired angle goes into the input to the right of the current angle for that joint //#if LEGSWING_ODE_DEBUG //printf("about to set input (x: %i,y: %i,z: %i) to last desired joint angle: %f \n", xInt, yInt, zInt, newDesiredAngle[leg_no][joint_no]); //#endif //substrate_pointer->setValue( // nameLookupGlobal[HCUBE::Node(xInt,yInt,zInt)], // newDesiredAngle[segment][leg_no][joint_no] // ); } //set whether the leg is touching the ground int xInt = 3; //putting touch just to the right of the 4th legs lastAngle int yInt = leg_no+(segment*2); int zInt = 0; substrate_pointer->setValue(nameLookupGlobal[HCUBE::Node(xInt,yInt,zInt)], thisLegIsTouching[segment][leg_no]); } #ifndef LEGSWING_ODE_DEBUG assert(num_legs==4); //warning: only works with four legs printf("Legs touching: FrontLeft (%i), BackLeft (%i), BackRight (%i), FrontRight (%i)\n", thisLegIsTouching[segment][0],thisLegIsTouching[segment][1], thisLegIsTouching[segment][2], thisLegIsTouching[segment][3]); #endif //printf("timeStepDivisor_pneat: %f\n", timeStepDivisor_pneat); // use if evolving sine period // if(fabs(timeStepDivisor_pneat<1)) sineOfTimeStep =0; //prevent divide by zero errors, and allow them to silence the sine wave // else sineOfTimeStep = sin(dReal(timeSteps_pneat)/timeStepDivisor_pneat)*M_PI; dReal sineOfTimeStep = sin(dReal(timeSteps)/50.0)*M_PI; #ifdef USE_EXTRA_NODE dReal negSineOfTimeStep = (-1.0 * sineOfTimeStep); #endif if(visualize and sineOfTimeStep>.9999*M_PI) printf("****************************************************\n"); if(visualize and sineOfTimeStep<-.9999*M_PI) printf("---------------------------------------------------\n"); //printf("sineOfTimeStep: %f\n", sineOfTimeStep); #ifndef USE_NLEG_ROBOT //<start> use to spread the PRYS horizontally //insert the roll, pitch and yaw to the 7th-9th columns of the 1st row //int yInt = 0; //int zInt = 0; //dReal insertValue; // //for(int q=0;q<3;q++){ // int xInt = 7+q; // if (q==0) insertValue = roll; // else if (q==1) insertValue = pitch; // else insertValue = yaw; // substrate_pointer->setValue( // nameLookupGlobal[HCUBE::Node(xInt,yInt,zInt)], // insertValue // ); //} //<ent> use to spread the PRYS horizontally //<start> to spread PRYS vertically //insert the roll, pitch and yaw to the 1st/0th-4th/3rd row of the 5th/4th columns int xInt = 4; int zInt = 0; dReal insertValue; for(int q=0;q<3;q++){ int yInt = q; if (q==0) insertValue = roll; else if (q==1) insertValue = pitch; else insertValue = yaw; substrate_pointer->setValue(nameLookupGlobal[HCUBE::Node(xInt,yInt,zInt)], insertValue); } //<end> //insert a sine wave based on timeSteps xInt = 4; int yInt = 3; zInt = 0; substrate_pointer->setValue(nameLookupGlobal[HCUBE::Node(xInt,yInt,zInt)], sineOfTimeStep); #else // USE_NLEG_ROBOT //<start> to spread PRYS vertically //insert the roll, pitch and yaw to the 1st/0th-4th/3rd row of the 5th/4th columns int xInt = 4; int zInt = 0; dReal insertValue; //roll int yInt = segment*2; substrate_pointer->setValue(nameLookupGlobal[HCUBE::Node(xInt,yInt,zInt)], roll); //pitch yInt = (segment*2)+1; substrate_pointer->setValue(nameLookupGlobal[HCUBE::Node(xInt,yInt,zInt)], pitch); //yaw xInt = 5; yInt = segment*2; substrate_pointer->setValue(nameLookupGlobal[HCUBE::Node(xInt,yInt,zInt)], yaw); //<end> if(segment < 1) { //insert a sine wave based on timeSteps yInt = segment*2+1; substrate_pointer->setValue(nameLookupGlobal[HCUBE::Node(xInt,yInt,zInt)], sineOfTimeStep); } else { dReal torsoAngle = dJointGetHingeAngle(torso[segment-1].joint); //TODO: does torso zero have a valid joint? yInt = segment*2+1; substrate_pointer->setValue(nameLookupGlobal[HCUBE::Node(xInt,yInt,zInt)], torsoAngle); } #endif #if SUBSTRATE_DEBUG cout << "State of the nodes pre-update\n"; for (int z=0;z<numSheets;z++) { cout << "Printing Layer " << z << "************************************************" << endl; for (int y1=0;y1<numNodesYglobal;y1++) { for (int x1=0;x1<numNodesXglobal;x1++) { //cout << "(x,y,z): (" << x1 << "," << y1 << "," << z << "): " ; cout << setw(12) << setiosflags(ios::right) << fixed << double(substrate_pointer->getValue( nameLookupGlobal[HCUBE::Node(x1,y1,z)] )); } cout << endl; } } cout << "Updating Substrate\n"; //CREATE_PAUSE(string("Line Number: ")+toString(__LINE__)); #endif //have to update the network once for each layer of *links* (or NumLayers -1) #if SUBSTRATE_DEBUG for (int a=0;a< numSheets - 1 ;a++) { substrate_pointer->update(1); cout << "State of the nodes post-update: " << a << endl; for (int z=0;z<numSheets;z++) { cout << "Printing Layer " << z << endl; for (int y1=0;y1<numNodesYglobal;y1++) { for (int x1=0;x1<numNodesXglobal;x1++) { //cout << "(x,y,z): (" << x1 << "," << y1 << "," << z << "): " ; cout << double(substrate_pointer->getValue(nameLookupGlobal[HCUBE::Node(x1,y1,z)])); cout << " "; } cout << endl; } } } #else substrate_pointer->update(numSheets-1); #endif } for(int segment = 0; segment < BODY_SEGMENTS; ++segment){ for (int leg_no = 0; leg_no < num_legs; leg_no++) { for (int joint_no = 0; joint_no < num_joints; joint_no++) { int xInt =joint_no*2; //which node we will be setting or getting. x & y are within the sheet, z specifies which sheet (0=input, 1=hidden, 2=output) int yInt =leg_no; int zInt = numSheets-1; //2 (or numSheets - 1) to get the output newDesiredAngle[segment][leg_no][joint_no] = M_PI*double(substrate_pointer->getValue(nameLookupGlobal[HCUBE::Node(xInt,yInt,zInt)])); #if LEGSWING_ODE_DEBUG printf("newDesiredAngle is: %f\n", newDesiredAngle[segment][leg_no][joint_no]); #endif THETA[segment][leg_no][joint_no] = newDesiredAngle[segment][leg_no][joint_no] + jointError[segment][leg_no][joint_no]; // adding joint error } } #ifdef USE_NLEG_ROBOT if(segment < BODY_SEGMENTS-1) { //get torso joint angle int xInt = 5; int yInt = segment*2+1; int zInt = numSheets - 1; torsoJointDesiredAngle[segment] = M_PI*double(substrate_pointer->getValue(nameLookupGlobal[HCUBE::Node(xInt,yInt,zInt)])); } #endif //get the timeStepDivisor // xInt =10; //which node we will be setting or getting. x & y are within the sheet, z specifies which sheet (0=input, 1=hidden, 2=output) // yInt =1; // zInt = 2; //2 to get the output // timeStepDivisor = 100.0*double(substrate_pointer->getValue( // nameLookupGlobal[HCUBE::Node(xInt,yInt,zInt)])); //if(visualize)printf("timeStepDivisor!: %f\n", timeStepDivisor); const dReal * torsoPosition = dBodyGetPosition(torso[segment].body); if(fabs(torsoPosition[0]) > maxXdistanceFrom0[segment]){ maxXdistanceFrom0[segment] = fabs(torsoPosition[0]); #ifndef LEGSWING_ODE_DEBUG printf("new maxX::::::::::::::::::::::::::::::::::::::::::::::: %f\n", maxXdistanceFrom0); #endif } if(fabs(torsoPosition[1]) > maxYdistanceFrom0[segment]){ maxYdistanceFrom0[segment] = fabs(torsoPosition[1]); #ifndef LEGSWING_ODE_DEBUG printf("new maxY:!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! %f\n", maxYdistanceFrom0); #endif } currentXdistanceFrom0[segment] = fabs(torsoPosition[0]); currentYdistanceFrom0[segment] = fabs(torsoPosition[1]); } Pcontrol(); for(int segment = 0; segment < BODY_SEGMENTS; ++segment) { for(int z=0;z<num_legs;z++) thisLegIsTouching[segment][z]=0; //reset these flags before checking the new state of things } if(fitness_function == 2) { for(int segment = 0; segment < BODY_SEGMENTS; ++segment) { for (int i = 0; i < num_legs; i++) { for (int j = 0; j < num_links; j++) { totalForce[0] += dBodyGetForce(leg[segment][i][j].body)[0]; totalForce[1] += dBodyGetForce(leg[segment][i][j].body)[1]; totalForce[2] += dBodyGetForce(leg[segment][i][j].body)[2]; } } totalForce[0] += dBodyGetForce(torso[segment].body)[0]; totalForce[1] += dBodyGetForce(torso[segment].body)[1]; totalForce[2] += dBodyGetForce(torso[segment].body)[2]; } } }
/*** シミュレーションループ ***/ void simLoop(int pause) { Pcontrol(); // P制御 dWorldStep(world, 0.01); // 動力学計算 drawArm(); // ロボットの描画 }