This tutorial shall give some insides in the current assembly workflow while providing theoretical background of the used design. Goal is to achieve a understanding of the assembly workbench's working, it's structure and how to use it.
This workbench is in an early development stage, therefore you will experience inconsistent behavior and all kinds of errors/crashs. Please report reproducible problems to the [assembly sub-forum] or the [mantis bug tracker].
The goal of an assembly workbench is to move parts around. It's therefore obvious that there needs to be a way to achieve this transformation of parts, and this part of the introduction is about this basic functionality.
In FreeCAD every object in 3D space has it's own coordinate system. This local system is set in relation to it's parent system by a transformation, its placement. The object's placement defines how the local geometry needs to be translated and rotated to be expressed in the parents system. Hence if you move a part by editing its placement property, you don't change the part, only the transformation of its coordinate system into the parent system. Imagine a simple box created in the Part workbench. Once created, the length parameter changes the box's dimension in the local x direction. As the placement is empty, it's also the global x direction. If you rotate the part by setting a rotation axis and an angle, the length will still be in local x direction, however, visually it will not change on x anymore as the visuals are presented in the global coordinate system. The box geometry has not changed, just the visualization is transformed.
This would make it easy to move single parts around: just adopt its placement. However, in FreeCAD most designs are done with many features (pads, pockets etc.), how would one handle that? Move every feature? Only the last one? Both ways would introduce some very problematic modeling behavior, therefore a third way is used: don't move features at all! Instead the concept of a Body was introduced into general modeling, everything done in part design is now grouped beneath it. This object has a placement property too and can be transformed.
Coming back to local and parent coordinate systems: the body is the perfect incarnation of that concept! Every feature beneath the body can't be moved directly, it's placement is always empty. That means, the feature's geometry doesn't need to be rotated or translated if we want to express it in the bodies coordinate system. But we can move the body inside the global coordinate system by setting it's placement, and then the global value of the feature's geometry is calculated by applying this transformation too. Remember, we rotate coordinate systems. That means if we transform the body system, everything beneath uses it as its personal global system. There is no need to move features at all. You want your whole design at a different place? Just set the body's placement!
To summarize: Coordinate systems can be stacked, every object uses it's parents system as personal global one. If the parents coordinate system is transformed, all children get transformed too without changing their local systems.
With the Body object we have everything we want for assembly: we can move complex designs in a comprehensible way, right?. Not quite! What would happen if you want to have your design many times inside the assembly? For example if you modeled a screw, you don't want to remodel it again every time you need one. Copying may work, however, what if you change your screw design: change all copies? That would be very annoying. To overcome this, again a new object is introduced: the part. A part is a pure assembly object and can only be created inside this workbench. Its purpose is to reference a body object and provide another coordinate system.
To understand why it's introduced we have to consider how things are moved in FreeCAD. Lets extend the body chart above with two parts referencing the same body as shown in the next picture.
The bodys local system is the same in both parts, however, the parts have their own placements and therefore can be transformed in respect to the global system. As placements get applied recursively, the very same features can end up on different positions. Imagine you change the parts placement P4 and P5 to different values, your design would appear in two total different places inside the global system without any changes to the features or the body holding them. And then imagine changing the body's coordinate system P3: You would change the position of all incarnations of your design in the same manner!
You may wonder how you design can be in two places while being only one geometry. Thats simple: The part shows only a visual representation of the geometry inside the body, and you can have many pictures of your single part. Also those visuals representations are transformed if you set the placement. A part holds absolutely no modeling information.
Back to our use case: if you need 100 screws you will model only one body with your design. Then you can add as much parts as you want holding this one body. By applying different placements to the parts only you can move the screws around as you want. And if you change something in your design, the body gets updated and every part too, as they all reference it. Awesome!
Now imagine another use case: you have a nice electrical motor assembly consisting of multiple parts, are all moved to the right position. Afterwards you want to create a bigger machine and you need multiple electrical motors for it. What we want is to reuse the motor assembly, the same reasoning as with the multiple body incarnations apply. For simple designs we were able to create multiple parts from one body, however, we can't create a part from multiple parts. Therefore we need another object which can do that! FreeCAD introduces the product object for this. A product is basically a full assembly with multiple parts, but also has a placement property. What does that mean? It becomes clear when we again extend the coordinate system chart with our new product object.
Now our parts are not anymore beneath the global coordinate system, but they are grouped beneath the product. For the parts nothing change: they works as before. And in fact, if our Product1 would have been the top-level object, absolutely nothing would change at all. The global system is just replaced by a product coordinate system which acts as global one. In our example however, we added the product to another product, together with a third part. Now it gets interesting: As a product has a placement property, it can be moved! And we already learned that such a transformation is applied to all children. Therefore parts 1 and 2 would move when you change the placement of Product1.
Back to our example: Product1 would be the electrical motor, Product2 the big machine. Now you can add multiple products to the machine which all reference the same parts as Product1, hence all representing a electrical motor. And as every product can be placed diffrently, you can move all motors to diffrent positions. Combine it with other parts and assemblies and you can build a complex machine. Again, if you update one body, all parts and therefore all products referencing it get updated.
At last you may ask why there is no global coordinate system in the last picture. Thats because nothing like a global coordinate system exists, it was just a concept for easy explaining. If you assembly your electrical motor, the top-level coordinate system would be the Product1 system. However, this is not a general global one, as you can add it to a another product which is the top-level cs afterwards. And this can be added to another, and so on. There is nothing like a global coordinate system, just a top-level one.To summarize: In the assembly workbench you can combine parts to assemblies (products). These products can be staked together with other parts in arbitrary numbers.
Up to now we discussed all details of moving things around with placements and the objects involved in it. It is however very tedious to calculate all placements by hand and set them manual via the property editor. It would be more pleasant if it would be possible to set simple relations between parts instead of abstract rotations and translations. Therefore FreeCAD introduces assembly constraints. As the name indicates, they work the same way as in the sketcher: the user applies different attributes to geometries of the parts. This can be for example the distance between two points, or their orientation (parallel, perpendicular) of lines etc. FreeCAD trys then to find placements which satisfy all given constraints.
To assemble things in the real world, one would use the parts structure to fit the counterpart into its place, for example a bolt which belongs into a hole. Or surfaces which touch each other and therefore define the parts exact position. In FreeCAD it works exactly like that: you use the parts geometry to specify where the second part belongs to. At your disposal are points, straight lines, planes and cylinders. The picture to the right shows them all in the FreeCAD environment. But of course, the geometry alone is not enough to calculate the parts positions, the kind of relation needs to be known too. For example two faces: They can touch each other, or just be parallel, maybe even perpendicular. This relation is set in FreeCAD through the already mentioned assembly constraints. You have 6 diffrent types at your hand: Fix, Distance, Orientation, Angle, Align and Coincident. Lets see what they all do and how to use them.
The fix constraint is the simplest of all constraints. It only needs one part to be selected and then it fixes its position and its rotation. No matter what you do to this part afterwards: it will hold its place. And thats the whole purpose of that type. It's most useful to have always one fixed part per assembly, as it can be annoying if all parts get moved to satisfy other constraints. If you fix the most basic part in your assembly, all other parts will move towards it which gives you a pleasant experience. Note that this constraint works only in the assembly it is created in, the part will not be fixed in any parent assembly (remember: assemblies can be stacked).
As you already guessed from the name, with this constraint you can specify the distance between two geometries. This works for two points, but also for a point and a line, or a line and a cylinder and many more combinations. This constraint is pretty simple, but two points need mentioning: First, if there are multiple possible distances between geometries, for example the last mentioned line and cylinder, then the shortest distance is used. Second, sometimes multiple solutions exist even for the shortest distance. This is the case for the point-plane distance: every value can be satisfied with the point above AND below the plane. So if you only specify the value, it can happen that FreeCAD puts the point at the wrong side of the plane. To control this, the distance constraint has a special option, the solution space. This option allows to reduce the space of possible solutions, so that it matches your wishes. Lets see how this works on our small example: