<normal_arglist> ::= (drive_caller) <element_driver> ,
[ hint , " <hint> " , [ ... ] ]
<driven_element>
<driven_element> ::= existing : <elem_type> , <elem_label>
<driven_element> ::= <element_card>
When the first format is used, an existing element
of type <elem_type> and label <elem_label> is looked for,
and it is wrapped by the driven element.
In this case, no new element is instantiated.
The label of the element must match that of the driving element given
at the beginning.
For consistency with the syntax, and for more flexibility,
even when wrapping an existing element the output flags can be set
at the end of the card.
This flag overrides the one set when the driven element was instantiated.
When the second format is used, a new normal element is read after the driving element's declaration; it is then instantiated and wrapped by the driven element wrapper. Note that after the element type, or after the keyword existing, a colon is used as a separator. This is one of the very few exception to the rule that colons can only follow descriptions at the beginning of a card. The label of the driven element must match that of the driving element given at the beginning of the card.
Example: a pin constraint between two rigid bodies is released:
set: integer body_1 = 1;
set: integer body_2 = 2;
# ...
structural: body_1, dynamic,
null, eye, null, null;
structural: body_2, dynamic,
null, eye, null, null;
# ....
rigid body: body_1, body_1,
1000., null, diag, 100.,100.,1.;
rigid body: body_2, body_2,
10., null, diag, 1.e-1,1.e-1,1.e-3;
# ...
# this constraint will be released when t = 10 s
driven: 1, string, "Time<10.",
joint: 1, spherical hinge,
body_1, null,
body_2, null;
Example: an axial rotation joint is replaced by a revolute hinge when the desired spin velocity, measured as the angular velocity of the second node (assuming, for instance, that the first one is fixed), is reached. The value of an abstract node is used to input the angular velocity to the axial rotation joint.
set: integer body_1 = 1;
set: integer body_2 = 2;
set: integer control_output = 3;
# ...
structural: body_1, static,
null, eye, null, null;
structural: body_2, dynamic,
null, eye, null, null;
abstract: control_output;
# ....
driven: 1, dof, body_2, structural, 6, differential,
string, "Var<100.",
joint: 1, axial rotation,
body_1, null,
hinge, 1, 1.,0.,0., 3, 0.,0.,1.,
body_2, null,
hinge, 1, 1.,0.,0., 3, 0.,0.,1.,
dof, control_output, abstract, algebraic,
linear, 0.,1.;
driven: 2, dof, body_2, structural, 6, differential,
string, "Var>=100.",
joint: 2, revolute hinge,
body_1, null,
hinge, 1, 1.,0.,0., 3, 0.,0.,1.,
body_2, null,
hinge, 1, 1.,0.,0., 3, 0.,0.,1.;
Currently, only few elements, significantly joints, support and honor hints. The typical syntax is given by a keywork followed by some optional parameters within curly brackets. For instance, the hint that instructs a joint to compute the offset with respect to the second node when it is activated is
driven: 10, string, "Time>1.", hint, "offset{2}",
joint: 10, ..."
A similar for is used to instruct a joint to compute the relative
orientation with respect to node 1:
driven: 20, string, "Time>1.", hint, "hinge{1}",
joint: 20, ..."
A distance joint may be fed a new drive by using:
driven: 30, string, "Time>1.",
hint, "drive{cosine,0.,pi/.1,-.9/2.,half,model::distance(1,2)}",
joint: 30, distance, ...
A drive hinge joint may be fed a new drive by using:
driven: 40, string, "Time>1.",
# note: the lines wrap for typographical reasons
# in the actual file, the string has to be a single line
hint, "drive3{model::xdistance(1,2),\
model::ydistance(1,2), model::zdistance(1,2),\
cosine,0.,pi/.1,-.9/2.,half,model::distance(1,2)}",
joint: 30, drive hinge, ...
This feature will likely be extended to other elements and generalized as much as possible.
<card> ::= inertia : <label>
[ , name , " <inertia_name> " ]
[ , position , (Vec3)<reference_position> ]
[ , orientation , (Mat3x3)<reference_orientation> ]
, <type_subset> [ , ... ]
[ , output , { no | yes | log | both } ] ;
<type_subset> ::= <type> , { all | <label_list> }
<type> ::= { body | joint | loadable }
<label_list> ::= <label> [ , <label_list> ]
where type currently can be body, joint and loadable,
although more elements associated to inertia might participate in the future.
All elements whose labels are listed must exist, and duplicates
are detected and considered errors.
The keyword all causes all the elements of type type
to be included in the list.
The only effect of the inertia statement is to log each inertia entry in the .log file in a self explanatory form, referred both to the global reference frame and to a reference frame originating from reference_position and oriented as reference_orientation. The optional parameter output may be used to alter the default behavior:
<card> ::= output : <elem_type> , <elem_list> ;
<elem_list> ::= { <elem_label> [ , <elem_list> ]
| range , <elem_start_label> , <elem_end_label> }
elem_type is a valid element type that can be read
as card name in the elements block.
In case the keyword range is used, all existing elements comprised
between <elem_start_label> and <elem_end_label>
are set; missing ones are silently ignored.