|
| 1 | +Nonlinear CCD |
| 2 | +============= |
| 3 | + |
| 4 | +We can also perform CCD of nonlinear trajectories (of linear geometry) using the method of :cite:t:`Ferguson2021RigidIPC`. While :cite:t:`Ferguson2021RigidIPC` introduce their method in the context of rigid bodies, it can be applied to any nonlinear trajectory of linear geometry. The method works by transforming the nonlinear trajectories into (adaptive) piecewise linear trajectories with an envelope/minimum separation around each piece, enclosing the nonlinear trajectory. The method then performs CCD on the piecewise linear trajectories to find the earliest time of impact. |
| 5 | + |
| 6 | +We provide the following functions to perform nonlinear CCD: |
| 7 | + |
| 8 | +.. md-tab-set:: |
| 9 | + |
| 10 | + .. md-tab-item:: C++ |
| 11 | + |
| 12 | + * :cpp:func:`ipc::point_point_nonlinear_ccd`, |
| 13 | + * :cpp:func:`ipc::point_edge_nonlinear_ccd`, |
| 14 | + * :cpp:func:`ipc::edge_edge_nonlinear_ccd`, and |
| 15 | + * :cpp:func:`ipc::point_triangle_nonlinear_ccd`. |
| 16 | + |
| 17 | + Each of these functions take as input a :cpp:func:`ipc::NonlinearTrajectory` object for the endpoints of the linear geometry. |
| 18 | + |
| 19 | + .. md-tab-item:: Python |
| 20 | + |
| 21 | + * :py:func:`ipctk.point_point_nonlinear_ccd`, |
| 22 | + * :py:func:`ipctk.point_edge_nonlinear_ccd`, |
| 23 | + * :py:func:`ipctk.edge_edge_nonlinear_ccd`, and |
| 24 | + * :py:func:`ipctk.point_triangle_nonlinear_ccd`. |
| 25 | + |
| 26 | + Each of these functions take as input a :py:func:`ipctk.NonlinearTrajectory` object for the endpoints of the linear geometry. |
| 27 | + |
| 28 | +For example, the following code defines a rigid trajectory in 2D in order to perform nonlinear CCD between a point and edge: |
| 29 | + |
| 30 | +.. md-tab-set:: |
| 31 | + |
| 32 | + .. md-tab-item:: C++ |
| 33 | + |
| 34 | + .. literalinclude:: ../../../tests/src/tests/ccd/test_nonlinear_ccd.cpp |
| 35 | + :language: c++ |
| 36 | + :start-after: // BEGIN_RIGID_2D_TRAJECTORY |
| 37 | + :end-before: // END_RIGID_2D_TRAJECTORY |
| 38 | + |
| 39 | + .. md-tab-item:: Python |
| 40 | + |
| 41 | + .. literalinclude:: ../../../python/tests/test_ccd.py |
| 42 | + :language: python |
| 43 | + :start-after: # BEGIN_RIGID_2D_TRAJECTORY |
| 44 | + :end-before: # END_RIGID_2D_TRAJECTORY |
| 45 | + :dedent: 4 |
| 46 | + |
| 47 | +Defining the Trajectory |
| 48 | +----------------------- |
| 49 | + |
| 50 | +Let's dive deeper by breaking down the implementation of Rigid2DTrajectory. The first function we need to implement is the call operator: |
| 51 | + |
| 52 | +.. md-tab-set:: |
| 53 | + |
| 54 | + .. md-tab-item:: C++ |
| 55 | + |
| 56 | + .. literalinclude:: ../../../tests/src/tests/ccd/test_nonlinear_ccd.cpp |
| 57 | + :language: c++ |
| 58 | + :lines: 127-134 |
| 59 | + :dedent: 4 |
| 60 | + |
| 61 | + |
| 62 | + .. md-tab-item:: Python |
| 63 | + |
| 64 | + .. literalinclude:: ../../../python/tests/test_ccd.py |
| 65 | + :language: python |
| 66 | + :lines: 88-92 |
| 67 | + :dedent: 8 |
| 68 | + |
| 69 | +This function computes the position of the point at a time :math:`t \in [0, 1]`. This defines the trajectory of the point. In this case, we have a rigid body with a center of mass (COM) at the origin. The trajectory of the point is given by: |
| 70 | + |
| 71 | +.. math:: |
| 72 | +
|
| 73 | + x(t) := R(\theta + t \Delta \theta) \bar{x} + T + t \Delta T |
| 74 | +
|
| 75 | +where :math:`\theta` is the angle of rotation about the COM, :math:`T` is the translation of the COM, :math:`\Delta \theta` and :math:`\Delta T` are the updates to :math:`\theta` and :math:`T`, respectively, and :math:`\bar{x}` is the position of the point in the interial frame. |
| 76 | + |
| 77 | +Computing a Conservative Envelope |
| 78 | +--------------------------------- |
| 79 | + |
| 80 | +The second function we need to implement is ``max_distance_from_linear``. |
| 81 | + |
| 82 | +.. md-tab-set:: |
| 83 | + |
| 84 | + .. md-tab-item:: C++ |
| 85 | + |
| 86 | + .. literalinclude:: ../../../tests/src/tests/ccd/test_nonlinear_ccd.cpp |
| 87 | + :language: c++ |
| 88 | + :lines: 136-147 |
| 89 | + :dedent: 4 |
| 90 | + |
| 91 | + .. md-tab-item:: Python |
| 92 | + |
| 93 | + .. literalinclude:: ../../../python/tests/test_ccd.py |
| 94 | + :language: python |
| 95 | + :lines: 94-100 |
| 96 | + :dedent: 8 |
| 97 | + |
| 98 | +This function computes the maximum distance over a time interval :math:`[t_0, t_1]` between the nonlinear trajectory and a line segment from :math:`x(t_0)` to :math:`x(t_1)`. Mathematically this function computes |
| 99 | + |
| 100 | +.. math:: |
| 101 | +
|
| 102 | + \min_{t\in[0, 1]} \|x((t_1 - t_0) t + t_0) - ((x(t_1) - x(t_0))t + x(t_0))\|, |
| 103 | +
|
| 104 | +for a given start and end time :math:`t_0` and :math:`t_1`, respectively. |
| 105 | + |
| 106 | +In the case of a 2D rigid body, we can compute this value analytically because we know the :math:`\arg\!\min`: |
| 107 | + |
| 108 | +.. math:: |
| 109 | +
|
| 110 | + \underset{t\in[0, 1]}{\arg\!\min} \|x((t_1 - t_0) t + t_0) - ((x(t_1) - x(t_0))t + x(t_0))\| = 0.5, |
| 111 | +
|
| 112 | +for :math:`(t_1 - t_0) \Delta \theta \leq \pi/2`, otherwise we can use the most conservative envelope radius of :math:`2 \|\bar{x}\|`. |
| 113 | + |
| 114 | +Performing Nonlinear CCD |
| 115 | +------------------------ |
| 116 | + |
| 117 | +Last, we use the ``Rigid2DTrajectory`` to perform nonlinear CCD between a point and edge: |
| 118 | + |
| 119 | +.. md-tab-set:: |
| 120 | + |
| 121 | + .. md-tab-item:: C++ |
| 122 | + |
| 123 | + .. literalinclude:: ../../../tests/src/tests/ccd/test_nonlinear_ccd.cpp |
| 124 | + :language: c++ |
| 125 | + :start-after: // BEGIN_TEST_RIGID_2D_TRAJECTORY |
| 126 | + :end-before: // END_TEST_RIGID_2D_TRAJECTORY |
| 127 | + :dedent: 4 |
| 128 | + |
| 129 | + .. md-tab-item:: Python |
| 130 | + |
| 131 | + .. literalinclude:: ../../../python/tests/test_ccd.py |
| 132 | + :language: python |
| 133 | + :start-after: # BEGIN_TEST_RIGID_2D_TRAJECTORY |
| 134 | + :end-before: # END_TEST_RIGID_2D_TRAJECTORY |
| 135 | + :dedent: 4 |
| 136 | + |
| 137 | +.. note:: |
| 138 | + We adjust the ``conservative_rescaling`` parameter to get a more accurate time of impact (TOI), but in practice, this is not needed as a more conservative estimate of the TOI is sufficient to avoid penetrations. |
0 commit comments