Skip to content

Commit 79e96de

Browse files
Make requested changes
1 parent 79fb57a commit 79e96de

File tree

10 files changed

+173
-280
lines changed

10 files changed

+173
-280
lines changed

tesseract/tesseract_collision/include/tesseract_collision/bullet/bullet_utils.h

Lines changed: 114 additions & 228 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,28 @@ GetAverageSupport(const btConvexShape* shape, const btVector3& localNormal, floa
333333
}
334334
}
335335

336+
/**
337+
* @brief This transversus the parent tree to find the base object and return its world transform
338+
* This should be the links transform and it should only need to transverse twice at max.
339+
* @param cow Bullet collision object wrapper.
340+
* @return Transform of link in world coordinates
341+
*/
342+
inline btTransform getLinkTransformFromCOW(const btCollisionObjectWrapper* cow)
343+
{
344+
if (cow->m_parent)
345+
{
346+
if (cow->m_parent->m_parent)
347+
{
348+
assert(cow->m_parent->m_parent->m_parent == nullptr);
349+
return cow->m_parent->m_parent->getWorldTransform();
350+
}
351+
352+
return cow->m_parent->getWorldTransform();
353+
}
354+
355+
return cow->getWorldTransform();
356+
}
357+
336358
/**
337359
* @brief This is used to check if a collision check is required between the provided two collision objects
338360
* @param cow1 The first collision object
@@ -372,38 +394,10 @@ inline btScalar addDiscreteSingleResult(btManifoldPoint& cp,
372394

373395
// }
374396

375-
btTransform tf0, tf1, tf0_inv, tf1_inv;
376-
tf0 = colObj0Wrap->getWorldTransform();
377-
tf1 = colObj1Wrap->getWorldTransform();
378-
379-
if (colObj0Wrap->m_parent)
380-
{
381-
if (colObj0Wrap->m_parent->m_parent)
382-
{
383-
tf0 = colObj0Wrap->m_parent->m_parent->getWorldTransform();
384-
assert(colObj0Wrap->m_parent->m_parent->m_parent == nullptr);
385-
}
386-
else
387-
{
388-
tf0 = colObj0Wrap->m_parent->getWorldTransform();
389-
}
390-
}
391-
392-
if (colObj1Wrap->m_parent)
393-
{
394-
if (colObj1Wrap->m_parent->m_parent)
395-
{
396-
tf1 = colObj1Wrap->m_parent->m_parent->getWorldTransform();
397-
assert(colObj1Wrap->m_parent->m_parent->m_parent == nullptr);
398-
}
399-
else
400-
{
401-
tf1 = colObj1Wrap->m_parent->getWorldTransform();
402-
}
403-
}
404-
405-
tf0_inv = tf0.inverse();
406-
tf1_inv = tf1.inverse();
397+
btTransform tf0 = getLinkTransformFromCOW(colObj0Wrap);
398+
btTransform tf1 = getLinkTransformFromCOW(colObj1Wrap);
399+
btTransform tf0_inv = tf0.inverse();
400+
btTransform tf1_inv = tf1.inverse();
407401

408402
ContactResult contact;
409403
contact.link_names[0] = cd0->getName();
@@ -431,6 +425,86 @@ inline btScalar addDiscreteSingleResult(btManifoldPoint& cp,
431425
return 1;
432426
}
433427

428+
/**
429+
* @brief Calculate the continuous contact data for casted collision shape
430+
* @param col Contact results
431+
* @param cow Bullet Collision Object Wrapper
432+
* @param pt_world Casted contact point in world coordinates
433+
* @param normal_world Casted normal to move shape out of collision in world coordinates
434+
* @param link_tf_inv The links world transform inverse
435+
* @param link_index The link index in teh ContactResults the shape is associated with
436+
*/
437+
inline void calculateContinuousData(ContactResult* col,
438+
const btCollisionObjectWrapper* cow,
439+
const btVector3& pt_world,
440+
const btVector3& normal_world,
441+
const btTransform& link_tf_inv,
442+
size_t link_index)
443+
{
444+
assert(dynamic_cast<const CastHullShape*>(cow->getCollisionShape()) != nullptr);
445+
const auto* shape = static_cast<const CastHullShape*>(cow->getCollisionShape());
446+
assert(shape != nullptr);
447+
448+
// Get the start and final location of the shape
449+
btTransform shape_tfWorld0 = cow->getWorldTransform();
450+
btTransform shape_tfWorld1 = cow->getWorldTransform() * shape->m_t01;
451+
452+
// Given the shapes final location calculate the links transform at the final location
453+
Eigen::Isometry3d s = col->transform[link_index].inverse() * convertBtToEigen(shape_tfWorld0);
454+
col->cc_transform[link_index] = convertBtToEigen(shape_tfWorld1) * s.inverse();
455+
456+
// Get the normal in the local shapes coordinate system at start and final location
457+
btVector3 shape_normalLocal0 = normal_world * shape_tfWorld0.getBasis();
458+
btVector3 shape_normalLocal1 = normal_world * shape_tfWorld1.getBasis();
459+
460+
// Calculate the contact point at the start location using the casted normal vector in thapes local coordinate system
461+
btVector3 shape_ptLocal0;
462+
float shape_localsup0;
463+
GetAverageSupport(shape->m_shape, shape_normalLocal0, shape_localsup0, shape_ptLocal0);
464+
btVector3 shape_ptWorld0 = shape_tfWorld0 * shape_ptLocal0;
465+
466+
// Calculate the contact point at the final location using the casted normal vector in thapes local coordinate system
467+
btVector3 shape_ptLocal1;
468+
float shape_localsup1;
469+
GetAverageSupport(shape->m_shape, shape_normalLocal1, shape_localsup1, shape_ptLocal1);
470+
btVector3 shape_ptWorld1 = shape_tfWorld1 * shape_ptLocal1;
471+
472+
float shape_sup0 = normal_world.dot(shape_ptWorld0);
473+
float shape_sup1 = normal_world.dot(shape_ptWorld1);
474+
475+
// TODO: this section is potentially problematic. think hard about the math
476+
if (shape_sup0 - shape_sup1 > BULLET_SUPPORT_FUNC_TOLERANCE)
477+
{
478+
col->cc_time[link_index] = 0;
479+
col->cc_type[link_index] = ContinuousCollisionType::CCType_Time0;
480+
}
481+
else if (shape_sup1 - shape_sup0 > BULLET_SUPPORT_FUNC_TOLERANCE)
482+
{
483+
col->cc_time[link_index] = 1;
484+
col->cc_type[link_index] = ContinuousCollisionType::CCType_Time1;
485+
}
486+
else
487+
{
488+
// Given the contact point at the start and final location along with the casted contact point
489+
// the time between 0 and 1 can be calculated along the path between the start and final location contact occurs.
490+
float l0c = (pt_world - shape_ptWorld0).length();
491+
float l1c = (pt_world - shape_ptWorld1).length();
492+
493+
col->nearest_points_local[link_index] =
494+
convertBtToEigen(link_tf_inv * (shape_tfWorld0 * ((shape_ptLocal0 + shape_ptLocal1) / 2.0)));
495+
col->cc_type[link_index] = ContinuousCollisionType::CCType_Between;
496+
497+
if (l0c + l1c < BULLET_LENGTH_TOLERANCE)
498+
{
499+
col->cc_time[link_index] = .5;
500+
}
501+
else
502+
{
503+
col->cc_time[link_index] = static_cast<double>(l0c / (l0c + l1c));
504+
}
505+
}
506+
}
507+
434508
inline btScalar addCastSingleResult(btManifoldPoint& cp,
435509
const btCollisionObjectWrapper* colObj0Wrap,
436510
int /*index0*/,
@@ -458,38 +532,10 @@ inline btScalar addCastSingleResult(btManifoldPoint& cp,
458532
// return 0;
459533
// }
460534

461-
btTransform tf0, tf1, tf0_inv, tf1_inv;
462-
tf0 = colObj0Wrap->getWorldTransform();
463-
tf1 = colObj1Wrap->getWorldTransform();
464-
465-
if (colObj0Wrap->m_parent)
466-
{
467-
if (colObj0Wrap->m_parent->m_parent)
468-
{
469-
tf0 = colObj0Wrap->m_parent->m_parent->getWorldTransform();
470-
assert(colObj0Wrap->m_parent->m_parent->m_parent == nullptr);
471-
}
472-
else
473-
{
474-
tf0 = colObj0Wrap->m_parent->getWorldTransform();
475-
}
476-
}
477-
478-
if (colObj1Wrap->m_parent)
479-
{
480-
if (colObj1Wrap->m_parent->m_parent)
481-
{
482-
tf1 = colObj1Wrap->m_parent->m_parent->getWorldTransform();
483-
assert(colObj1Wrap->m_parent->m_parent->m_parent == nullptr);
484-
}
485-
else
486-
{
487-
tf1 = colObj1Wrap->m_parent->getWorldTransform();
488-
}
489-
}
490-
491-
tf0_inv = tf0.inverse();
492-
tf1_inv = tf1.inverse();
535+
btTransform tf0 = getLinkTransformFromCOW(colObj0Wrap);
536+
btTransform tf1 = getLinkTransformFromCOW(colObj1Wrap);
537+
btTransform tf0_inv = tf0.inverse();
538+
btTransform tf1_inv = tf1.inverse();
493539

494540
ContactResult contact;
495541
contact.link_names[0] = cd0->getName();
@@ -518,121 +564,16 @@ inline btScalar addCastSingleResult(btManifoldPoint& cp,
518564
if (cd0->m_collisionFilterGroup == btBroadphaseProxy::KinematicFilter &&
519565
cd1->m_collisionFilterGroup == btBroadphaseProxy::KinematicFilter)
520566
{
521-
assert(dynamic_cast<const CastHullShape*>(colObj0Wrap->getCollisionShape()) != nullptr);
522-
const auto* shape0 = static_cast<const CastHullShape*>(colObj0Wrap->getCollisionShape());
523-
assert(shape0 != nullptr);
524-
525-
assert(dynamic_cast<const CastHullShape*>(colObj1Wrap->getCollisionShape()) != nullptr);
526-
const auto* shape1 = static_cast<const CastHullShape*>(colObj1Wrap->getCollisionShape());
527-
assert(shape1 != nullptr);
528-
529-
btVector3 shape0_normalWorld = -1 * cp.m_normalWorldOnB;
530-
btTransform shape0_tfWorld0 = colObj0Wrap->getWorldTransform();
531-
btTransform shape0_tfWorld1 = colObj0Wrap->getWorldTransform() * shape0->m_t01;
532-
btVector3 shape1_normalWorld = cp.m_normalWorldOnB;
533-
btTransform shape1_tfWorld0 = colObj1Wrap->getWorldTransform();
534-
btTransform shape1_tfWorld1 = colObj1Wrap->getWorldTransform() * shape1->m_t01;
535-
536-
Eigen::Isometry3d s0 = col->transform[0].inverse() * convertBtToEigen(shape0_tfWorld0);
537-
Eigen::Isometry3d s1 = col->transform[1].inverse() * convertBtToEigen(shape1_tfWorld0);
538-
col->cc_transform[0] = convertBtToEigen(shape0_tfWorld1) * s0.inverse();
539-
col->cc_transform[1] = convertBtToEigen(shape1_tfWorld1) * s1.inverse();
540-
541-
btVector3 shape0_normalLocal0 = shape0_normalWorld * shape0_tfWorld0.getBasis();
542-
btVector3 shape0_normalLocal1 = shape0_normalWorld * shape0_tfWorld1.getBasis();
543-
btVector3 shape1_normalLocal0 = shape1_normalWorld * shape1_tfWorld0.getBasis();
544-
btVector3 shape1_normalLocal1 = shape1_normalWorld * shape1_tfWorld1.getBasis();
545-
546-
btVector3 shape0_ptLocal0;
547-
float shape0_localsup0;
548-
GetAverageSupport(shape0->m_shape, shape0_normalLocal0, shape0_localsup0, shape0_ptLocal0);
549-
btVector3 shape0_ptWorld0 = shape0_tfWorld0 * shape0_ptLocal0;
550-
btVector3 shape0_ptLocal1;
551-
float shape0_localsup1;
552-
GetAverageSupport(shape0->m_shape, shape0_normalLocal1, shape0_localsup1, shape0_ptLocal1);
553-
btVector3 shape0_ptWorld1 = shape0_tfWorld1 * shape0_ptLocal1;
554-
555-
btVector3 shape1_ptLocal0;
556-
float shape1_localsup0;
557-
GetAverageSupport(shape1->m_shape, shape1_normalLocal0, shape1_localsup0, shape1_ptLocal0);
558-
btVector3 shape1_ptWorld0 = shape1_tfWorld0 * shape1_ptLocal0;
559-
btVector3 shape1_ptLocal1;
560-
float shape1_localsup1;
561-
GetAverageSupport(shape1->m_shape, shape1_normalLocal1, shape1_localsup1, shape1_ptLocal1);
562-
btVector3 shape1_ptWorld1 = shape1_tfWorld1 * shape1_ptLocal1;
563-
564-
float shape0_sup0 = shape0_normalWorld.dot(shape0_ptWorld0);
565-
float shape0_sup1 = shape0_normalWorld.dot(shape0_ptWorld1);
566-
float shape1_sup0 = shape1_normalWorld.dot(shape1_ptWorld0);
567-
float shape1_sup1 = shape1_normalWorld.dot(shape1_ptWorld1);
568-
569-
// TODO: this section is potentially problematic. think hard about the math
570-
if (shape0_sup0 - shape0_sup1 > BULLET_SUPPORT_FUNC_TOLERANCE)
571-
{
572-
col->cc_time[0] = 0;
573-
col->cc_type[0] = ContinouseCollisionType::CCType_Time0;
574-
}
575-
else if (shape0_sup1 - shape0_sup0 > BULLET_SUPPORT_FUNC_TOLERANCE)
576-
{
577-
col->cc_time[0] = 1;
578-
col->cc_type[0] = ContinouseCollisionType::CCType_Time1;
579-
}
580-
else
581-
{
582-
float l0c = (cp.m_positionWorldOnA - shape0_ptWorld0).length();
583-
float l1c = (cp.m_positionWorldOnA - shape0_ptWorld1).length();
584-
585-
col->nearest_points_local[0] =
586-
convertBtToEigen(tf0_inv * (shape0_tfWorld0 * ((shape0_ptLocal0 + shape0_ptLocal1) / 2.0)));
587-
col->cc_type[0] = ContinouseCollisionType::CCType_Between;
588-
589-
if (l0c + l1c < BULLET_LENGTH_TOLERANCE)
590-
{
591-
col->cc_time[0] = .5;
592-
}
593-
else
594-
{
595-
col->cc_time[0] = static_cast<double>(l0c / (l0c + l1c));
596-
}
597-
}
598-
599-
// TODO: this section is potentially problematic. think hard about the math
600-
if (shape1_sup0 - shape1_sup1 > BULLET_SUPPORT_FUNC_TOLERANCE)
601-
{
602-
col->cc_time[1] = 0;
603-
col->cc_type[1] = ContinouseCollisionType::CCType_Time0;
604-
}
605-
else if (shape1_sup1 - shape1_sup0 > BULLET_SUPPORT_FUNC_TOLERANCE)
606-
{
607-
col->cc_time[1] = 1;
608-
col->cc_type[1] = ContinouseCollisionType::CCType_Time1;
609-
}
610-
else
611-
{
612-
float l0c = (cp.m_positionWorldOnB - shape1_ptWorld0).length();
613-
float l1c = (cp.m_positionWorldOnB - shape1_ptWorld1).length();
614-
615-
// Get local in the links frame
616-
col->nearest_points_local[1] =
617-
convertBtToEigen(tf1_inv * (shape1_tfWorld0 * ((shape1_ptLocal0 + shape1_ptLocal1) / 2.0)));
618-
col->cc_type[1] = ContinouseCollisionType::CCType_Between;
619-
620-
if (l0c + l1c < BULLET_LENGTH_TOLERANCE)
621-
{
622-
col->cc_time[1] = .5;
623-
}
624-
else
625-
{
626-
col->cc_time[1] = static_cast<double>(l0c / (l0c + l1c));
627-
}
628-
}
567+
calculateContinuousData(col, colObj0Wrap, cp.m_positionWorldOnA, -1 * cp.m_normalWorldOnB, tf0_inv, 0);
568+
calculateContinuousData(col, colObj1Wrap, cp.m_positionWorldOnB, cp.m_normalWorldOnB, tf1_inv, 1);
629569
}
630570
else
631571
{
632572
bool castShapeIsFirst = (cd0->m_collisionFilterGroup == btBroadphaseProxy::KinematicFilter) ? true : false;
633573
btVector3 normalWorldFromCast = -(castShapeIsFirst ? 1 : -1) * cp.m_normalWorldOnB;
634574
const btCollisionObjectWrapper* firstColObjWrap = (castShapeIsFirst ? colObj0Wrap : colObj1Wrap);
635575
const btTransform& first_tf_inv = (castShapeIsFirst ? tf0_inv : tf1_inv);
576+
const btVector3& ptOnCast = castShapeIsFirst ? cp.m_positionWorldOnA : cp.m_positionWorldOnB;
636577

637578
if (castShapeIsFirst)
638579
{
@@ -646,62 +587,7 @@ inline btScalar addCastSingleResult(btManifoldPoint& cp,
646587
col->normal *= -1;
647588
}
648589

649-
btTransform tfWorld0, tfWorld1;
650-
assert(dynamic_cast<const CastHullShape*>(firstColObjWrap->getCollisionShape()) != nullptr);
651-
const auto* shape = static_cast<const CastHullShape*>(firstColObjWrap->getCollisionShape());
652-
assert(shape != nullptr);
653-
654-
tfWorld0 = firstColObjWrap->getWorldTransform();
655-
tfWorld1 = firstColObjWrap->getWorldTransform() * shape->m_t01;
656-
657-
Eigen::Isometry3d s1 = col->transform[1].inverse() * convertBtToEigen(tfWorld0);
658-
col->cc_transform[0] = col->transform[0];
659-
col->cc_transform[1] = convertBtToEigen(tfWorld1) * s1.inverse();
660-
661-
btVector3 normalLocal0 = normalWorldFromCast * tfWorld0.getBasis();
662-
btVector3 normalLocal1 = normalWorldFromCast * tfWorld1.getBasis();
663-
664-
btVector3 ptLocal0;
665-
float localsup0;
666-
GetAverageSupport(shape->m_shape, normalLocal0, localsup0, ptLocal0);
667-
btVector3 ptWorld0 = tfWorld0 * ptLocal0;
668-
btVector3 ptLocal1;
669-
float localsup1;
670-
GetAverageSupport(shape->m_shape, normalLocal1, localsup1, ptLocal1);
671-
btVector3 ptWorld1 = tfWorld1 * ptLocal1;
672-
673-
float sup0 = normalWorldFromCast.dot(ptWorld0);
674-
float sup1 = normalWorldFromCast.dot(ptWorld1);
675-
676-
// TODO: this section is potentially problematic. think hard about the math
677-
if (sup0 - sup1 > BULLET_SUPPORT_FUNC_TOLERANCE)
678-
{
679-
col->cc_time[1] = 0;
680-
col->cc_type[1] = ContinouseCollisionType::CCType_Time0;
681-
}
682-
else if (sup1 - sup0 > BULLET_SUPPORT_FUNC_TOLERANCE)
683-
{
684-
col->cc_time[1] = 1;
685-
col->cc_type[1] = ContinouseCollisionType::CCType_Time1;
686-
}
687-
else
688-
{
689-
const btVector3& ptOnCast = castShapeIsFirst ? cp.m_positionWorldOnA : cp.m_positionWorldOnB;
690-
float l0c = (ptOnCast - ptWorld0).length();
691-
float l1c = (ptOnCast - ptWorld1).length();
692-
693-
col->nearest_points_local[1] = convertBtToEigen(first_tf_inv * (tfWorld0 * ((ptLocal0 + ptLocal1) / 2.0)));
694-
col->cc_type[1] = ContinouseCollisionType::CCType_Between;
695-
696-
if (l0c + l1c < BULLET_LENGTH_TOLERANCE)
697-
{
698-
col->cc_time[1] = .5;
699-
}
700-
else
701-
{
702-
col->cc_time[1] = static_cast<double>(l0c / (l0c + l1c));
703-
}
704-
}
590+
calculateContinuousData(col, firstColObjWrap, ptOnCast, normalWorldFromCast, first_tf_inv, 1);
705591
}
706592

707593
return 1;

0 commit comments

Comments
 (0)