A Modular Script Interpreter API
WitEngine is a powerful API designed to build easily extensible, modular script interpreters. It allows developers to create interpreters that can seamlessly manage and control a wide range of systems, from industrial hardware setups to software automation tasks, by combining different modular components into a unified interpreter.
What is WitEngine?
At its core, WitEngine consists of two main components:
Interpreter Host: The central engine that runs and manages scripts.
Controllers: Independent modules that extend the interpreter’s functionality by introducing new variables, functions, and operations.
The interpreter host dynamically loads controllers from a specified folder, assembling a cohesive interpreter tailored to the specific needs of your project. Each controller can define its own variables and functions, which become immediately available to any script running on the host. This modular approach allows scripts to seamlessly utilize resources from multiple controllers, provided they are loaded into the host environment.
Key Features
Modular Architecture: Easily add or remove controllers to customize the interpreter’s capabilities without altering the core system.
Extensibility: Developers can create new controllers to introduce additional functionality, variables, and operations.
Dynamic Scripting: Scripts can access and use functions and variables from any loaded controller, enhancing flexibility.
Independent Development: Controllers can be developed, tested, and debugged independently before integration.
No Recompilation Needed: Modify or add processes without recompiling or reinstalling the entire system.
Example Use Case: Photobox Setup
Let’s assume that we need to control a photobox setup with a rotating table, background screens, and multiple cameras—each of these devices can have its own controller. The rotating table might have functions for setting angles, the screen could have functions for changing colors, and the camera could have functions for taking snapshots at specific resolutions. Once the base functionality of each device is implemented in its controller, you can write simple scripts to manage different processes—like photographing cylindrical bottles from all angles or capturing images of box-like objects from different sides.
The process for photographing a cylindrical bottle involves:
Initial Positioning: Place the bottle on the rotating table.
Background Adjustment: Change the background color to red.
Image Capture: Take a photo using the front camera.
Background Change: Switch the background to green and capture another photo.
Repeat Background Change: Alternate background colors and capture images.
Rotation: Rotate the table by a set angle (e.g., 10 degrees).
Iteration: Repeat the process until images are captured from all desired angles.
Processing script will look like this:
~IDG Segmentation for cylindrical (bottle-like) items ~
Job:SegmentationDefault(String:id)
{
~Variables~
Color:background; Double:degree; UEyeImage:callback;
~Process~
Screen.Init(#ScreenId#);
IDG.Segmentation.Init(#WorkFolder#, "Mask\mask.png", "Mask\area.xml");
Loop(36)
{
Camera.UEye.SetExposure(ueye1, #ExposureRgb#);
background = Screen.SwitchColor(255, 0, 0);
callback = Camera.UEye.Snapshot(red);
Return(callback);
background = Screen.SwitchColor(0, 255, 0);
callback = Camera.UEye.Snapshot(green);
Return(callback);
background = Screen.SwitchColor(0, 0, 255);
callback = Camera.UEye.Snapshot(blue);
Return(callback);
IDG.Segmentation.Process(#WorkFolder#, id, "0", degree, red, green, blue);
degree = Turntable.Rotate(10, "COM3");
}
Screen.Dispose();
}
For a box-shaped product, the process differs:
Initial Imaging: Photograph the box from four sides
User Interaction: Prompt the user to reposition the box.
Additional Imaging: Capture images of the remaining sides.
Processing script will look like this:
~IDG Segmentation for box items ~
Job:SegmentationBox(String:id)
{
~Variables~
Color:background; Double:degree; UEyeImage:callback;
~Process~
Screen.Init(#ScreenId#);
IDG.Segmentation.Init(#WorkFolder#, "Mask\mask.png", "Mask\area.xml");
~Stage 1~
Loop(4)
{
Camera.UEye.SetExposure(ueye1, #ExposureRgb#);
background = Screen.SwitchColor(255, 0, 0);
callback = Camera.UEye.Snapshot(red);
Return(callback);
background = Screen.SwitchColor(0, 255, 0);
callback = Camera.UEye.Snapshot(green);
Return(callback);
background = Screen.SwitchColor(0, 0, 255);
callback = Camera.UEye.Snapshot(blue);
Return(callback);
IDG.Segmentation.Process(#WorkFolder#, id, "0", degree, red, green, blue);
degree = Turntable.Rotate(90, "COM3");
}
Prompt("RepositionBoxMessage");
Double:degree1;
~Stage 2~
Loop(2)
{
Camera.UEye.SetExposure(ueye1, #ExposureRgb#);
background = Screen.SwitchColor(255, 0, 0);
callback = Camera.UEye.Snapshot(red);
Return(callback);
background = Screen.SwitchColor(0, 255, 0);
callback = Camera.UEye.Snapshot(green);
Return(callback);
background = Screen.SwitchColor(0, 0, 255);
callback = Camera.UEye.Snapshot(blue);
Return(callback);
IDG.Segmentation.Process(#WorkFolder#, id, "1", degree1, red, green, blue);
degree1 = Turntable.Rotate(180, "COM3");
}
Screen.Dispose();
}