コード例 #1
0
ファイル: leg.cpp プロジェクト: artembelaev/juk
void Leg::moveTo(const Vector4 & point)
{
    double x = point.x() - FBasePoint.x();
    double y = point.y() - FBasePoint.y();
    double z = point.z() - FBasePoint.z();

    if (right()) x *= -1;
    
    // Поворот плоскости ноги до целевой точки
    double base_angle = atan2(y, x) * 180.0 / PI;

    if (right()) base_angle *= -1;
        
    // Координаты коленки в плоскости бедра и голени (относительно бедренного сустава)
    double knee_x;
    double knee_y;
    // Координаты кончика ноги в той же системе
    double x2 = sqrt(x*x + y*y) - FEMUR_LEDGE;
    double y2 = -(point.z() - FEMUR_H);
    if (intersectCircles(knee_x, knee_y, FEMUR_LENGTH, x2, y2, TIBIA_LENGTH))
    {
        double femur_angle = atan2(knee_y, knee_x) * 180.0 / PI;
        double tibia_angle = femur_angle + atan2(-(y2 - knee_y), x2 - knee_x) * 180 / PI;

        if (right())
        {
            femur_angle *= -1;
            tibia_angle = 180 - tibia_angle;
        }
        
        setServoAngles(90 + base_angle, 90 + femur_angle, tibia_angle);
    }
}
コード例 #2
0
ファイル: hexapod.cpp プロジェクト: NoDignity/HEX
void hexapod::sit ()
{
	int ii;
	float target[3];
	for (ii=0; ii<6; ii++)
	{
		target[0] = legpos[ii][0] + 10.0*cos(legang[ii]);
		target[1] = legpos[ii][1] + 10.0*sin(legang[ii]);
		target[2] = -5.0;
		IKSolve(ii,target);
	}
	setServoAngles();
}
コード例 #3
0
ファイル: hexapod.cpp プロジェクト: NoDignity/HEX
void hexapod::step (float dt)
{
	int ii, modt;
	float absspeed, speedsgn, ssfrac, ssfrac2;
	float cycletime, xpos, ypos, zpos, target[3];
	float legraise;
	float turn_dist, thtpos, rpos, maxdist;
	float dist, tht0, turn_step, speed_step;

	// clamp speed and turning, just in case
	hexlock.lock();
	if (speed > MAX_SPEED) speed = MAX_SPEED;
	if (speed < -MAX_SPEED) speed = -MAX_SPEED;
	if (turning > 1.0) turning = 1.0;
	if (turning < -1.0) turning = -1.0;
	if (standheight < -2.0) standheight = -2.0;
	if (standheight > 2.0) standheight = 2.0;
	
	// make sure speed doesnt change too rapidly
	speed_step = -(smoothspeed - speed);
	if (speed_step > SPEED_SLEW*dt) speed_step = SPEED_SLEW*dt;
	if (speed_step < -SPEED_SLEW*dt) speed_step = -SPEED_SLEW*dt;
	smoothspeed += speed_step;
	// cap the rate at which turning can change
	
	turn_step = -(smoothturning - turning);
	if (turn_step > TURN_SLEW*dt) turn_step = TURN_SLEW*dt;
	if (turn_step < -TURN_SLEW*dt) turn_step = -TURN_SLEW*dt;
	smoothturning += turn_step;
	
	hexlock.unlock();

	// to control walking, modify speed and turning
	absspeed = fabs(smoothspeed);
	speedsgn = 1.0;
	if (smoothspeed < 0.0) speedsgn = -1.0;

	// walking speed is influenced by leg sweep and movement speed
	legraise = 1.0;
	if (absspeed < 0.05) 
		legraise = absspeed/0.05;
	if (absspeed < 0.2)
	{
		sweepmodifier = absspeed*0.8/0.2;
		speedmodifier = 0.25;
	} else if (absspeed < 0.8) {
		sweepmodifier = 0.8;
		speedmodifier = absspeed/sweepmodifier;
	} else if (absspeed < 1.0) {
		sweepmodifier = absspeed;
		speedmodifier = 1.0;
	} else {
		sweepmodifier = 1.0;
		speedmodifier = absspeed;
	}
	speedmodifier *= speedsgn;

	if (ssrunning)
	{
		sstime += dt;
		ssfrac = sstime/SS_DURATION;
		for (ii=0; ii<6; ii++)
		{
			// compute final target
			target[0] = legpos[ii][0]*1.5;
			if (ii == 0 || ii == 2) target[1] = 14.0;
			if (ii == 1) target[1] = 18.0;
			if (ii == 3 || ii == 5) target[1] = -14.0;
			if (ii == 4) target[1] = -18.0;
			target[0] = legpos1[ii][0];
			target[1] = legpos1[ii][1];
			target[2] = -10. + standheight;
			// given final target, turn into current target
			if (ssfrac < 0.5)
			{
				ssfrac2 = ssfrac*2.0;
				if (ii % 2 == 0)
				{
					target[0] = ssx0[ii] + ssfrac2*(target[0]-ssx0[ii]);
					target[1] = ssy0[ii] + ssfrac2*(target[1]-ssy0[ii]);
					target[2] = ssz0[ii] + ssfrac2*(target[2]-ssz0[ii]) + 
						2.0*pow(sin(3.1416*ssfrac2),2);
				} else {
					target[0] = ssx0[ii];
					target[1] = ssy0[ii];
					target[2] = ssz0[ii];
				}
			} else {
				ssfrac2 = (ssfrac-0.5)*2.0;
				if (ii % 2 == 0)
				{
					// don't modify targets
				} else {
					target[0] = ssx0[ii] + ssfrac2*(target[0]-ssx0[ii]);
					target[1] = ssy0[ii] + ssfrac2*(target[1]-ssy0[ii]);
					target[2] = ssz0[ii] + ssfrac2*(target[2]-ssz0[ii]) +
						2.0*pow(sin(3.1416*ssfrac2),2);
				}
			}
			IKSolve(ii,target);
		}
		if (sstime > SS_DURATION)
		{
			ssrunning = false;
			sstime = 0.0;
		}
	} else {
	

	// based on current turning, compute turning math
	if (fabs(smoothturning) <= TURN_TOL)
		turn_dist = tan((1.0-TURN_TOL)*3.1416/2.0)*50.;
	else if (fabs(smoothturning) > TURN_TOL)
		turn_dist = tan((1.0-smoothturning)*3.1416/2.0)*50.;
	// compute dist between turn_dist and farthest leg
	maxdist = 0.0;
	for (ii=0; ii<6; ii++)
	{
		dist = sqrt(pow(legpos1[ii][0],2) + pow(legpos1[ii][1]-turn_dist,2));
		if (dist > maxdist) maxdist = dist;
	}
	// each leg can only sweep so much, so use this farthest leg
	// to determine the angle of sweep that every leg must do
	maxsweep = 8.*sweepmodifier/maxdist;
	if (turn_dist < 0.0) maxsweep = -maxsweep;
	// maxsweep is the angle of sweep for every leg, in radians

	// increment dead-reckoning position
	// turning radius is "turn_dist"
	dr_ang += dt*speedmodifier*maxsweep*2.0*0.83775/fdf;
	if (dr_ang > PI) dr_ang -= 2.*PI;
	if (dr_ang < -PI) dr_ang += 2.*PI;
	dr_xpos += maxsweep*turn_dist*dt*speedmodifier*2.0*cos(dr_ang)*0.83775/fdf;
	dr_ypos += maxsweep*turn_dist*dt*speedmodifier*2.0*sin(dr_ang)*0.83775/fdf;

	// dr_ang has about 20% error, likely systematic
	// dr_xpos,dr_ypos have more like 5% error, also likely systematic

	// increment fake time
	time += dt*speedmodifier;
	if (time > 1.0) time -= 1.0;
	if (time < 0.0) time += 1.0;

	// loop through each leg to figure out where it should be right now
	for (ii=0; ii<6; ii++)
	{
		// where is this leg in the cycle of stepping?
		// the 0.5*ii is to completely de-sync legs
		// the other part is to adjust it more
		cycletime = fmod(time + 0.5*ii + (legpos[ii][0]-legpos[0][0])*0.0125, 1.0);
		
		// use bezier curve to either be up or down
		// b2d_walk_down goes between +/- 0.83775
		if (cycletime < fdf) b2d_walk_down.getPos(cycletime/fdf, &thtpos, &zpos);
		else b2d_walk_up.getPos((cycletime-fdf)/(1.-fdf), &thtpos, &zpos);
		// convert thtpos into angle?
		thtpos *= maxsweep;

		// convert rpos to xpos,ypos
		dist = sqrt(pow(legpos1[ii][0],2) + pow(legpos1[ii][1]-turn_dist,2));
		tht0 = atan2(legpos1[ii][1]-turn_dist,legpos1[ii][0]);
		xpos = dist*cos(thtpos+tht0);
		ypos = turn_dist + dist*sin(thtpos+tht0);

		// set up the IK target
		target[0] = xpos;
		target[1] = ypos;
		target[2] = -10.0 + zpos*3.0*legraise + standheight;
		if (standheight < 0.0) target[2] -= 1.7*zpos*standheight;


		// perform IK solve
		IKSolve(ii,target);
		// TODO: add error handling if IK fails to converge
	}

	}
	setServoAngles();
}