WIP: Manipulate the assembly #29

Draft
Vectornaut wants to merge 8 commits from tangent-space into main
Collaborator

Find the tangent space of the solution variety and use it to interactively deform the assembly.

Tangent space

Implementation

The structure engine::ConfigSubspace represents a subspace of the configuration vector space \operatorname{Hom}(\mathbb{R}^n, \mathbb{R}^5). It holds a basis for the subspace which is orthonormal with respect to the Euclidean inner product. The method ConfigSubspace::symmetric_kernel takes an endomorphism of the configuration vector space, which must be symmetric with respect to the Euclidean inner product, and returns its approximate kernel in the form of a ConfigSubspace.

At the end of engine::realize_gram, we use the computed Hessian to find the tangent space of the solution variety, and we return it alongside the realization. Since altering the constraints can change the tangent space without changing the solution, we compute the tangent space even when the guess passed to the realization routine is already a solution.

After Assembly::realize calls engine::realize_gram, it saves the returned tangent space in the assembly's tangent signal.

Automated testing

The test engine::tests::tangent_test builds a simple assembly with a known tangent space, runs the realization routine, and checks the returned tangent space against a hand-computed basis.

Limitations

The method ConfigSubspace::symmetric_kernel approximates the kernel by taking all the eigenspaces whose eigenvalues are smaller than a hard-coded threshold size. We may need a more flexible system eventually.

Since a ConfigSubspace stores motions in matrix form, the tangent space saved by Assembly::realize only makes sense as long as the number of elements in the assembly and the elements' column indices stay the same. The column indices aren't designed to be used like this: they were originally only meant to be read and written within Assembly::realize. If we really want to use the column indices between Assembly::realize calls, we should work harder to keep them valid between calls.

For the zero subspace, ConfigSubspace.proj panics, rather than returning zero as its name suggests it should.

Deformation

Implementation

The main purpose of this implementation is to confirm that deformation works as we'd hoped. The code is messy, and the deformation routine has at least one numerical quirk.

For simplicity, the keyboard commands that manipulate the assembly are handled by the display, just like the keyboard commands that control the camera. Deformation happens at the beginning of the animation loop.

The function Assembly::deform works like this:

  1. Take a list of element motions
  2. Project them onto the tangent space of the solution variety
  3. Sum them to get a deformation v of the whole assembly
  4. Step the assembly along the "mass shell" geodesic tangent to v
    • This step stays on the solution variety to first order
  5. Call realize to bring the assembly back onto the solution variety

Manual testing

To manipulate the assembly:

  1. Select a sphere
  2. Make sure the display has focus
  3. Hold the following keys:
    • A/D for x translation
    • W/S for y translation
    • shift+W/S for z translation

Limitations

Because the manipulation commands are handled by the display, you can only manipulate the assembly when the display has focus.

Since our test assemblies only include spheres, we assume in Assembly::deform that every element is a sphere.

When the tangent space is zero, Assembly::deform does nothing except print "The assembly is rigid" to the console.

During a deformation, the curvature and co-curvature components of a sphere's vector representation can exhibit weird discontinuous "swaps" that don't visibly affect how the sphere is drawn. [I'll write more about this in an issue.]

Find the tangent space of the solution variety and use it to interactively deform the assembly. ### Tangent space #### Implementation The structure `engine::ConfigSubspace` represents a subspace of the configuration vector space $\operatorname{Hom}(\mathbb{R}^n, \mathbb{R}^5)$. It holds a basis for the subspace which is orthonormal with respect to the Euclidean inner product. The method `ConfigSubspace::symmetric_kernel` takes an endomorphism of the configuration vector space, which must be symmetric with respect to the Euclidean inner product, and returns its approximate kernel in the form of a `ConfigSubspace`. At the end of `engine::realize_gram`, we use the computed Hessian to find the tangent space of the solution variety, and we return it alongside the realization. Since altering the constraints can change the tangent space without changing the solution, we compute the tangent space even when the guess passed to the realization routine is already a solution. After `Assembly::realize` calls `engine::realize_gram`, it saves the returned tangent space in the assembly's `tangent` signal. #### Automated testing The test `engine::tests::tangent_test` builds a simple assembly with a known tangent space, runs the realization routine, and checks the returned tangent space against a hand-computed basis. #### Limitations The method `ConfigSubspace::symmetric_kernel` approximates the kernel by taking all the eigenspaces whose eigenvalues are smaller than a hard-coded threshold size. We may need a more flexible system eventually. Since a `ConfigSubspace` stores motions in matrix form, the tangent space saved by `Assembly::realize` only makes sense as long as the number of elements in the assembly and the elements' column indices stay the same. The column indices aren't designed to be used like this: they were originally only meant to be read and written within `Assembly::realize`. If we really want to use the column indices between `Assembly::realize` calls, we should work harder to keep them valid between calls. For the zero subspace, `ConfigSubspace.proj` panics, rather than returning zero as its name suggests it should. ### Deformation #### Implementation The main purpose of this implementation is to confirm that deformation works as we'd hoped. The code is messy, and the deformation routine has at least one numerical quirk. For simplicity, the keyboard commands that manipulate the assembly are handled by the display, just like the keyboard commands that control the camera. Deformation happens at the beginning of the animation loop. The function `Assembly::deform` works like this: 1. Take a list of element motions 2. Project them onto the tangent space of the solution variety 3. Sum them to get a deformation $v$ of the whole assembly 4. Step the assembly along the "mass shell" geodesic tangent to $v$ * This step stays on the solution variety to first order 5. Call `realize` to bring the assembly back onto the solution variety #### Manual testing To manipulate the assembly: 1. Select a sphere 2. Make sure the display has focus 3. Hold the following keys: * **A**/**D** for $x$ translation * **W**/**S** for $y$ translation * **shift**+**W**/**S** for $z$ translation #### Limitations Because the manipulation commands are handled by the display, you can only manipulate the assembly when the display has focus. Since our test assemblies only include spheres, we assume in `Assembly::deform` that every element is a sphere. When the tangent space is zero, `Assembly::deform` does nothing except print "The assembly is rigid" to the console. During a deformation, the curvature and co-curvature components of a sphere's vector representation can exhibit weird discontinuous "swaps" that don't visibly affect how the sphere is drawn. *[I'll write more about this in an issue.]*
Vectornaut added 7 commits 2024-12-10 10:13:24 +00:00
At the end of the realization routine, use the computed Hessian to find
the tangent space of the solution variety, and return it alongside the
realization. Since altering the constraints can change the tangent space
without changing the solution, we compute the tangent space even when
the guess passed to the realization routine is already a solution.
Turn on the browser console panic message output provided by the
`console_error_panic_hook` feature. This feature was already enabled by
default in our Cargo configuration, but it wasn't actually being used.
This seems like a good starting point, even though the code is messy and
the deformation routine has some numerical quirks. Note that the translation
direction is mixed up: the keys are for x, but the velocity field is for z.
Make the x translation keys translate along the x axis, as intended.
This helps prevent small spheres from shrinking during deformations.
Vectornaut added 1 commit 2024-12-11 21:02:06 +00:00
The examples call `engine::realize_gram`, which now includes a call to
`symmetric_kernel`, so we need to make sure that `symmetric_kernel`
can run on whatever target Cargo uses for examples. For that target on
my machine, `console::log_1` panics with the message "function not
implemented on non-`wasm32` targets".
Vectornaut changed title from Manipulate the assembly to WIP: Manipulate the assembly 2024-12-13 20:11:04 +00:00
This pull request is marked as a work in progress.

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin tangent-space:tangent-space
git checkout tangent-space
Sign in to join this conversation.
No reviewers
No Milestone
No project
No Assignees
1 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: glen/dyna3#29
No description provided.