I spent most of the day reading about constraint solvers (as well as error correction). It seems like you can categorize constraint solvers as either sequential or simultaneous.
Sequential solvers solve each constraint individually. Because solving one constraint could invalidate another constraint, a sequential solver is normally iterative: All constraints are solved multiple times until a maximum iteration has been reached or all of the constraints are solved. These are generally easier to both understand and implement.
All of the constraints are solved at the same time, removing the need to iterate. This normally involves solving an LCP, which appears to be a difficult task.
The solvers can then be split up into force-based, impulse-based, and finally position-based methods.
The constraint is solved by applying a force. For example, a constraint to keep two objects within a certain distance would apply a force pulling the objects together if they become separated further than that maximum distance.
An impulse is applied to the constraint anchor points if the constraint is not met. For example, a collision constraint would apply an impulse in order to push the two objects away from each other.
The position is changed to meet the constraint. This appears to be mostly used in error correction, such as ensuring that two objects do not interpenetrate. I'm not sure if this is a standard way of going about this or not, but I thought it was a cool idea: Don't change the position directly. Instead, apply an impulse and perform explicit Euler integration.
I'm done reading that rigid body dynamics thesis for now. I'll be reading some articles on 3D engine architecture next, including a rather long one on scene graphs. That is for another blog post though.