25. OpenPLX for AGX Dynamics
OpenPLX is a high-level modeling language designed to work seamlessly with AGX Dynamics. It provides a structured approach to defining physics simulations, allowing users to create and configure rigid bodies, constraints, motors, friction models, and more in a human-readable format.
By leveraging AGX Dynamics, OpenPLX enables the simulation of complex mechanical systems, vehicles, robotics, and deformable terrains with minimal effort.
Note
OpenPLX is a work in progress. This draft version will evolve with user feedback and experience. We welcome your input and collaboration.
This page explains how OpenPLX interacts with AGX Dynamics and provides a structured way to define physics simulations. For a complete overview of OpenPLX Syntax and Bundles, consult the OpenPLX Documentation.
Note
This version of AGX (2.43.0.0) is built with OpenPLX version 0.30.0. OpenPLX release log.
25.1. How OpenPLX Works with AGX Dynamics
OpenPLX acts as an interface layer for AGX Dynamics, converting structured OpenPLX definitions into AGX simulation components. When you load an OpenPLX file, it is transformed into an AGX Dynamics simulation tree, allowing for efficient physics-based interactions.
This means:
OpenPLX describes the physics setup and the scene.
The AGX Dynamics engine executes the simulation.
Users can interact with the scene through OpenPLX files.
Python controllers interact by sending or receiving OpenPLX signals.
25.2. Simulating an OpenPLX File in AGX Viewer
To simulate an .openplx file with AGX Dynamics, pass it to agxViewer like you would with an .agx file:
agxViewer myModel.openplx
25.3. Animating the SNAP assembly process
Use openplx_animate_snap to inspect how SNAP positions the parts of an
OpenPLX model during loading. The viewer replays the recorded transforms,
shows the responsible mate and connector, and highlights forcing steps.
This is a playback of the assembly process, not a dynamic simulation of the
machine.
Parts appear when their nearest animated transform begins its first SNAP step. A cylinder body whose own local transform stays unchanged follows its animated barrel, rod or actuator parent. Transforms recorded only as initial states do not keep a part hidden.
25.3.1. Starting the animation
Run the command in an AGX Python environment with OpenPLX support. On Linux
and macOS, source setup_env.bash from the AGX installation or build you
intend to use. On Windows, use the configured AGX command prompt. The AGX
and OpenPLX versions must support recording SNAP history and the SNAP report;
the script enables both automatically when loading the model.
python -m agxPythonModules.openplx.openplx_animate_snap scene.openplx
Playback starts automatically and loops by default. For inspection, start paused and advance one step at a time with the Right Arrow key:
python -m agxPythonModules.openplx.openplx_animate_snap scene.openplx --start-paused
If the model uses custom bundles, supply their search paths. Repeat
--extra-bundle-path for each path. Model and bundle paths are resolved
relative to the current working directory; absolute paths can also be used.
python -m agxPythonModules.openplx.openplx_animate_snap scene.openplx \
--extra-bundle-path ../machine_bundles \
--extra-bundle-path ../robot_bundles \
--start-paused
--addBundlePath is an alias for --extra-bundle-path. To select a
specific model declared in the file, add --modelName MyScene; otherwise
the last model in the file is loaded.
25.3.2. Playback controls
Give the viewer window keyboard focus before using these controls. Camera navigation remains available while playback is paused.
Key |
Action |
|---|---|
Space |
Toggle automatic playback. |
Right Arrow |
Pause automatic playback and animate the next step. |
Left Arrow |
Pause automatic playback and animate the previous step. |
|
Return to the initial state and pause. |
End |
Jump to the final assembled state and pause. |
|
Toggle looping. |
Pausing during a transition completes that transition. To examine a step,
start with --start-paused and advance to it with the arrow keys.
25.3.3. Reading the overlay and markers
The overlay begins with SNAP instruction [step] type and lists the moved
local transform, its owning model, the mate, and the responsible connector.
Use these paths to locate the corresponding declarations in the OpenPLX
source. One mate can produce several steps, for example a translation
followed by a rotation.
The viewer creates one sphere and an axis marker for the active instruction:
Green identifies the responsible connector for an ordinary SNAP step.
Red identifies a
ForcingorForcingDofstep. SNAP has chosen a reference pose or degree of freedom that the model did not uniquely determine. Review the accompanying SNAP warnings for details.
The same marker changes color and position as playback advances; markers are not retained at every previously processed connector. A following step without new connector information can retain the preceding marker. If a report does not identify a connector, the script falls back to the moved transform’s origin.
The sphere has a radius of 0.06 m. Markers use normal scene rendering, so they can be small at the current zoom level or obscured by model geometry. Pause playback and adjust the camera to inspect them. Markers are hidden at the initial state, before an instruction has been selected.
25.3.4. Timing and loading options
For a slower, single playback:
python -m agxPythonModules.openplx.openplx_animate_snap scene.openplx \
--duration-ms 1000 --step-delay-ms 300 --no-loop
Option |
Default |
Meaning |
|---|---|---|
|
|
Duration of each animated transition, in milliseconds. |
|
|
Delay between transitions during automatic playback, in milliseconds. |
|
Off |
Wait for keyboard input before starting playback. |
|
Looping enabled |
Stop at the final step instead of restarting. |
|
|
Select |
|
|
Time limit for the full-serialization helper process, in milliseconds. |
In auto mode the script first attempts full serialization in a helper
process, then falls back to registered objects if the attempt fails or times
out. Registered serialization also reconstructs nested actuator and cylinder
owner frames from their transform metadata. Use
--serialization-mode registered to skip the full-serialization attempt.
In full mode a helper failure is reported instead of falling back; use
--serialization-timeout-ms to adjust its time limit.
Run the command with --help to list its options.
You can also select the script explicitly by passing its full path to Python:
python /path/to/agx/data/python/modules/agxPythonModules/openplx/openplx_animate_snap.py scene.openplx --start-paused
An error about missing SNAP history or a missing SNAP report indicates that the loaded model or runtime did not provide the required playback data. Check the model’s load errors and use compatible AGX/OpenPLX binaries with the animation script.
25.4. Importing an AGX File in OpenPLX
AGX .agx files contain pre-defined physics models. OpenPLX supports seamless integration of AGX models into simulation systems.
The AGX Model describes the basic physics setup, including rigid bodies, constraints, collision geometries and visuals.
OpenPLX imports the AGX model and augments it with additional components, such as tracks and a drivetrain.
OpenPLX describes the complete simulation scene.
Controller scripts (python/C++) connects the OpenPLX model to the desired control systems.
The AGX Dynamics engine executes the simulation.
25.4.1. Syntax for Importing an AGX File
To import an .agx file into OpenPLX, use the following OpenPLX syntax:
import @"model.agx" as AGXModel
Scene is Physics3D.System:
my_model is AGXModel
The imported AGX model (AGXModel) can now be referenced within OpenPLX.
To load the OpenPLX scene and view the AGX model, use:
agxViewer scene.openplx -p
25.4.2. Viewing an AGX File as an OpenPLX Model
You can open an AGX file to find the components you need to reference using the anytoopenplx command:
python -m agxPythonModules.openplx.anytoopenplx model.agx > model_reference.openplx
Use this file to identify signals and components to reference when augmenting your model with additional OpenPLX components.
Note
At the moment, the models generated OpenPLX file will duplicate the content of the agx file, creating a conflict when running the simulation. To accomodate this, change the file extension of the new .openplx file to .txt, or place it outside the root folder of your OpenPLX bundle.
25.5. OpenPLX Tutorials
Explore the OpenPLX Tutorials to get started with OpenPLX for AGX Dynamics.
25.6. AGX Annotations
Annotation |
Description |
Type |
|---|---|---|
agx_relaxation_time |
Directly set the AGX Dampling. |
Real |
agx_solve_type |
Set the AGX Solve type for a constraint. |
String |
agx_friction_solve_type |
Sets the AGX Solve type for the fricion model. |
String |
agx_approximate_cone_friction |
Enables AGX approximate cone friction. |
Bool |
agx_terrain_material |
Sets an AGX terrain material preset. |
String |
agx_actuator_internal_inertia |
Sets the internal inertia of the input shaft of a agxPowerLine::RotationalActuator
or the internal mass of the input rod of a agxPowerLine::TranslationalActuator. |
Real |
agx_observer_frame |
Maps a |
Bool |
agx_debug_render_frame |
Renders the axes of a |
Bool |
25.7. AGX Track Wheel Annotations
The following annotations can be applied to a Vehicles.TrackSystem.Components.TrackWheels.Base to set AGX Track Wheel properties.
Annotation |
Description |
Type |
|---|---|---|
agx_track_wheel_split_segments |
Bool |
25.8. AGX Sensor Annotations
The following annotations are applied to Sensor bundle related models to tweak how they are loaded.
Annotation |
Description |
Type |
|---|---|---|
agx_sensor_lidar_preview |
Annotate a Sensors.LidarLogic to enable, or not, visualization of the lidar point cloud. |
Bool |
agx_sensor_camera_output_preview |
Annotate a Sensors.Signals.CameraColorOutput or a Sensors.Signals.CameraDepthOutput to enable, or not, a visualization of that output. |
Bool |
agx_sensor_camera_output_preview_maximum_depth |
Annotate a Sensors.Signals.CameraDepthOutput to optionally specify the maximum depth value used to scale the preview visualization values. |
Real |
25.9. AGX Plugin Annotations
When importing a .agx file there are a few annotations that change the import behavior.
Annotation |
Description |
Type |
|---|---|---|
discard_rigid_body_positions |
Discards all position information for rigid bodies if set to |
Bool |
regenerate_shape_uuids |
Setting this to |
Bool |
material_naming_rule |
Controls how imported materials will be named. This can be necessary to avoid collisions since materials are always put in a global scope. |
String |
ignore_disabled_secondary_constraints |
Secondary constraints that are disabled are not imported if this is set to |
Bool |
25.10. AGX Terrain Plugin Annotations
The following annotations can be applied to the import of a .tif or .tiff file.
Annotation |
Description |
Type |
|---|---|---|
num_samples_x |
Number of samples to read in x-axis. |
Int |
num_samples_y |
Number of samples to read in y-axis. |
Int |
offset_x |
Pixel offset in x-axis. |
Int |
offset_y |
Pixel offset in y-axis. |
Int |
height_offset |
Shifts heights by a fixed amount. |
Real |
max_depth |
The maximum depth of the terrain. |
Real |
26. OpenPLX → AGX: Mapping Guide
26.1. Scope
A guide showing how each OpenPLX types and attributes end up in AGX.
26.2. Accessing mapped AGX objects
After loading an OpenPLX model, use LoadResult.getAgxObjectMap() to find
the AGX objects created from its OpenPLX objects. This provides access to the
running simulation, for example to change a body’s mass or a gear’s damping.
The object map looks up existing objects; it does not create or remap them.
First obtain an OpenPLX object from result.scene() using its path relative
to that scene. For example, use robot.joint1.mate when the full object
name is Scene.robot.joint1.mate. Pass that object to the map, rather than
its name or UUID. Use objects from the same load result as the map.
The C++ API is findMapped<AgxType>(openplxObject). It returns an
agx::ref_ptr<AgxType>; an empty reference means that no matching object of
the requested type was found. Include the header defining the requested AGX
type. Python exposes the named methods listed below instead of the C++
template.
26.2.1. Obtaining the object map
These examples assume that result is a successful return value from
agxopenplx::load_from_file in C++, or agxOpenPLX.load_from_file in
Python, and that the simulation remains alive. Check result.errors()
before accessing the scene. The paths in the examples are illustrative;
replace them with paths in your model.
#include <agxOpenPLX/AgxOpenPlxApi.h>
#include <agxOpenPLX/AgxObjectMap.h>
#include <openplx/Object.h>
#include <stdexcept>
auto scene = result.scene();
auto objectMap = result.getAgxObjectMap();
// Reused by the C++ examples below.
auto requireObject = [scene](const char* path) {
auto object = scene->getObject(path);
if (!object)
throw std::runtime_error(path);
return object;
};
scene = result.scene()
object_map = result.getAgxObjectMap()
# Reused by the Python examples below.
def require_object(path):
obj = scene.getObject(path)
if obj is None:
raise RuntimeError(f"OpenPLX object not found: {path}")
return obj
def require_mapped(ref, path):
if not ref:
raise RuntimeError(f"AGX object not found: {path}")
return ref
Keep the returned references while using the objects. In Python, .get()
accesses the underlying AGX object. Acquire a new map and new object
references after reloading the scene.
26.2.2. Rigid bodies and mass properties
Map the Physics3D.Bodies.RigidBody instance, such as a tool body, to
agx::RigidBody. Mass and inertia are properties of this AGX body;
the OpenPLX inertia object is not a separate AGX rigid body.
#include <agx/RigidBody.h>
auto body = objectMap->findMapped<agx::RigidBody>(
requireObject("robot.tool"));
if (!body || !body->getMassProperties()->setMass(12.0))
throw std::runtime_error("Unable to set tool mass");
body_ref = require_mapped(
object_map.findMappedRigidBody(require_object("robot.tool")),
"robot.tool")
if not body_ref.get().getMassProperties().setMass(12.0):
raise RuntimeError("Unable to set tool mass")
setMass also scales the inertia tensor with the mass change. If a tool’s
mass distribution changes, update its center of mass and inertia tensor as
well.
26.2.3. Contact geometries
An OpenPLX contact geometry maps to agxCollide::Geometry. Its collision
shape is accessed through that geometry. Visual geometries do not have this
mapping.
#include <agxCollide/Geometry.h>
auto geometry = objectMap->findMapped<agxCollide::Geometry>(
requireObject("robot.tool.contact_geometry"));
if (!geometry)
throw std::runtime_error("Tool contact geometry was not mapped");
geometry->setEnableCollisions(false);
Python provides findMappedGeometry overloads for OpenPLX Sphere,
Box and Cylinder contact geometries:
# Each path names a contact geometry of the indicated type.
for path in ("ball.sphere", "crate.box", "roller.cylinder"):
geometry_ref = require_mapped(
object_map.findMappedGeometry(require_object(path)), path)
geometry_ref.get().setEnableCollisions(False)
26.2.4. Mates and constraints
Map the mate itself, for example robot.joint1.mate, rather than the
robotics joint system containing it. Request agx::Constraint to accept
different constraint implementations, or a concrete type when that type is
required. For example, a hinge configured with clearance can map to a slack
hinge instead of agx::Hinge.
#include <agx/Constraint.h>
#include <agx/Hinge.h>
auto constraint = objectMap->findMapped<agx::Constraint>(
requireObject("robot.joint1.mate"));
if (!constraint)
throw std::runtime_error("Joint mate was not mapped");
constraint->setEnableComputeForces(true);
// Use a concrete type only when the model produces that type.
auto hinge = objectMap->findMapped<agx::Hinge>(
requireObject("robot.joint1.mate"));
if (hinge) {
const auto angle = hinge->getAngle();
// Use angle in the application.
}
Python provides findMappedConstraint overloads for OpenPLX Hinge,
Prismatic, Lock and Cylindrical interactions. They return
agx.ConstraintRef:
for path in ("hinge", "prismatic", "lock", "cylindrical"):
constraint_ref = require_mapped(
object_map.findMappedConstraint(require_object(path)), path)
constraint_ref.get().setEnableComputeForces(True)
For a known regular hinge, constraint_ref.get().asHinge() gives access
to hinge-specific methods. Check the downcast before using it.
26.2.5. Motors, springs and ranges (C++)
One OpenPLX interaction can produce both an AGX constraint and a secondary
controller. Select the controller’s type when changing its operating value.
The following examples cover Physics3D.Interactions.TorqueMotor,
LinearSpring and RotationalRange, respectively:
#include <agx/ElementaryConstraint.h>
auto motor = objectMap->findMapped<agx::TargetSpeedController>(
requireObject("robot.disturbanceTorque1"));
if (!motor)
throw std::runtime_error("Torque motor was not mapped");
// Equal lower and upper bounds prescribe a torque in Nm.
motor->setForceRange(5.0, 5.0);
auto spring = objectMap->findMapped<agx::LockController>(
requireObject("suspension.spring"));
if (!spring)
throw std::runtime_error("Spring controller was not mapped");
spring->setPosition(0.25);
auto range = objectMap->findMapped<agx::RangeController>(
requireObject("robot.joint1.range"));
if (!range)
throw std::runtime_error("Range controller was not mapped");
range->setEnable(false);
Physics3D force and velocity motors also use
agx::TargetSpeedController. This does not imply that a
DriveTrain.TorqueMotor maps to the same type. For normal control of
actuators, the OpenPLX signal/control interfaces provide their declared
inputs, such as torque_input, without requiring AGX-specific lookups.
26.2.6. Drivetrain units and connectors
Drivetrain bodies map to powerline units, while couplings such as gears map to powerline connectors. In C++, request the appropriate concrete type:
#include <agxDriveTrain/Shaft.h>
#include <agxDriveTrain/Gear.h>
auto shaft = objectMap->findMapped<agxDriveTrain::Shaft>(
requireObject("robot.joint1.drive_train.motor_shaft"));
if (!shaft)
throw std::runtime_error("Motor shaft was not mapped");
const auto angularVelocity = shaft->getAngularVelocity();
auto gear = objectMap->findMapped<agxDriveTrain::Gear>(
requireObject("robot.joint1.drive_train.gear"));
if (!gear)
throw std::runtime_error("Gear was not mapped");
const auto ratio = gear->getGearRatio();
A DriveTrain.FlexibleGear maps to agxDriveTrain::HolonomicGear.
For LinearElastic flexibility with stiffness k > 0 and
MechanicalDamping with damping constant c, AGX stores compliance
1 / k and relaxation time c / k. To change damping during runtime,
use the latter conversion:
#include <openplx/DriveTrain/FlexibleGear.h>
#include <openplx/Physics/Interactions/Flexibility/LinearElastic.h>
auto gearModel = std::dynamic_pointer_cast<openplx::DriveTrain::FlexibleGear>(
requireObject("robot.joint1.drive_train.gear"));
if (!gearModel)
throw std::runtime_error("Expected a FlexibleGear");
auto elastic = std::dynamic_pointer_cast<
openplx::Physics::Interactions::Flexibility::LinearElastic>(
gearModel->flexibility());
auto flexibleGear = objectMap->findMapped<agxDriveTrain::HolonomicGear>(gearModel);
if (!flexibleGear || !elastic || elastic->stiffness() <= 0.0)
throw std::runtime_error("Expected a mapped gear with positive stiffness");
const double dampingConstant = 1.0;
flexibleGear->setViscousDamping(dampingConstant / elastic->stiffness());
Python exposes this lookup as findMappedFlexibleGear. Keep the returned
agxDriveTrain.HolonomicGearRef and use .get() to access the gear:
from openplx.DriveTrain import FlexibleGear
from openplx.Physics.Interactions.Flexibility import LinearElastic
gear_model = require_object("robot.joint1.drive_train.gear")
if not isinstance(gear_model, FlexibleGear):
raise RuntimeError("Expected a FlexibleGear")
elastic = gear_model.flexibility()
if not isinstance(elastic, LinearElastic) or elastic.stiffness() <= 0.0:
raise RuntimeError("Expected positive linear elastic stiffness")
gear_ref = require_mapped(
object_map.findMappedFlexibleGear(gear_model),
"robot.joint1.drive_train.gear")
damping_constant = 1.0
gear_ref.get().setViscousDamping(damping_constant / elastic.stiffness())
If stiffness has also been changed directly in AGX, use that current stiffness when computing the relaxation time. The OpenPLX value need not reflect later AGX changes.
26.2.7. Assemblies and frames (C++)
A nested Physics3D.System maps to an agxSDK::Assembly. Transform
objects map to agx::Frame: use the system’s local_transform, a body’s
kinematics.local_transform or kinematics.local_cm_transform, or a
contact geometry’s local_transform.
#include <agxSDK/Assembly.h>
#include <agx/Frame.h>
#include <agx/ObserverFrame.h>
auto robot = objectMap->findMapped<agxSDK::Assembly>(requireObject("robot"));
if (!robot)
throw std::runtime_error("Robot assembly was not mapped");
auto toolFrame = objectMap->findMapped<agx::Frame>(
requireObject("robot.tool.kinematics.local_transform"));
if (!toolFrame)
throw std::runtime_error("Tool frame was not mapped");
const auto toolTransform = toolFrame->getMatrix();
auto observer = objectMap->findMapped<agx::ObserverFrame>(
requireObject("robot.tool.tcp_connector"));
if (!observer)
throw std::runtime_error("TCP connector has no observer frame");
The last lookup requires a mate connector that was mapped to an observer
frame, for example by adding the .agx_observer_frame: true annotation.
An ordinary mate connector’s internal constraint frame is not automatically
available through this lookup. To obtain the root assembly directly, use
result.assembly().
26.2.8. Sensors and terrain tools (C++)
Sensor lookups use the sensor logic object. For example, a
Sensors.PulsedLidarLogic maps to an agxSensor::Lidar; the enclosing
sensor body and its visual geometry are separate objects. A
Terrain.Shovel maps to an agxTerrain::Shovel, which is a terrain tool
instance, separate from its bucket rigid body.
#include <agxSensor/Lidar.h>
#include <agxTerrain/Shovel.h>
auto lidar = objectMap->findMapped<agxSensor::Lidar>(
requireObject("robot.lidar.logic"));
if (!lidar)
throw std::runtime_error("Lidar logic was not mapped");
auto shovel = objectMap->findMapped<agxTerrain::Shovel>(
requireObject("shovel"));
if (!shovel)
throw std::runtime_error("Shovel was not mapped");
shovel->setEnable(false);
These lookups require the corresponding sensor or terrain objects to have
been created during loading. Not every object listed elsewhere in this
mapping guide is indexed by AgxObjectMap. For example, retrieve a body’s
mass properties through the body, and a collision shape or material through
its geometry.
26.2.9. Python lookup methods
The currently exposed Python methods are:
Method |
OpenPLX input type |
Return type |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
Other C++ findMapped<T> instantiations are not exposed as Python methods.
An unsupported Python argument type raises an overload/type error; a
supported argument without a matching AGX object returns an empty reference.
26.2.10. Runtime updates and lookup modes
Changing an OpenPLX object with setDynamic does not automatically update
the already mapped AGX mass, stiffness or damping. Apply runtime parameter
changes to the AGX object, or use an OpenPLX input supported by the
signal/control interface. AGX setters likewise do not write the new values
back to the OpenPLX objects. Apply updates on the simulation thread between
steps, or while simulation stepping is otherwise synchronized.
Prefer the map supplied by LoadResult. It includes the assembly,
powerline and sensor environment used during loading. The default lookup
mode uses UUIDs derived from the OpenPLX object’s UUID and type, so the
OpenPLX UUID string should not be assumed to equal the AGX UUID string.
When working with an existing assembly instead, a map can be created
explicitly. For name-based lookup, the AGX names must match the full names
returned by the corresponding OpenPLX objects’ getName():
auto nameMap = agxopenplx::AgxObjectMap::create(
result.assembly(), result.power_line(), nullptr,
agxopenplx::AgxObjectMapMode::Name);
This example includes drivetrain objects but omits sensors. Supply their
agxSensor::Environment* as the third argument when needed. Transform
agx::Frame entries are indexed only in UUID mode. Recreate an explicitly
built map when adding objects that need to be indexed.
26.3. Core object / ID / transform mapping
OpenPLX |
AGX |
Notes |
|---|---|---|
|
|
The name of an object in AGX is generally the full OpenPLX name including all namespaces with dot separation. |
|
|
A .uuid: annotation in an OpenPLX object mapped to AGX will enforce that to the created AGX object. If no annotation exist AGX will generate a new uuid. |
|
|
|
|
|
The OpenPLX system tree maps to an assembly tree in AGX. Systems include bodies and geometries. Bodies include geometries. |
|
|
Pose computed from main axis/normal/position; observer frames preserved for AGX-imported connectors. |
26.4. Bodies & mass properties
OpenPLX |
AGX |
Notes |
|---|---|---|
|
Kinematics declaration for rigid bodies. Container of velocities and transforms. |
|
|
Inertia declaration for rigid bodies. Contains scalar mass and inertia tensor. |
|
|
|
is_dynamic: True → DYNAMICS; otherwise KINEMATICS. |
|
|
Negative mass → error. Auto-generate if not given. |
|
|
CM rotation applied to tensor; SPD validation. |
|
|
Local transform relative owning system. |
|
|
Local CM transform relative the local transform. In AGX the rotation must match model frame. Keep identity rotation! |
|
|
The local OpenPLX velocities will be transformed to world in AGX. |
26.5. Geometry (contact shapes & attributes)
OpenPLX |
Attributes |
AGX mapping |
Notes |
|---|---|---|---|
|
|
|
An OpenPLX ContactGeometry maps to an agx::Geometry with a single shape. |
|
|
|
Size mapped with 0.5 factor per axis for half-extents. |
|
|
|
The Y axis is the default cylinder axis in AGX. |
|
|
|
The Y axis is the default capsule axis in AGX. |
|
|
|
|
|
|
|
Built via |
|
|
|
Built via |
|
|
|
Path must be absolute; scale → diagonal of |
26.6. Materials & surface contact
OpenPLX |
AGX |
Notes |
|---|---|---|
|
|
Name/UUID; density → |
|
|
A material model that models Young’s modulus. |
OpenPLX |
Alternatives |
AGX mapping |
Notes |
|---|---|---|---|
|
Configurable with attributes listed below. |
|
Created/uniqued per material pair in AGX. , |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Clearance also maps to slack in a SlackHinge, SlackPrismatic. |
|
A non zero scalar value. |
|
Restitution in the direction of a contact normal. |
|
A non zero scalar value. |
|
Restitution orthogonal to the contact normal. Not mapped to support a different restitution in the secondary direction. |
26.7. Interactions & constraints
- An
agx::Constraintis created using frames computed from its mate connectors and their respectiveagx::RigidBody. Each DOF’s compliance and damping (relaxation time) is set from the corresponding OpenPLX flexibility/dissipation component (see section below). Friction controllers on supported constarints are configured from PLX friction. frictionmay becomeDefaultDryFriction,AsymmetricLimitFrictionorConstantLimitFriction.AsymmetricLimitFrictionandConstantLimitFrictionwill both setagx::FrictionController::setMinimumStaticFrictionForceRange.Names/UUIDs always propagated.
OpenPLX |
Notes on Attributes |
AGX mapping |
DOFs & extras |
|---|---|---|---|
|
Slack variant if |
|
Free to rotate around the |
|
Slack if |
|
Free to move along the |
|
|
Slack variant if |
Free to move along and rotate around the |
|
No slack version. No mapping of ranges implemented. |
|
Free to rotate around all axes. |
|
Slack variant if |
|
Slack if |
|
No slack version. No mapping of distance range or distance motor implemented. |
|
Constrained to keep the distance between the mate connectors, otherwise free to move. |
|
Add all rigid bodies you like to merge to the |
|
Bodies merged via |
26.8. Regularization parameters
Most OpenPLX interactions, including mates and surface contact models,
have attributes for flexibility and dissipation which will map to compliance and damping in AGX.
The OpenPLX models are designed so that if the attributes does not become anything, the parameters will get the default AGX values.
The attributes are unique for each mate, listing one parameter for each degree of freedom (DOF).
Generally the local axes of a mate use the naming convention of the mate connectors, which are main, normal and cross.
Each regularization parameter is defined either around or along one of these axes.
flexibility alternatives:
Rigid→complianceset to machine-epsilon (nearly rigid).LinearElastic(stiffness)→compliance = 1/stiffness.stiffness == 0→ kill DOF (force range0).
dissipation alternatives:
ConstraintRelaxationTimeDamping→ maps directly to the AGX Spook damping parameter.agx::Constraint::setDamping.MechanicalDamping(damping)which requiresflexibilityto beLinearElastic(stiffness)→spook_damping = damping/stiffness.
26.9. Controllers: motors, ranges, springs (1-DOF controller constraints)
OpenPLX interactions also include springs, motors and ranges. These map to AGX controller constraints. Each controlling one degree of freedom with the possibility to declare regularization parameters.
OpenPLX |
AGX |
Notes |
|---|---|---|
|
|
|
|
Maps to |
Controlled in runtime by updating the force range with required_effort = min = max. |
|
|
Range |
|
|
Position/angle set; force range; enable; |
Annotation |
Reuse existing AGX constraint’s motor/range/lock |
Present when importing an .agx file, looks up constraint by UUID and attaches controller to the correct DOF. |
Annotation |
|
|
26.10. Environment, collisions & signals
OpenPLX |
AGX |
Notes |
|---|---|---|
|
|
Vector or center+magnitude mapped. |
|
Geometry/group assignment |
Adds all bodies/geometries/systems to AGX groups; respects nested systems. |
|
|
Applied recursively in |
|
|
Ensures frames exist for source and relative connectors (world excluded). |
26.11. Friction on constraints (non-contacts)
OpenPLX |
AGX |
Notes |
|---|---|---|
|
|
Dry/limit frictions converted to coefficient or static force ranges; controller disabled if unsupported in PLX side. |
26.12. Annotations reference
Controller reuse:
agx_imported_controller_constraint(UUID of an AGX constraint to attach to).Constraint solve:
agx_solve_type(DIRECT,DIRECT_AND_ITERATIVE,ITERATIVE).Friction solve:
agx_friction_solve_type(DIRECT,SPLIT,DIRECT_AND_ITERATIVE,ITERATIVE) +agx_approximate_cone_friction(boolean).Oriented friction:
reference_body/reference_geometry+primary_direction (Vec3).Terrain material:
agx_terrain_material(string).Observer frames:
agx_observer_frame_annotation/agx_debug_frame_annotationon MateConnectors.Track-specific:
agx_track_*,agx_set_*(see Tracks table).
26.13. Notes on error handling (high-level)
Invalid/duplicate material pairs, bad inertia tensors, negative mass, missing connected bodies, misplaced connectors, invalid OBJ/Trimesh, invalid friction frame, etc., are reported via the provided ErrorReporter and guarded with warnings/fallbacks.