kinematic - Kinematic solver/constraint system¶
This module defines the types and functions for kinematic manimulation and computation.
A Kinematic is a conceptual approach of mechanisms. It sort parts in several groups with the same movement (so in a solid, the solids are all bound together), and it links the defined solids by joints corresponding to the constraints each solid put to the other solids in the joint. That way no matter what are the parts, and what are their shape, even whan surfaces links the solids - the solid always have the same movements when there is the same joints between them.
So to analyse a mechanisme we look at its kinematic. And that can be done prior or after the part design as it is independant.
A kinematic in itself is a set of solids, observing movement relations. Those are modeled across the following classes: Solid
and Kinematic
.
Solids are considered to be undeformable, this allows the to use the Screw theory to represent the force and movement variables (see https://en.wikipedia.org/wiki/Screw_theory).
In this module, screws are called Screw
.
Tip
In case of undeformable solids, torsors makes possible to represent both the translative and rotative part of each movement aspect, independently from the point in the solid.
- class Screw(resulting=None, momentum=None, position=None)¶
- a 3D torsor aka Screw aka Wrench aka Twist - is a mathematical object defined as follow:
a resulting vector R
a momentum vector field M
- the momentum is a function of space, satisfying the relationship:
M(A) = M(B) + cross(R, A-B)
- therefore it is possible to represent a localized torsor such as:
R = resulting
M = momentum vector at position P
P = position at which M takes the current value
- torsor are usefull for generalized solid mechanics to handle multiple variables of the same nature:
- force torsor:
Screw(force, torque, pos)
- velocity (aka kinematic) torsor:
Screw(rotation, velocity, pos)
- kinetic (inertia) torsor:
Screw(linear movement quantity, rotational movement quantity, pos)
all these torsors makes it possible to represent all these values independently from expression location
- resulting¶
- Type
vec3
- momentum¶
- Type
vec3
- position¶
- Type
vec3
Of course, as any vector variables,
Screw
implements+ -
with otherTorsor
, and* /
withfloat
- locate(pt) madcad.kinematic.Screw ¶
gets the same torsor, but expressed for an other location
- transform(mat) madcad.kinematic.Screw ¶
changes the torsor from coordinate system
- class Solid(pose=None, **content)¶
Solid for kinematic definition, used as variable by the kinematic solver
- orientation¶
rotation from local to world space
- Type
quat
- position¶
displacement from local to world
- Type
vec3
- content¶
objects to display using the solid’s pose
- Type
dict/list
- name¶
optional name to display on the scheme
- Type
str
- property pose: glm.dmat4x4¶
transformation from local to global space, therefore containing the translation and rotation from the global origin
- set(**objs)¶
contenient method to set many elements in one call. equivalent to
self.content.update(objs)
- add(value)¶
add an item in self.content, a key is automatically created for it and is returned
- __getitem__(key)¶
- transform(trans) madcad.kinematic.Solid ¶
create a new Solid moved by the given transformation, with the same content
- place(*args, **kwargs) madcad.kinematic.Solid ¶
strictly equivalent to
.transform(placement(...))
- class Kinematic(joints, fixed=(), solids=None)¶
Holds a kinematic definition, and methods to use it The solid objects used are considered as variables and are modified inplace by methods, and can be modified at any time by outer functions The joints are not modified in any case (and must not be modified while a Kinematic is using it)
- joints¶
the joints constraints
- solids¶
all the solids the joint applys on, and eventually more
- fixed¶
the root solids that is considered to be fixed to the ground
- solvekin(joints, fixed=(), precision=0.0001, maxiter=None, damping=1)¶
solver for kinematic joint constraints.
Unlike
solve
, the present solver is dedicated to kinematic usage (and far more efficient and precise). It doesn’t rely on variables as defined by solve, but instead use Solids as constraints.See the joints module for joints definitions.
- makescheme(joints, color=None)¶
create kinematic schemes and add them as visual elements to the solids the joints applies on
- placement(*pairs, precision=0.001)¶
return a transformation matrix that solved the placement constraints given by the surface pairs
- Parameters
pairs – a list of surface pairs to convert to kinematic joints using
guessjoint
precision – surface guessing and kinematic solving precision (distance)
each pair define a joint between the two assumed solids (a solid for the left members of the pairs, and a solid for the right members of the pairs). placement will return the pose of the first relatively to the second, satisfying the constraints.
Example
>>> # get the transformation for the pose >>> pose = placement( ... (screw['part'].group(0), other['part'].group(44)), # two cylinder surfaces: Gliding joint ... (screw['part'].group(4), other['part'].group(25)), # two planar surfaces: Planar joint ... ) # solve everything to get solid's pose >>> # apply the transformation to the solid >>> screw.pose = pose
>>> # or >>> screw.place( ... (screw['part'].group(0), other['part'].group(44)), ... (screw['part'].group(4), other['part'].group(25)), ... )
suppose we have those parts to assemble and it’s hard to guess the precise pose transform between them
placement gives the pose for the screw to make the selected surfaces coincide
- explode(solids, factor=1, offsets=None) -> (solids:list, graph:Mesh)¶
move the given solids away from each other in the way of an exploded view. makes easier to seen the details of an assembly . See
explode_offsets
for the algorithm- Parameters
solids – a list of solids (copies of each will be made before displacing)
factor – displacement factor, 0 for no displacement, 1 for normal displacement
offsets – if given, must be the result of
explode_offsets(solids)
Example
>>> # pick some raw model and separate parts >>> imported = read(folder+'/some_assembly.stl') >>> imported.mergeclose() >>> parts = [] >>> for part in imported.islands(): ... part.strippoints() ... parts.append(Solid(part=segmentation(part))) ... >>> # explode the assembly to look into it >>> exploded = explode(parts)
before operation
after operation
- explode_offsets(solids) [solid_index, parent_index, offset, barycenter] ¶
build a graph of connected objects, ready to create an exploded view or any assembly animation. See
explode()
for an example. The exploded view is computed using the meshes contained in the given solids, so make sure there everything you want in their content.Complexity is
O(m * n)
where m = total number of points in all meshes, n = number of solidsNote
Despite the hope that this function will be helpful, it’s (for computational cost reasons) not a perfect algorithm for complex assemblies (the example above is at the limit of a simple one). The current algorithm will work fine for any simple enough assembly but may return unexpected results for more complexe ones.