35 CordeModel::Config::Config(
const std::size_t res,
36 const double r,
const double d,
37 const double ym,
const double shm,
38 const double stm,
const double csc,
39 const double gt,
const double gr) :
52 throw std::invalid_argument(
"Corde string radius is not positive.");
56 throw std::invalid_argument(
"Corde String density is not positive.");
60 throw std::invalid_argument(
"String Young's Modulus is negative.");
64 throw std::invalid_argument(
"Shear Modulus is negative.");
68 throw std::invalid_argument(
"Stretch Modulus is negative.");
72 throw std::invalid_argument(
"Spring Constant is negative.");
76 throw std::invalid_argument(
"Damping Constant (position) is negative.");
80 throw std::invalid_argument(
"Damping Constant (rotation) is negative.");
90 btVector3 rodLength(pos2 - pos1);
91 btVector3 unitLength( rodLength / ((
double) m_config.resolution - 1) );
92 btVector3 massPos(pos1);
94 double unitMass = m_config.density * M_PI * pow( m_config.radius, 2) * unitLength.length();
96 CordePositionElement* currentPoint =
new CordePositionElement(massPos, unitMass);
98 m_massPoints.push_back(currentPoint);
100 std::cout << massPos << std::endl;
102 for (std::size_t i = 1; i < m_config.resolution; i++)
105 massPos += unitLength;
106 currentPoint =
new CordePositionElement(massPos, unitMass);
107 m_massPoints.push_back(currentPoint);
109 linkLengths.push_back(unitLength.length() * 1.0);
110 std::cout << massPos <<
" " << unitMass << std::endl;
113 CordeQuaternionElement* currentAngle =
new CordeQuaternionElement(quat1);
114 m_centerlines.push_back(currentAngle);
116 std::size_t n = m_config.resolution - 1;
117 for (std::size_t i = 1; i < n; i++)
119 currentAngle =
new CordeQuaternionElement(quat1.slerp(quat2, (
double) i / (
double) n) );
120 m_centerlines.push_back(currentAngle);
121 std::cout << currentAngle->q << std::endl;
122 quaternionShapes.push_back(unitLength.length());
128 CordeModel::~CordeModel()
130 for (std::size_t i = 0; i < m_massPoints.size(); i++)
132 delete m_massPoints[i];
134 for (std::size_t i = 0; i < m_centerlines.size(); i++)
136 delete m_centerlines[i];
140 void CordeModel::step (btScalar dt)
144 throw std::invalid_argument(
"Timestep is not positive.");
148 computeInternalForces();
149 unconstrainedMotion(dt);
153 size_t n = m_massPoints.size();
154 for (std::size_t i = 0; i < n; i++)
156 std::cout <<
"Position " << i <<
" " << m_massPoints[i]->pos << std::endl
157 <<
"Force " << i <<
" " << m_massPoints[i]->force << std::endl;
160 std::cout <<
"Quaternion " << i <<
" " << m_centerlines[i]->q << std::endl
161 <<
"Qdot " << i <<
" " << m_centerlines[i]->qdot << std::endl
162 <<
"Force " << i <<
" " << m_centerlines[i]->tprime << std::endl
163 <<
"Torque " << i <<
" " << m_centerlines[i]->torques << std::endl;
172 void CordeModel::computeConstants()
174 assert(computedStiffness.empty());
176 const double pir2 = M_PI * pow(m_config.radius, 2);
178 computedStiffness.push_back( m_config.StretchMod * pir2);
179 computedStiffness.push_back( m_config.YoungMod * pir2 / 4.0);
180 computedStiffness.push_back( m_config.YoungMod * pir2 / 4.0);
181 computedStiffness.push_back( m_config.ShearMod * pir2 / 2.0);
186 computedInertia.setValue(m_config.density * pir2 / 4.0,
187 m_config.density * pir2 / 4.0,
188 m_config.density * pir2 / 2.0);
192 assert(!computedInertia.fuzzyZero());
194 inverseInertia.setValue(1.0/computedInertia[0],
195 1.0/computedInertia[1],
196 1.0/computedInertia[2]);
203 void CordeModel::stepPrerequisites()
205 std::size_t n = m_massPoints.size();
206 for (std::size_t i = 0; i < n - 1; i++)
208 CordePositionElement* r_0 = m_massPoints[i];
209 r_0->force.setZero();
212 n = m_centerlines.size();
213 for (std::size_t i = 0; i < n - 1; i++)
215 CordeQuaternionElement* q_0 = m_centerlines[i];
216 q_0->tprime = btQuaternion(0.0, 0.0, 0.0, 0.0);
217 q_0->torques.setZero();
221 void CordeModel::computeInternalForces()
223 std::size_t n = m_massPoints.size() - 1;
226 for (std::size_t i = 0; i < n; i++)
228 CordePositionElement* r_0 = m_massPoints[i];
229 CordePositionElement* r_1 = m_massPoints[i + 1];
231 CordeQuaternionElement* quat_0 = m_centerlines[i];
234 const btScalar x1 = r_0->pos[0];
235 const btScalar y1 = r_0->pos[1];
236 const btScalar z1 = r_0->pos[2];
238 const btScalar x2 = r_1->pos[0];
239 const btScalar y2 = r_1->pos[1];
240 const btScalar z2 = r_1->pos[2];
243 const btScalar q11 = quat_0->q[0];
244 const btScalar q12 = quat_0->q[1];
245 const btScalar q13 = quat_0->q[2];
246 const btScalar q14 = quat_0->q[3];
249 const btVector3 posDiff = r_0->pos - r_1->pos;
250 const btVector3 velDiff = r_0->vel - r_1->vel;
251 const btScalar posNorm = posDiff.length();
252 const btScalar posNorm_2 = posDiff.length2();
253 const btVector3 director( (2.0 * (q11 * q13 + q12 * q14)),
254 (2.0 * (q12 * q13 - q11 * q14)),
255 ( -1.0 * q11 * q11 - q12 * q12 + q13 * q13 + q14 * q14));
261 const btScalar spring_common = computedStiffness[0] *
262 (linkLengths[i] - posNorm) / (linkLengths[i] * posNorm);
264 const btScalar diss_common = m_config.
gammaT *
265 posNorm_2 * posDiff.dot(velDiff) / pow (linkLengths[i] , 5);
268 const btScalar quat_cons_x = m_config.ConsSpringConst * linkLengths[i] *
269 ( director[2] * (x1 - x2) * (z1 - z2) - director[0] * ( pow( posDiff[1], 2) + pow( posDiff[2], 2) )
270 + director[1] * (x1 - x2) * (y1 - y2) ) / ( pow (posNorm, 3) );
273 const btScalar quat_cons_y = m_config.ConsSpringConst * linkLengths[i] *
274 ( -1.0 * director[2] * (y1 - y2) * (z1 - z2) + director[1] * ( pow( posDiff[0], 2) + pow( posDiff[2], 2) )
275 - director[0] * (x1 - x2) * (z1 - z2) ) / ( pow (posNorm, 3) );
278 const btScalar quat_cons_z = m_config.ConsSpringConst * linkLengths[i] *
279 ( -1.0 * director[0] * (y1 - y2) * (z1 - z2) + director[2] * ( pow( posDiff[0], 2) + pow( posDiff[1], 2) )
280 - director[1] * (x1 - x2) * (z1 - z2) ) / ( pow (posNorm, 3) );
282 r_0->force[0] += -1.0 * (x1 - x2) * (spring_common + diss_common);
284 r_1->force[0] += (x1 - x2) * (spring_common + diss_common);
287 r_0->force[1] += -1.0 * (y1 - y2) * (spring_common + diss_common);
289 r_1->force[1] += (y1 - y2) * (spring_common + diss_common);
292 r_0->force[2] += -1.0 * (z1 - z2) * (spring_common + diss_common);
294 r_1->force[2] += (z1 - z2) * (spring_common + diss_common);
299 r_1->force[0] += quat_cons_x;
302 r_1->force[1] += quat_cons_y;
305 r_1->force[2] += quat_cons_z;
309 r_0->force[0] -= quat_cons_x;
311 r_0->force[1] -= quat_cons_y;
313 r_0->force[2] -= quat_cons_z;
317 r_0->force[0] -= quat_cons_x;
318 r_1->force[0] += quat_cons_x;
320 r_0->force[1] -= quat_cons_y;
321 r_1->force[1] += quat_cons_y;
323 r_0->force[2] -= quat_cons_z;
324 r_1->force[2] += quat_cons_z;
327 #if (0) // Original derivation
329 quat_0->tprime[0] += 2.0 * m_config.ConsSpringConst * linkLengths[i]
330 * ( q11 * quat_0->q.length2() + (q13 * posDiff[0] -
331 q14 * posDiff[1] - q11 * posDiff[2]) / posNorm);
333 quat_0->tprime[1] += 2.0 * m_config.ConsSpringConst * linkLengths[i]
334 * ( q12 * quat_0->q.length2() + (q14 * posDiff[0] +
335 q13 * posDiff[1] - q12 * posDiff[2]) / posNorm);
337 quat_0->tprime[2] += 2.0 * m_config.ConsSpringConst * linkLengths[i]
338 * ( q13 * quat_0->q.length2() + (q11 * posDiff[0] +
339 q12 * posDiff[1] + q13 * posDiff[2]) / posNorm);
341 quat_0->tprime[3] += 2.0 * m_config.ConsSpringConst * linkLengths[i]
342 * ( q14 * quat_0->q.length2() + (q12 * posDiff[0] -
343 q11 * posDiff[1] + q14 * posDiff[2]) / posNorm);
344 #else // quat_0->q.length2() should always be 1, but sometimes numerical precision renders it slightly greater
346 quat_0->tprime[0] += 2.0 * m_config.ConsSpringConst * linkLengths[i]
347 * ( q11 + (q13 * posDiff[0] -
348 q14 * posDiff[1] - q11 * posDiff[2]) / posNorm);
350 quat_0->tprime[1] += 2.0 * m_config.ConsSpringConst * linkLengths[i]
351 * ( q12 + (q14 * posDiff[0] +
352 q13 * posDiff[1] - q12 * posDiff[2]) / posNorm);
354 quat_0->tprime[2] += 2.0 * m_config.ConsSpringConst * linkLengths[i]
355 * ( q13 + (q11 * posDiff[0] +
356 q12 * posDiff[1] + q13 * posDiff[2]) / posNorm);
358 quat_0->tprime[3] += 2.0 * m_config.ConsSpringConst * linkLengths[i]
359 * ( q14 + (q12 * posDiff[0] -
360 q11 * posDiff[1] + q14 * posDiff[2]) / posNorm);
364 n = m_centerlines.size() - 1;
367 for (std::size_t i = 0; i < n; i++)
369 CordeQuaternionElement* quat_0 = m_centerlines[i];
370 CordeQuaternionElement* quat_1 = m_centerlines[i + 1];
373 const btScalar q11 = quat_0->q[0];
374 const btScalar q12 = quat_0->q[1];
375 const btScalar q13 = quat_0->q[2];
376 const btScalar q14 = quat_0->q[3];
378 const btScalar q21 = quat_1->q[0];
379 const btScalar q22 = quat_1->q[1];
380 const btScalar q23 = quat_1->q[2];
381 const btScalar q24 = quat_1->q[3];
383 const btScalar qdot11 = quat_0->qdot[0];
384 const btScalar qdot12 = quat_0->qdot[1];
385 const btScalar qdot13 = quat_0->qdot[2];
386 const btScalar qdot14 = quat_0->qdot[3];
388 const btScalar qdot21 = quat_1->qdot[0];
389 const btScalar qdot22 = quat_1->qdot[1];
390 const btScalar qdot23 = quat_1->qdot[2];
391 const btScalar qdot24 = quat_1->qdot[3];
393 const btScalar k1 = computedStiffness[1];
394 const btScalar k2 = computedStiffness[2];
395 const btScalar k3 = computedStiffness[3];
404 const btScalar stiffness_common = 4.0 / quaternionShapes[i] *
405 pow(quaternionShapes[i] - 1.0, 2);
407 const btScalar q11_stiffness = stiffness_common *
408 (k1 * q24 * (q11 * q24 + q12 * q23 - q13 * q22 - q14 * q21) +
409 k2 * q23 * (q11 * q23 - q12 * q24 - q13 * q21 + q14 * q22) +
410 k3 * q22 * (q11 * q22 - q12 * q21 + q13 * q24 - q14 * q23));
412 const btScalar q12_stiffness = stiffness_common *
413 (k1 * q23 * (q12 * q23 + q11 * q24 - q13 * q22 - q14 * q21) +
414 k2 * q24 * (q12 * q24 - q11 * q23 + q13 * q21 - q14 * q22) +
415 k3 * q21 * (q12 * q21 - q11 * q22 - q13 * q24 + q14 * q23));
417 const btScalar q13_stiffness = stiffness_common *
418 (k1 * q22 * (q13 * q22 - q11 * q24 - q12 * q23 + q14 * q21) +
419 k2 * q21 * (q13 * q21 - q11 * q23 + q12 * q24 - q14 * q22) +
420 k3 * q24 * (q13 * q24 + q11 * q22 - q12 * q21 - q14 * q23));
422 const btScalar q14_stiffness = stiffness_common *
423 (k1 * q21 * (q14 * q21 - q11 * q24 - q12 * q23 + q13 * q22) +
424 k2 * q22 * (q14 * q22 + q11 * q23 - q12 * q24 - q13 * q21) +
425 k3 * q23 * (q14 * q23 - q11 * q22 + q12 * q21 - q13 * q24));
427 const btScalar q21_stiffness = stiffness_common *
428 (k1 * q14 * (q14 * q21 - q11 * q24 - q12 * q23 + q13 * q22) +
429 k2 * q13 * (q13 * q21 - q11 * q23 + q12 * q24 - q14 * q22) +
430 k3 * q12 * (q12 * q21 - q11 * q22 + q14 * q23 - q13 * q24));
432 const btScalar q22_stiffness = stiffness_common *
433 (k1 * q13 * (q13 * q22 - q11 * q24 - q12 * q23 + q14 * q21) +
434 k2 * q14 * (q14 * q22 + q11 * q23 - q12 * q24 - q13 * q21) +
435 k3 * q11 * (q11 * q22 - q12 * q21 + q13 * q24 - q14 * q23));
437 const btScalar q23_stiffness = stiffness_common *
438 (k1 * q12 * (q12 * q23 + q11 * q24 - q13 * q22 - q14 * q21) +
439 k2 * q11 * (q11 * q23 - q13 * q21 - q12 * q24 + q14 * q22) +
440 k3 * q14 * (q14 * q23 - q11 * q22 + q12 * q21 - q13 * q24));
442 const btScalar q24_stiffness = stiffness_common *
443 (k1 * q11 * (q11 * q24 + q12 * q23 - q13 * q22 - q14 * q21) +
444 k2 * q12 * (q12 * q24 - q11 * q23 + q13 * q21 - q14 * q22) +
445 k3 * q13 * (q13 * q24 + q11 * q22 - q12 * q21 - q14 * q23));
448 const btScalar damping_common = 4.0 * m_config.gammaR / quaternionShapes[i];
450 const btScalar q11_damping = damping_common *
451 (q12 * (q12 * qdot11 - q11 * qdot12 + q21 * qdot22 - q22 * qdot21 - q23 * qdot24 + q24 * qdot23) +
452 q13 * (q13 * qdot11 - q11 * qdot13 + q21 * qdot23 + q22 * qdot24 - q23 * qdot21 - q24 * qdot22) +
453 q14 * (q14 * qdot11 - q11 * qdot14 + q21 * qdot24 - q22 * qdot23 + q23 * qdot22 - q24 * qdot21));
455 const btScalar q12_damping = damping_common *
456 (q11 * (q11 * qdot12 - q12 * qdot11 - q21 * qdot22 + q22 * qdot21 + q23 * qdot24 - q24 * qdot23) +
457 q13 * (q13 * qdot12 - q13 * qdot13 - q21 * qdot24 + q22 * qdot23 - q23 * qdot22 + q24 * qdot21) +
458 q14 * (q14 * qdot12 - q14 * qdot14 + q21 * qdot23 + q22 * qdot24 - q23 * qdot21 - q24 * qdot22));
460 const btScalar q13_damping = damping_common *
461 (q11 * (q11 * qdot13 - q13 * qdot11 - q21 * qdot23 - q22 * qdot24 + q23 * qdot21 + q24 * qdot22) +
462 q12 * (q12 * qdot13 - q13 * qdot12 + q21 * qdot24 - q22 * qdot23 + q23 * qdot22 - q24 * qdot21) +
463 q14 * (q14 * qdot13 - q13 * qdot14 - q21 * qdot22 + q22 * qdot21 + q23 * qdot24 - q24 * qdot23));
465 const btScalar q14_damping = damping_common *
466 (q11 * (q11 * qdot14 - q14 * qdot11 - q21 * qdot24 + q22 * qdot23 - q23 * qdot22 + q24 * qdot21) +
467 q12 * (q12 * qdot14 - q14 * qdot12 - q21 * qdot23 - q22 * qdot24 + q23 * qdot21 + q24 * qdot22) +
468 q13 * (q13 * qdot14 - q14 * qdot13 + q21 * qdot22 - q22 * qdot21 - q23 * qdot24 + q24 * qdot23));
470 const btScalar q21_damping = damping_common *
471 (q22 * (q22 * qdot21 + q11 * qdot12 - q12 * qdot11 - q13 * qdot14 + q14 * qdot13 - q21 * qdot22) +
472 q23 * (q23 * qdot21 + q11 * qdot13 + q12 * qdot14 - q13 * qdot11 - q14 * qdot12 - q21 * qdot23) +
473 q24 * (q24 * qdot21 + q11 * qdot14 - q12 * qdot13 + q13 * qdot12 - q14 * qdot11 - q21 * qdot24));
475 const btScalar q22_damping = damping_common *
476 (q21 * (q21 * qdot22 - q11 * qdot12 + q12 * qdot11 + q13 * qdot14 - q14 * qdot13 - q22 * qdot21) +
477 q23 * (q23 * qdot22 - q11 * qdot14 + q12 * qdot13 - q13 * qdot12 + q14 * qdot11 - q22 * qdot23) +
478 q24 * (q24 * qdot22 + q11 * qdot13 + q12 * qdot14 - q13 * qdot11 - q14 * qdot12 - q22 * qdot24));
480 const btScalar q23_damping = damping_common *
481 (q21 * (q21 * qdot23 - q11 * qdot13 + q13 * qdot11 - q12 * qdot14 + q14 * qdot12 - q23 * qdot21) +
482 q22 * (q22 * qdot23 + q11 * qdot14 - q12 * qdot13 + q13 * qdot12 - q14 * qdot11 - q22 * qdot22) +
483 q24 * (q24 * qdot23 - q11 * qdot12 + q12 * qdot11 + q13 * qdot14 - q14 * qdot13 - q23 * qdot24));
485 const btScalar q24_damping = damping_common *
486 (q21 * (q21 * qdot24 - q11 * qdot14 + q12 * qdot13 - q13 * qdot12 + q14 * qdot11 - q24 * qdot21) +
487 q22 * (q21 * qdot24 - q11 * qdot13 - q12 * qdot14 + q13 * qdot11 + q14 * qdot12 - q24 * qdot22) +
488 q23 * (q23 * qdot24 + q11 * qdot12 - q12 * qdot11 - q13 * qdot14 + q14 * qdot13 - q24 * qdot23));
491 quat_0->tprime[0] += q11_stiffness + q11_damping;
493 quat_1->tprime[0] += q21_stiffness + q21_damping;
495 quat_0->tprime[1] += q12_stiffness + q12_damping;
497 quat_1->tprime[1] += q22_stiffness + q22_damping;
499 quat_0->tprime[2] += q13_stiffness + q13_damping;
501 quat_1->tprime[2] += q23_stiffness + q23_damping;
503 quat_0->tprime[3] += q14_stiffness + q14_damping;
505 quat_1->tprime[3] += q24_stiffness + q24_damping;
510 void CordeModel::unconstrainedMotion(
double dt)
512 for (std::size_t i = 0; i < m_massPoints.size(); i++)
514 CordePositionElement* p_0 = m_massPoints[i];
516 p_0->vel += dt / p_0->mass * p_0->force;
518 p_0->pos += dt * p_0->vel;
520 for (std::size_t i = 0; i < m_centerlines.size(); i++)
523 CordeQuaternionElement* quat_0 = m_centerlines[i];
524 quat_0->transposeTorques();
526 const btVector3 omega = quat_0->omega;
528 quat_0->omega += inverseInertia * (quat_0->torques -
529 omega.cross(computedInertia * omega)) * dt;
530 quat_0->updateQDot();
531 quat_0->q = (quat_0->qdot*dt + quat_0->q).normalize();
535 CordeModel::CordePositionElement::CordePositionElement(btVector3 p1,
double m) :
538 force(0.0, 0.0, 0.0),
543 throw std::invalid_argument(
"Mass is negative.");
547 CordeModel::CordeQuaternionElement::CordeQuaternionElement(btQuaternion q1) :
549 qdot(0.0, 0.0, 0.0, 0.0),
550 tprime(0.0, 0.0, 0.0, 0.0),
551 torques(0.0, 0.0, 0.0),
557 void CordeModel::CordeQuaternionElement::transposeTorques()
559 torques[0] += 1.0/2.0 * (q[0] * tprime[2] - q[2] * tprime[0] - q[1] * tprime[3] + q[3] * tprime[1]);
560 torques[1] += 1.0/2.0 * (q[1] * tprime[0] - q[0] * tprime[1] - q[2] * tprime[3] + q[3] * tprime[2]);
561 torques[2] += 1.0/2.0 * (q[0] * tprime[0] + q[1] * tprime[1] + q[2] * tprime[2] + q[3] * tprime[3]);
564 void CordeModel::CordeQuaternionElement::updateQDot()
566 qdot[0] = 1.0/2.0 * (q[0] * omega[2] + q[1] * omega[1] - q[2] * omega[0]);
567 qdot[1] = 1.0/2.0 * (q[1] * omega[2] - q[0] * omega[1] + q[3] * omega[0]);
568 qdot[2] = 1.0/2.0 * (q[0] * omega[0] + q[2] * omega[2] + q[3] * omega[1]);
569 qdot[3] = 1.0/2.0 * (q[3] * omega[2] - q[2] * omega[1] - q[1] * omega[0]);
573 bool CordeModel::invariant()
575 return (m_massPoints.size() == m_centerlines.size() + 1)
576 && (m_centerlines.size() == linkLengths.size())
577 && (linkLengths.size() == quaternionShapes.size() + 1)
578 && (computedStiffness.size() == 4);
Defines structure for the Corde softbody String Model.
CordeModel(btVector3 pos1, btVector3 pos2, btQuaternion quat1, btQuaternion quat2, CordeModel::Config &Config)
Rand seeding simular to the evolution and terrain classes.