/*** 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];
		}
	}	
}
Exemple #2
0
Fichier : arm1.cpp Projet : Ry0/ODE
/*** シミュレーションループ ***/
void simLoop(int pause)
{
  Pcontrol();                                  // P制御
  dWorldStep(world, 0.01);                     // 動力学計算
  drawArm();                                   // ロボットの描画
}