Please fill in your name and student id:
First name: | Last name: | Student ID: |
---|---|---|
For a more readable version of this document, see Readme.pdf.
Deadline: March 26th 2020, 1pm. Only commits pushed to github before this date and time will be considered for grading.
Issues and questions: Please use the issue tracker of the starter code repository if you have any general issues or questions about this assignment. You can also use the issue tracker of your personal repository or email me.
In the first assignment, we implemented several optimization methods to solve unconstrained optimization problems, for example IK for a two-bar linkage. In this assignment we want to simulate more complex mechanisms using the same optimization methods.
A mechanical linkage consists of
- links of different length,
- hinge joints that connect two links,
- fixed joints that keep a point on a link fixed with respect to world coordinates,
- and fixed angle joints that enforce a fixed angle between a rigid body and the world.
We will model a general class of mechanisms with rigid bodies and constraints that act between these rigid bodies. Here are the components of our simulation:
Rigid bodies. We will model the links as rigid bodies. The position
The world coordinates,
$$
p_w(x_i) = x_{p,i} + R({\theta_i}) p_l
$$
where
Hinge joints. A hinge joint connects two rigid bodies
**Fixed angle joints ** force the relative angle of two rigid bodies
We collect the states of all
In the last assignment, you already implemented Newton's method. What you need to do in this assignment, is to compute the gradient
Task 1.1: The constraints of the hinge and the fixed joint both use the function
Relevant code: RigidBody.h
. Implement the function dpWorld_dx
. The function drotationMatrix_dtheta
returns src/tests/tests
, it should print rigid body test: [PASSED]
.
Task 1.2: Now we can compute the Jacobians of the hinge and fixed joint constraints. Note that the Jacobian for the hinge joint has the following structure:
Relevant code: In the file Joint.h
you implement the methods jacobian
for all three different joints. Make use of the previously implemented method rb.dpWorld_dx
of the rigid body class. You can test your implementation by running the executable src/tests/tests
, it should print
hinge joint test: [PASSED]
fixed joint test: [PASSED]
fixed angle joint test: [PASSED]
Task 1.3: Having implemented the Jacobians of all different types of constraints, we need to assemble them into the global Jacobian
Relevant code: In the file KinematicEnergy.h
, the method jacobian
computes the global Jacobian i
keeps track of how many constraints were already processed. Each rigid body has a field dofIdx
which is the start index of the rigid body in the global state vector dCdx.block<1,3>(i, dofIdx)
are thus dofIdx
.
Again, you can test your implementation by running the executable src/tests/tests
, it should print simulation test: [PASSED]
. You can now also ran the app src/app/app
, click "run simulation" and drag around rigid bodies. The linkage should behave as expected.
Using the simulation, we now want to change the dimensions of the linkage to perform a certain task. We will use the famous Jansen leg mechanism. The goal is to find link lengths, such that the end-effector (or foot) of the Jansen leg tracks a target trajectory.
Task 2.1: Run the app and select the Jansen mechanism. While the simulation is running, you can select a rigid body and change its length with the arrow up/down keys. The resulting trajectory (green) of the end-effector will change. Try your best to change the link length by hand, such that it matches the target trajectory (orange) best possible. Click the button "print link length" and report the result printed to cout
.
Your answer: the printed list of link lengths
Task 2.2: It probably took you some time to find a good approximation to the target trajectory. Let's now use random search to find the optimal link lengths
Relevant code: Implement the method evaluate
in the file MechanismOptimizer
to return MatchTrajectoryObjective
has its own copy of the simulation sim
. The method sim.setDesignParameters(p)
sets the link lengths sim.recordTrajectory()
returns the trajectory as a matrix where each row contains the coordinates of the end-effector. You can also adjust the search region in the method MechanismOptimizer::optimizeTrajectory()
.
What is the best mechanism your algorithm found? Click the button "print link length" and report the result printed to cout
.
Your answer: the printed list of link lengths
Make sure you install the following:
- Git (https://git-scm.com)
- Windows: download installer from website
- Linux: e.g.
sudo apt install git
- MacOS: e.g.
brew install git
- CMake (https://cmake.org/)
- Windows: download installer from website
- Linux: e.g.
sudo apt install cmake
- MacOS: e.g.
brew install cmake
On Windows, you can use Git Bash to perform the steps mentioned below.
- Clone this repository and load submodules:
git clone --recurse-submodules YOUR_GIT_URL
- Make build folder and run cmake
cd comp-fab-a0-XXX mkdir build && cd build cmake ..
- Compile code and run executable
- for MacOS and Linux:
make ./src/app/app
- for Windows:
- open
assignement0.sln
in Visual Studio - in the project explorer, right-click target "app" and set as startup app.
- Hit F5!
- open
- for MacOS and Linux:
-
If you are new to git, there are many tutorials online, e.g. http://rogerdudler.github.io/git-guide/.
-
You will not have to edit any CMake file, so no real understanding of CMake is required. You might however want to generate build files for your favorite editor/IDE: https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html