void BodyCutForce(dBodyID body,float l_limit,float w_limit) { const dReal wa_limit=w_limit/fixed_step; const dReal* force= dBodyGetForce(body); dReal force_mag=dSqrt(dDOT(force,force)); //body mass dMass m; dBodyGetMass(body,&m); dReal force_limit =l_limit/fixed_step*m.mass; if(force_mag>force_limit) { dBodySetForce(body, force[0]/force_mag*force_limit, force[1]/force_mag*force_limit, force[2]/force_mag*force_limit ); } const dReal* torque=dBodyGetTorque(body); dReal torque_mag=dSqrt(dDOT(torque,torque)); if(torque_mag<0.001f) return; dMatrix3 tmp,invI,I; // compute inertia tensor in global frame dMULTIPLY2_333 (tmp,m.I,body->R); dMULTIPLY0_333 (I,body->R,tmp); // compute inverse inertia tensor in global frame dMULTIPLY2_333 (tmp,body->invI,body->R); dMULTIPLY0_333 (invI,body->R,tmp); //angular accel dVector3 wa; dMULTIPLY0_331(wa,invI,torque); dReal wa_mag=dSqrt(dDOT(wa,wa)); if(wa_mag>wa_limit) { //scale w for(int i=0;i<3;++i)wa[i]*=wa_limit/wa_mag; dVector3 new_torqu; dMULTIPLY0_331(new_torqu,I,wa); dBodySetTorque ( body, new_torqu[0], new_torqu[1], new_torqu[2] ); } }
ngl::Vec3 RigidBody::getForce() const { // When getting, the returned values are pointers to internal data structures, // so the vectors are valid until any changes are made to the rigid body // system structure. const dReal *pos=dBodyGetForce(m_id); return ngl::Vec3(*pos,*(pos+1),*(pos+2)); }
bool ODERigidObject::WriteState(File& f) const { //TODO: use body quaternion Vector3 w,v; const dReal* pos=dBodyGetPosition(bodyID); const dReal* q=dBodyGetQuaternion(bodyID); GetVelocity(w,v); //do we need this? const dReal* frc=dBodyGetForce(bodyID); const dReal* trq=dBodyGetTorque(bodyID); if(!WriteArrayFile(f,pos,3)) return false; if(!WriteArrayFile(f,q,4)) return false; if(!WriteFile(f,w)) return false; if(!WriteFile(f,v)) return false; if(!WriteArrayFile(f,frc,3)) return false; if(!WriteArrayFile(f,trq,3)) return false; return true; }
/*** 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]; } } }
/* returns the force acting on the body */ void body_force (t_real *res, dBodyID b) { dCopyVector3 (res, dBodyGetForce (b)); }
IoObject *IoODEBody_force(IoODEBody *self, IoObject *locals, IoMessage *m) { IoODEBody_assertValidBody(self, locals, m); return IoVector_newWithODEPoint(IOSTATE, dBodyGetForce(BODYID)); }
void CPHCharacter::getForce(Fvector& force) { if(!b_exist)return; force.set(*(Fvector*)dBodyGetForce(m_body)); }
const dReal * SParts::getForce() { return dBodyGetForce(m_odeobj->body()); }
const dReal* ODE_Link::getForce(){ return dBodyGetForce(bodyId); }
void base::hack_2d(void) { const dReal *rot = dBodyGetAngularVel (body); const dReal *quat_ptr; dReal quat[4], quat_len; quat_ptr = dBodyGetQuaternion (body); quat[0] = quat_ptr[0]; quat[1] = 0; quat[2] = 0; quat[3] = quat_ptr[3]; quat_len = sqrt (quat[0] * quat[0] + quat[3] * quat[3]); quat[0] /= quat_len; quat[3] /= quat_len; dBodySetQuaternion (body, quat); dBodySetAngularVel (body, 0, 0, rot[2]); //Restricting Rotation To One Axis //The plane2D stops objects rotating along non-2d axes, //but it does not compensate for drift const dReal *rot1 = dBodyGetAngularVel( body ); const dReal *quat_ptr1; dReal quat1[4], quat_len1; quat_ptr1 = dBodyGetQuaternion( body ); quat1[0] = quat_ptr1[0]; quat1[1] = 0; quat1[2] = 0; quat1[3] = quat_ptr1[3]; quat_len1 = sqrt( quat1[0] * quat1[0] + quat1[3] * quat1[3] ); quat1[0] /= quat_len1; quat1[3] /= quat_len1; dBodySetQuaternion( body, quat1 ); dBodySetAngularVel( body, 0, 0, rot1[2] ); dMatrix3 R = { 0, 0, 0, 0, 0, 1}; // 0 0 y if(!rotatebit) //if there is no set rotatebit then don't make rotate in ode { quat1[0] = 0; quat1[1] = 0; quat1[2] = 0; quat1[3] = 1; dBodySetQuaternion( body, quat1 ); dBodySetAngularVel( body, 0, 0, 0 ); } static dVector3 pointrelvel; const dReal *odepos; const dReal *force; dBodyGetRelPointVel(body,0,0,0,pointrelvel); odepos=dBodyGetPosition(body); force = dBodyGetForce (body); dBodySetForce(body,force[0],force[1],0.000); if (odepos[2]>=0.001 || odepos[2]<=-0.001 ){ dBodySetPosition (body,odepos[0],odepos[1], 0.000); dBodyAddRelForce (body,0,0, -(pointrelvel[2])); dBodySetTorque (body, 0.00, 0.00, 0.000); } }