- Content Creation
- Using an Application
- Definitions and Instances
- Creating Content in C++
- Dynamics Objects
- Other Content Extensions
- Content Creation in Python
- Content Creation Tutorials
The main tool for content creation is the Vortex® Studio Editor. The Editor manages all the dependencies between the documents. For example, it ensures that a change in a mechanism document is reflected in the scene where that mechanism is being used.
However, a user could want to automatically create content in code (in C++ or Python) but some key concepts must be understood for that content to be compatible with Vortex Studio. The reader is expected to understand extensions, smart interfaces and fields, described in Customizing Vortex.
Vortex Studio SDK internally uses its own concepts. Content classes are IObjects. While some content classes can be created and manipulated without a Vortex application, many features (e.g., configuration) will not work without a VxApplication. The Vortex Studio Editor is a VxApplication, working in Editing mode when content is being created. It is recommended to create or edit content using a VxApplication. Objects being edited should be added to the application before editing them.
The Vortex Studio Editor allows you to create five types of content documents: Part, Assembly, Graphics Gallery, Mechanism and Scene. When a user creates a part (or any other content object), it creates a definition. When a user inserts that part into an assembly, it uses a special copy of that definition, called an instance.
- Application Setups (i.e, class ApplicationConfig) are also definitions, but they are not content and work slightly differently. Setups are not covered in this section.
A definition consists of a main IObject (the parent) and some associated instances of IObject and IExtension (the children) saved into a file. An instance is a copy of a definition that remembers the definition it came from. To put a definition object into another, it must be instantiated.
Since an instance remembers its definition, when that definition changes, the instance can receive the changes via the synchronization operation called
The sync operation only brings the definition data to the instance. Definition data are the parameters of an object, as well as all the data of its children. The presence and order of the children are also definition data.
In addition to definition data, there is also instance data. Instance data are the inputs/outputs distinct in each instance and are saved within the parent's definition.
There are two exceptions to this rule:
- The inputs and outputs values of a VHL interface extension, which can be a child of a mechanism or a scene, are instance data.
- The field inputActivate of a Configuration is instance data. A configuration in a mechanism is usually activated at the scene level.
The editor handles definitions, instances and sync properly without manual intervention. For example, to get the changes in the number of collision geometry of a part in a scene, the part instances of the assembly definitions using it must be synced, then the assembly instances must be synced and so on up to the scene. It is a manual process.
The Vortex Studio Editor has five types of definitions: part, assembly, Graphic Gallery, mechanism and scene, corresponding to the documents it can create. While the concept of a definition can be generalized, the editor would not know what to do with custom definitions.
A simulator should not need to perform those operations; they are editing concepts.
Adding a part to a assembly:
- The assembly is a definition (saved in a .vxassembly file). An inserted part in that assembly is an instance of a part definition (that was saved in a .vxpart file).
- Within the assembly document, the part instance can be positioned using the inputLocalTransform field. The field is an input, that field's instance data belongs to the definition data of the assembly.
- If the part is opened in its own document in the editor, the definition data is being edited, such as parameters like mass, and its children, the collision geometries.
- Any changes to the part's parameters and children (the collision geometries) will be synchronized to the assembly when going back to the assembly document in the editor. However, the position of the part instance will remain the same.
- Going up to the mechanism and scene levels works in an analogous way.
Objects can be saved with the VxObjectSerializer. Only definitions can be saved to a file.
The serializer can be used to load objects as well. Object loaded are thus definitions. When a definition containing instances is loaded, all the definitions of the instance will be loaded as well.
All the instances are automatically synchronized after a load.
// Create a part
- VxSimulationFileManager returns instances. When loading an object, the VxSimulationFileManager loads the definition, instantiates it and returns that instance. For content creation, it is recommended to use a VxObjectSerializer, since you will need to work with definitions. VxObjectSerializer does NOT distribute content in a distributed application.
Cloning is an operation to copy an object. A clone is independent of its source. Cloning a definition makes a definition. Cloning an instance makes an instance, linked to the same definition.
Instantiating creates a copy of a definition, the resulting object is an instance but a link is kept to its definition. You cannot create an instance of an object that is not a definition. As mentioned before, instances cannot be saved on their own into a file, but instance data are saved with their parent definition.
The synchronize operation consists of updating an instance's definition data to match its definition while keeping the instance data. Once done, the children of the object are fully updated to match the children of the definition object.
All Vortex objects are extensions. Extensions are plugins and as such an object can be created using the extension factory with the proper factory key. However, the recommended way of using Vortex Object is by using VxSmartInterface. If the factory key is part of the desired object (as member kFactoryKey), the create() function should be used.
// The following code creates an object of type MyExtension
Most content objects are dynamics. These are your mechanisms, assemblies, constraints, attachment, attachment points, parts, and collision geometries.
These dynamics objects are represented by interfaces in the code (e.g., part, box), while the implementation is actually a dynamics extension provided by the dynamics plugin (VxDynamics.vxp).
A header file describes the interface that should be used by the developer (e.g., VxDynamics/Part.h).
The header file gives access to everything the user needs to make it work: the factory key and fields to each input, output and parameter. Some utility functions are also provided.
An ICD header file describes the name of each input, output and parameter should a user needs to access them in a generic fashion from a VxExtension.
Dynamics objects part, assembly and mechanism can be loaded and saved to disk.
Every dynamics object that can be moved implements the IMobile Interface. The position of an IMobile is set by the input inputLocalTransform and the actual position of an object is given by the output outputWorldTransform.
The following code is an example of using a box collision geometry extension.
The following code is an example of creating a part.
The following code is an example of creating an assembly.
The following code is an example of creating a hinge constraint with minimal inputs.
The following code is an example of creating an attachment with two attachment points, each referencing a different part. The example attaches part together by adding an attachment to the assembly.
Attachments can be added to a mechanism or a scene to attach assemblies or mechanisms, respectively.
The following code is an example of creating a mechanism.
Scenes are where you put all your mechanisms for your simulation.
VHL Interfaces are extensions that give direct access to its children's fields by mapping it to a VHL field. VHL Interface can be added to a mechanism or a scene.
Adding inputs, outputs or parameters is available through the interface.
|VHL Interface in mechanism|
// Create the VHL extension
Connection containers are extensions that contain connections between fields. Fields that can be connected must be children of the connection container's parent, typically a mechanism.
Adding connections is available through the interface.
// Create the connection container extension
Python scripting extensions are standard extensions to control an aspect of the simulation in code. These are handled by the dynamics module and are added to a mechanism or a scene.
The script file parameter refers to the .py file to execute. It is also possible to set the Python code to execute as a string in the code parameter, but it is less convenient for editing.
The script extension can be edited to dynamically add inputs, outputs and parameters that can be used by the Python script.
The added fields can be referred by the script using
self.outputs .<field added>,
self.parameters .<field added>, where
<field added> is the name of the field with invalid characters replaced by underscore. The value is available from the value property of the Python field.
|Python scripting extension|
// Create the Python scripting extension
Configurations are extensions used by mechanisms and scenes to configure them. By this, we mean that a configuration is a set of modifications to the content that can be applied or not. The main goal is to make the mechanism or scene more reusable. Rather than having multiple copies of the object with just a small number of differences, configuration allow you to keep one base object and as many distinct configurations as you want.
Configurations are set when the application is in editing mode, before the simulation is run. They cannot be changed in simulation mode.
- When added to an object (a mechanism or a scene), VxContent::Configuration can reference other extensions in the same object, allowing you to modify inputs and parameters of referenced extensions or remove them from content.
- A configuration does not create extensions; the extensions must be in the object without configuration.
- An object can have multiples configurations.
- A configuration is only a set of modifications to be applied to one or many referenced extensions. The type of modifications are called actions.
- The actions are applied on the referenced extensions when activated.
- Multiple configurations can be activated at the same time, but a configuration cannot be activated if there is a conflict between changes.
- Activation can only happen while the application is in editing mode.
A configuration can do one of the following actions, given by enum eConfigurationAction, on a given referenced extension:
- Modify (kModify) :
- When configuration is activated, selected inputs/parameters values are modified in the referenced extension; the referenced extension will be sent to the modules normally.
- When configuration is not activated, all inputs/parameters values are untouched in the referenced extension; the referenced extension will be sent to the modules normally.
- This is the default action.
- Remove (kRemoveOnActivation) :
- When configuration is activated, the referenced extension will not be sent to the modules.
- When configuration is not activated, the referenced extension will be sent to the modules normally; all inputs/parameters values are untouched in the referenced extension.
- Add (kAddOnActivation):
- When configuration is activated, the referenced extension will be sent to the modules normally; selected inputs/parameters values are modified in the referenced extension.
- When configuration is not activated, the referenced extension will not be sent to the modules.
Two configurations will be in conflict if:
- They are modifying values in the same extensions.
- One configuration modifies values and the other wants to remove the extension.
- One configuration wants to add an extension, and the other wants to modify or remove the same extension.
The configuration extensions are handled by the Configuration Module. The module is part of a VxApplication and does not need to be added by the application setup.
The activation of a configuration is not instantaneous, it requires an update so that it can be treated by the Configuration Module and propagated properly across the network.
The field inputActivate is instance data, activating a configuration in a mechanism definition won't affect which configurations are activated in the scene. An activated configuration in the definition only affects which configurations will be activated when the instance is created.
A configuration in a scene can refer to a configuration in a mechanism instance, allowing you to use the configuration of a scene to configure a mechanism.
Activating or editing a configuration must be done in editing mode. Adding references should be done when the extension is not activated. In order to have a different set of inputs or parameters values for a reference extension, it must be added to a configuration (with action kModify or kAddOnActivation), then the configuration must be activated. When a user edits the values of a referenced extension, the changed values will only be in effect when the configuration is activated. The code sample below shows an example.
The Configuration API offers several functions to ease edition.
- Function addReference() allows you to reference an extension in a configuration, with one of the following actions: kModify, kRemoveOnActivation or kAddOnActivation.
- Function removeReference() allows you to remove a reference to an extension in a configuration. The returned object can be kept to revert the removed extension with all of its modifications.
- To activate the configuration, field inputActivate should be set to true. It requires an update to be propagated.
- If there is a conflict, configuration will not be activated but will stay in that state. If the conflict gets resolved, it will activate on its own.
- Use field outputActivated to determine activation success.
- Use function getRuntimeErrors() to find a conflict in activation.
- Function canActivate() should be called before setting inputActivate to true, to know what will be the result of the activation.
- Function restoreReference() allows you to restore a removed extension with its set of modifications.
- Function getReferencedExtensions() allows you to consult the referenced extensions with their associated actions within a configuration.
|Configuring a mechanism|
Content can be created in Python as well. See Python Scripting for more information.
The purpose of this tutorial is to show how to create a rover sample loadable in the Editor and the Player, using C++ code. The rover has no graphics but it shows the features described above. This tutorial is found in your Vortex Studio installation folder.
Next topic: Python Scripting
Vortex® Studio 2019b by CM Labs | Last update: 11:51 AM, 9/25/2019 — Release 2019.12.0.56 | © CM Labs Simulations Inc.