Vortex Simulation Toolkit
Vortex is a physics engine which allows to simulate solids in a virtual
environment according to physical laws. The commercially available library
is wrapped for use in NEO/NST.
This tutorial will show you, how to use the Vortex Simulation Toolkit
within NEO/NST. You will learn
How to get a license grant
Currently we have
two floating network licenses controlled by a flexlm license server running on
hasdrubal. Additionally we have two node-locked licenses bound to the network
cards of pareios and xerxes. In order to get a license grant, you have to set
the enviroment variable
LM_LICENSE_FILE=27000@hasdrubal:/vol/mathengine/license/ver.201.laptops
Because the number of available licenses is limited, you may not get a
license grant. In this case only the collision detection and dynamical
constraints don't work. You can edit and (run) your neo circuits! You can
check availability of licenses for collision detection (mcd) and dynamics
solver (mdt) using the commands lmstat -f mcd and lmstat -f
mdt. The lmstat utility program can be found in
/vol/mathengine/license/bin and you should probably insert this path
to your PATH environment variable.
How the class hierarchy of universes, scenes and
objects works
A simulation runs in a virtual universe, whose class
implementation provides methods to control all global properties, such as
gravity, material properties, friction coefficients etc. Into a universe
several scenes can be loaded, which contain a collection of articulated
bodies, i.e. bodies connected by several joints. All objects (solids and
joints) defined in a scene are accessible within neo through a unique
name. The object's class implementations allow to control the specific
properties of this object. The ballman example
illustrates this mechanism of referencing objects within scenes within
universes.
How to describe a scene using a xml-syntax file
Most objects within a universe should be described within a scene-description
file (for example ballman.me). These files use a
simple xml-style syntax with a lot of tags to describe solids and joints.
Nevertheless it is possible to create some simple solids directly as well (see
the prog_unit of the ballman example). The
description-file contains the following sections:
global world specific definitions, basic solid geometries, definition of the solids themselves, joints and graphics stuff.
Because solids
frequently use the same basic geometry primitives (box, sphere, cylinder,
etc.) these geometries are defined separately and can be used in the
definition of several solids. All defined objects in the file get a unique
ID (with separate name spaces for geometries, solids, joints, graphic
primitives and graphics).
How to actuate joints
Vortex provides the possibility to actuate hinge and prismatic joints in
two ways (see hinge1.HNST):
- through direct specification of destination positions using
SetValue
- through specification of desired joint velocities using
SetSpeed.
Joint angles (or positions in case of prismatic joints) are always
given relative to the creation position, i.e. the creation position
represents an angle / position equal to zero. Notice to specify joint angles
of hinges in radians. The actual joint position can be retrieved using
GetValue and its current speed with GetSpeed
With each hinge or prismatic joint motor is connected a maximally appliable
force, which can be accessed by Set/GetMaxForce. Vortex uses an
optimal speed control algorithm, which ensures that the desired joint speed is
achieved in the next time step, if the neccessary force is smaller than the
maximal force. Due to inertia effects the neccessary force might be too large,
such that the desired speed is reached within serveral time steps only.
There is a simple position controller implemented yet, which linearly scales
the position error in order to compute a joint speed to reduce the position
error. There is an additional clipping to a maximal joint speed as well, which
can be accessed through Set/GetMaxSpeed. The gain or proportionality
constant to scale with can be changed using Set/GetCtrlParams. In
principle it is possible to use other position controllers as well - but the
wrapping into Neo is not completed yet.
How to use robots to simplify access to joints
Because robots and especially robot hands usually contain several joints it
would be expensive to actuate each joint separetely. For this purpose a robot
class is used which combines all solids and joints of a robot and makes them
accessible simultaniously through single function calls. See hinge2.HNST for an example.
How to get joint and contact forces
Vortex handles joints and contacts as constraints to the dynamics of bodies.
They apply forces and torques to the bodies each time step. The forces
and torques applied during the last time step can be requested using the
method GetForces (callback, int iFilter). For each constraint
this method calls the user-specified function callback providing
the actual constraint type, the applied force and torque as its arguments.
arm.HNST shows the usage of this scheme within
a prog-unit to compute the sum of applied joint and contact forces. For
this purpose the callback function SumForces accumulates contact
or joint forces depending on the given type iType:
float SumForces (int iType, float* force, float *torque)
{
if (iType == tCONTACT) // depending on constraint type
add (contactF, contactF, force); // accumulate
contact forces
else
add (jointF, jointF, force); // accumulate joint
forces
}
This function is called within the solid's method solid.GetForces
(SumForces).
How to get contact data
To retrieve more contact data, like contact position and normal, a similar
scheme exists, to iterate all contact positions of a solid. For this purpose
the method GetContacts calls a user specified callback function
for each contact. friction.HNST uses this scheme
to draw a small arrow pointing in the normal direction of each contact
of small box on a plane. There the callback Contacts() is used:
float Contacts (int iType, float* force, float* torque,
float* pos, float* normal, float *dir, float f1, float f2) {
maxFriction[0] = f1; maxFriction[1] = f2;
DrawArrow (pos, normal);
}
A more elaborated example
The last example shows the TUM of our laboratory
grasping a ball hanging in the universe. This circuits uses VTK for
visualization purposes, enabling multiple views of the scene (the thumb
camera). The quality of the grasp is measured using the Grasp unit
and visualized as the force polytope.
Interactive functions added by universe.draw
to view3d
A call to the method draw of a universe object within
the context of an interactive view3d unit enables the following functionality
to this unit:
key 'r' - reset the universe
key 'g' - toggle graphics on / off
key 'p' - toggle pause: stops simulation
The following keys toggle the behaviour of the middle mouse button:
key 'd' - dragging solids
key 'f' - display joint forces
key 'c' - display contact normals