
Implementation of support for diverse industrial equipment and other RTC (Robotic Technological Complex) components is provided by a system of pluggable modules. To deploy a production line, it is necessary to provide all the required components, including RTC modules.
One of the functions of the IndustrialBuilder application, designed specifically for production deployment, is the development and assembly of such modules. This document-oriented application operates on Standard Template Construct documents. Processing an STC package results in the formation of the production line in a specific manner.
In this material, we will examine the development of an STC package and its use in the task of synthesizing RTC modules.
Info
Let's create a new document and name it RTC Modules.
In the "Package" section, we can edit the STC header file – we can set a detailed description of the packages, and a gallery of explanatory images. Function calls for STC processing are also available here via the toolbar.
We will create a set of four modules of one type each – for a robot, a tool, a part, and an IMA software element.
Components
This is essential material for forming any production line. Currently, it is represented by images, scenes, program listings, and kinematics.
Components can be added either by simply dragging and dropping them into the corresponding Resources sections, or by selecting them from files using the
button on the toolbar. Empty listings can also be created with the
button and edited. Editing of scenes and images is not supported.


Let's add a set of components – an image and two models.
A separate, specific type of resource is the kinematic group. It represents a named list of kinematic elements with a parameter indicating the type of kinematics. The kinematic element itself is a named and identifiable Float value.
Unlike other resources, which are placed in the model module package in one way or another during composition, kinematics are used for resource synthesis. Kinematic processing is implemented by IndustrialBuilder, currently supporting the synthesis of robots with 6DOF and Portal kinematics.
Let's create 6DOF kinematics and set the base height to 100 mm.
Modules
The digital entity of a production object is implemented by the program
code of itself and a virtual model that reproduces the visual and
physical properties associated with the production object.
Thus, a module that provides the program code for the digital twin and
the model components must be assembled from the corresponding resources.
The program code is described in text files-listings, while the model is
assembled from a set of scenes (a SceneKit Scene format file with a scn extension) and textures (various raster graphics formats).
The current version of Industrial Builder allows you to create and edit
modules of four types – for production objects (Robot, Tool, Part) and
Changer elements.
Editing all module components is performed in the Module Designer. The
set of components available for editing varies depending on the module
type. Visual model editing is available for robots, tools, and parts.
Module | Robot | Tool | Part | Changer |
---|---|---|---|---|
Description | + | + | + | + |
Operations | - | + | - | - |
Code | Controller, Connector | Controller, Connector | - | Change |
Resources | + | + | + | - |
Connection Parameters | + | + | - | - |
Linked Internal Components | + | + | - | - |
Let's go through all the elements of the Modules disclosure group and add the modules.
We'll start with the part. In the list of modules on the right, let's add a new module named Armoire. Next, let's go to the module designer, and in "Resources," we'll assign the texture and scene of the armoire. In the scene's context menu, we'll select "Is main scene", specifying it as the main one.
We will examine working with the listing using the example of creating the Changer – Random module. We will generate the listing depending on the type of module being created (external or internal).
We will supplement the created function so that it fills all memory registers with random values.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// Change Func | |
// | |
import Darwin | |
//MARK: - Main | |
guard CommandLine.arguments.count > 0 else { exit(1) } | |
var registers: [Float] = CommandLine.arguments.dropFirst().compactMap { Float($0) } | |
change(registers: ®isters) | |
print(registers.map { String($0) }.joined(separator: " "), terminator: "") | |
//MARK: - Function | |
func change(registers: inout [Float]) | |
{ | |
for i in 0..<registers.count | |
{ | |
registers[i] = Float(Int.random(in: 0...200)) | |
} | |
} |
Let's create a tool module named Spatula. We'll select the single scene and set it as the main one. Because the tool is controlled, we also specify a set of nodes that will be controlled by the model's controller. We are only interested in the stiffener node.
Next, we define a list of available operation codes. We will have a pair – one for rotating the stiffener clockwise and one counter-clockwise (by 90º).
Now, let's create the model controller listing code. It processes the value of the incoming operation code and returns a SCNAction command.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
private var moved = false | |
override func nodes_perform(code: Int, completion: @escaping () -> Void) | |
{ | |
if nodes.count == 1 // Gripper model has two nodes of jaws | |
{ | |
switch code | |
{ | |
case 0: // Clockwise rotation | |
if !moved | |
{ | |
moved = true | |
nodes[safe_name: "stiffener"].runAction(.rotate(by: .pi / 2, around: SCNVector3(0, 1, 0), duration: 0.1)) | |
{ | |
self.moved = false | |
completion() | |
} | |
} | |
else | |
{ | |
completion() | |
} | |
case 1: // Counter-clockwise rotation | |
if !moved | |
{ | |
moved = true | |
nodes[safe_name: "stiffener"].runAction(.rotate(by: -.pi / 2, around: SCNVector3(0, 1, 0), duration: 0.1)) | |
{ | |
self.moved = false | |
completion() | |
} | |
} | |
else | |
{ | |
completion() | |
} | |
default: | |
moved = false | |
completion() | |
} | |
} | |
else | |
{ | |
completion() | |
} | |
} |
Finally, let's create a robot module named Lowbot. We will generate its content from a 6DOF kinematic model. To do this, we return to the kinematic model created earlier, tap the
button, and export it to the robot module.

Building
Sets of assembled modules are defined in assembly sheets. Each list consists of four lists, corresponding to the four module types: Robot, Tool, Part and Changer.
Let's proceed to create and edit a set of lists. To do this, in the Package section, open the Build assembly tool, accessible via the
button.

We create two lists – External and Internal. In the first, we'll define the tool and part modules. In the second, the robot and tool modules.
There are two assembly types available – Files for exporting modules as a set of external pluggable packages, and App, for exporting as packages embedded within the application project and compiled with it.
Processing
When assembling internal modules, a Modules folder is created, containing a set of module packages and a List file, which initializes the internal_modules tuple of arrays. The module header file becomes a listing with the prefix _Info, containing the initialization code for an instance of the module's class.
Next, a function is executed that creates a set of listings according to the name and contents of the code items in each processed module. For robots and tools, it also injects the scene node list into the model's controller code, and connection parameters for the connector. All listing files for a single module are placed in the Code folder of the module package and are prefixed with <module name>_, which is necessary to ensure correct compilation during subsequent assembly within the application project.
Next, resources are saved to the Resources.scnassets folder, similar to the creation of an external module package.
The finished Modules folder with internal modules is enough to place in the RCWorkspace application project and compile it.
When assembling external modules, the module's data is saved in the Info header file.
Next, similarly to internal modules, code elements are saved in the corresponding Code folders of the module's package file. However, no parameters are injected into the code listings, as the relevant data (model node list, connection parameters) are saved in the header file.
The final stage of module export is saving its resources in the Resources.scnassets folder.
After all external modules have been composed and placed in the export folder, Industrial Builder additionally places a set of scripts in the folder for compiling program component listings of modules into Unix executables. In versions for iOS, iPadOS, and visionOS, the export of external modules is completed at this stage, since they lack a terminal. In macOS, compilation can be launched directly from Industrial Builder.
The compilation kit includes the following scripts:
- LtPConvert – Converts the specified listing file into a swift package for a terminal application project. The Unix executable compiled by this project receives the same name as the original listing. The package name consists of the listing name and the _Project postfix. The latest version of the IndustrialKit library is also linked to the project.
- PBuild – Compiles the project package into an executable file, which it places in the same directory as the project.
- LCompile – Converts the listing into a Unix executable. This script actually executes the LtPConvert and PBuild scripts sequentially. When called with the -c parameter, it also deletes the original listing and the executable's project package file after execution.
- MPCompile – Compiles the program components of all modules (having extensions robot, tool, part, changer) located in the same folder as the script itself. It finds all Swift files and executes the LCompile script with the -c parameter for them.
This compilation kit allows you to supplement, edit the source code of external modules and compile them independently of IndustrialBuilder. Also, deferred compilation is necessary when exporting external modules on platforms that do not have a terminal.
Conclusion
We have reviewed one of the functions of an automated production preparation tool – the development of industrial modules. The mastered functionality allows us to expand support and integrate a variety of robotic equipment, components of production equipment, as well as expand the software functionality of the RTC control system.