关节运动模拟 in ODE

首先把上次的模拟结果全部画到了一张图里, 可以看一下模拟效果.

还是很有趣.




这次是可控制的关节运动, 不像上次一样全部是纯自然的动作了.

不过这次没法保证代码和结果是完全对的, 参数太多,没太多时间挨个改...


先来看效果





这些展示了关节重心的移动过程, 基本上是在很疯狂的旋转.

第一个关节设定了和大地的fixJoint却还能小幅旋转, 真是神奇....




总之先放在这吧


Mac-mini:ode$ cat example6.d
import std.stdio;
import ode;

static dWorldID world;
static dSpaceID space;
static dJointGroupID contactgroup;

struct cot{
	dBodyID link;
	dJointID joint;
	dReal l,r,theta;
	dReal x,y,z;
	dReal mass;
	dReal anchorx,anchory,anchorz;
	dReal axisx, axisy, axisz;
}

cot*[] links;

const 
	double k1 = 10., fMax = 100.;
void control(){
	foreach(l;links[1..$]){
		double tmp = l.theta - dJointGetHingeAngle(l.joint);
		dJointSetHingeParam(l.joint, dParamVel, k1*tmp);
		dJointSetHingeParam(l.joint, dParamFMax, fMax);
	}
}

extern(System) void nearCallBack(void* date, dGeomID o1, dGeomID o2){
	const maxContacts = 10;
	dContact[maxContacts] contact;
	int numc = dCollide(o1, o2, maxContacts, &contact[0].geom, dContact.sizeof);
	if (numc>0) {
		for (uint i = 0; i< numc; i++) {
			with (contact[i].surface){
				mode = dContactSoftCFM | dContactSoftERP | dContactApprox1;
				mu = dInfinity;
				soft_cfm = 1e-8;
				soft_erp = 1.;
			}
			dJointID c = dJointCreateContact(world, contactgroup, &contact[i]);
			dJointAttach(c, dGeomGetBody(contact[i].geom.g1), dGeomGetBody(contact[i].geom.g2));
		}
	}
}

void simLoop(){
	control();
	dSpaceCollide(space, null ,&nearCallBack);
	dWorldStep(world, 0.01);
	dJointGroupEmpty(contactgroup);
	dReal* pos;
	foreach(k,b;links){
		pos = dBodyGetPosition(b.link);
		foreach(i;0..3) writef("%.6f\t",*(pos+i));
	}
	writeln();
}

void create(cot* b){
	b.link = dBodyCreate(world);
	dMass m1;
	dMassSetZero(&m1);
	dMassSetCylinderTotal(&m1,b.mass,2,b.r, b.l);
	dBodySetMass(b.link,&m1);
	dBodySetPosition(b.link, b.x,b.y,b.z);
}

void createFixedJoint(cot* b1, cot* b2){
		b1.joint = dJointCreateFixed(world,null);
		if (!b2){ dJointAttach(b1.joint, b1.link, null);}
		else{ dJointAttach(b1.joint,b1.link,b2.link); }
		dJointSetFixed(b1.joint);    
}

void createHinge(cot* a1, cot* b1){
	b1.joint = dJointCreateHinge(world, null);
	dJointAttach(b1.joint,a1.link, b1.link); 
	dJointSetHingeAnchor(b1.joint, b1.anchorx, b1.anchory, b1.anchorz);
	dJointSetHingeAxis(b1.joint, b1.axisx, b1.axisy, b1.axisz);
}

/*
struct cot{
	dBodyID link;
	dJointID joint;
	dReal l,r,theta;
	dReal x,y,z;
	dReal mass;
	dReal anchorx,anchory,anchorz;
	dReal axisx, axisy, axisz;
}*/

void main(){
	links ~= new cot(null,null,0.1,0.2,0,0,0,0.05,10,0,0,0,0,0,1);
	links ~= new cot(null,null,0.9,0.04,90,0.0,0,0.5,2,0,0,0.1,0,0,1);
	links ~= new cot(null,null,1,0.04,120,0,0.0,1.5,2,0,0,1,0,1,0);
	links ~= new cot(null,null,1,0.04,70,0,0,2.55,2,0,0,2,0,1,0);
	dInitODE();
	world = dWorldCreate();
	space = dHashSpaceCreate(null);
	contactgroup = dJointGroupCreate(0);
	dWorldSetERP(world, 0.5);
	dWorldSetCFM(world, 1e-3);

	dWorldSetGravity(world, 0, 0, -9.8);

	foreach(b;links) create(b);
	createFixedJoint(links[0], null);
	for(uint i=1;i


你可能感兴趣的:(杂谈)