Help
  • Explore Community
  • Get Started
  • Ask the Community
  • How-To & Best Practices
  • Contact Support
Notifications
Login / Register
Schneider Electric
Community
Community
Notifications
close
  • Categories
  • Forums
  • Knowledge Center
  • Blogs
  • Ideas
  • Events & Webinars
Help
Help
  • Explore Community
  • Get Started
  • Ask the Community
  • How-To & Best Practices
  • Contact Support
Login / Register

Contact Support

Close

Ask our Experts

Have a question related to our products, solutions or services? Get quick support on community Forums

Email Us

For Community platform-related support, please email us

New Community Ranking System
Our Community ranking system has recently been updated. You may notice changes in user rankings and receive system messages or notifications. If you have questions about how the new ranking works, please refer to the announcement post for more details (click here).

Digital Twin

This knowledge base is addressing usage of software Experior, Machine Expert Twin and future Automation Expert Twin. These softwares are used to create smaller instances of digital twins for use in industrial automation, warehouse management, design & engineering with more..

Search in

Improve your search experience:

  • Exact phrase → Use quotes " " (e.g., "error 404")
  • Wildcard → Use * for partial words (e.g., build*, *tion)
  • AND / OR → Combine keywords (e.g., login AND error, login OR sign‑in)
  • Keep it short → Use 2–3 relevant words , not full sentences
  • Filters → Narrow results by section (Knowledge Base, Users, Products)
cancel
Turn on suggestions
Auto-suggest helps you quickly narrow down your search results by suggesting possible matches as you type.
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Select a Country

Please select a country to continue with beta search.

  • Home
  • Schneider Electric Community
  • Knowledge Center
  • Digital Twin
Options
  • Knowledge Base Article Dashboard
  • Subscribe
  • Bookmark
  • Invite a Friend
Invite a Co-worker
Send a co-worker an invite to the portal.Just enter their email address and we'll connect them to register. After joining, they will belong to the same company.
You have entered an invalid email address. Please re-enter the email address.
This co-worker has already been invited to the Exchange portal. Please invite another co-worker.
Please enter email address
Send Invite Cancel
Invitation Sent
Your invitation was sent.Thanks for sharing Exchange with your co-worker.
Send New Invite Close
Labels
Top Labels
  • Alphabetical
  • Experior 6 85
  • Experior 7 57
  • Exp-6 Developer Guide 35
  • Exp-7 Developer 16
  • Exp-6 User Guides 16
  • Exp-7 Communication Protocols 11
  • Exp-6 Experior 11
  • Exp-6 Communication Protocols 11
  • Exp-7 Getting Started 10
  • Exp-6 Dev Environment 9
  • Exp-7 User Interface 9
  • Exp-6 Dev Assembly 7
  • Exp-7 Building Models 6
  • Exp-7 Working With Models 5
  • Exp-6 PLC 4
  • Exp-6 Getting Started 3
  • Exp-7 Importing Graphics 3
  • Exp-6 3rd Party Programs 2
  • Exp-6 Tips and Tricks 2
  • Remote Viewer 2
  • Exp-6 Model Modifications Examples 1
  • Previous
  • 1 of 3
  • Next
Top Contributors
  • Kasper.Vestrup
    Kasper.Vestrup
See More Contributors

Related Forums

  • Intelligent Devices Forum

Previous Next

Invite a Colleague

Found this content useful? Share it with a Colleague!

Invite a Colleague Invite

Digital Twin

Sort by:
Likes
  • Date
  • Views
  • Likes
Options
  • Knowledge Base Article Dashboard
  • Subscribe
  • Bookmark
  • Invite a Friend
  • « Previous
    • 1
    • 2
    • 3
    • …
    • 8
  • Next »

Setting up URSim with Experior 6

Before you start, make sure you have the Universal Robots Experior catalogs: • Experior.Catalog.UniversalRobots.dll • UniversalRobotsCommunication.dll   Afterward, follow these steps   Robot controller connection The following steps will connect the Experior URX assembly to the robot controller in URSim.   1. Place the Experior UR catalog (.dll) files in the Experior 6 installation folder (usually C:\Xcelgo\Xcelgo Experior 6).   2. Download and unpack/install the following: a. UR Non-Linux Offline simulator virtual machine (URSim):  b. VMware Workstation Player    3. Open VMware Workstation. Open the URSim virtual machine (Player-File-Open, then browse the file explorer to where you unpacked the files from 2.a., then select the .vmx file).    4. When the virtual machine is running, open the file with the name of the robot that you want to simulate. Then, turn the virtual robot on using the button on the bottom left. Then click ON and START.   5. Open Experior 6.0. Make sure the UniversalRobots catalog is selected in the catalog selector. Drag and drop the desired robot from the Catalogs panel to the model.   6. Go to URSim and open the robot settings.   In the settings menu, select System-Network. Note the URSim IP address.   7. Connect URSim to Experior. Do this by going to your Experior model, selecting the robot, and writing the URSim IP address in the IP Address field, under Robot connection. 7.1 Afterward, right-click on the robot and select Connect to robot controller. After this, the robot in Experior will snap into the position of the robot in URSim.       After this, the robot in Experior will replicate the trajectory of the robot in URSim.   Connecting robot I/O through Modbus TCP The following steps show how to connect the robot I/O through the URSim Modbus server and the Experior Modbus client.   1. In URSim, go to Installation- Fieldbus- Modbus- Add a new signal. (Initially, the variable list will be empty) In the dropdown menu, select the variable type: Digital Input/Output, Register (byte) Input/Output. Rename the variable (this is the name that will be used in the UR programming interface)   2. Assign the memory address for the variable. For this, you need to take into account that all the addresses have specific uses (see here).   3. In Experior, add the Modbus client by right-clicking the Communication panel, and selecting Modbus.     4. Select the Modbus client, and in the Properties panel, write the URSim IP address in the IP Address field, under Communication.     5. Assign Input/Output variables to the desired components. To do this, first set the Connection id to the id corresponding to the Modbus client. Then, assign the memory address of the Modbus server (assigned in step 2) in the Address field for the specific Input/Output. Modify the Register value, depending on the variable type defined in step 2. For Register Inputs/Outputs, Modify the Size value to UInt16 (WORD).   6. After all the memory addresses have been set in Experior, right-click on the Modbus client and click connect. While the connection is active, you won´t be able to modify the associated I/O in Experior.     After this, the variable values will be represented in the Experior model.   (This example was made with the Display assembly, found in the Advanced catalog)   
View full article
Kasper.Vestrup Explorer
‎2026-01-09 03:35 AM

on ‎2026-01-09 03:35 AM

Labels:
  • Exp-6 3rd Party Programs
  • Experior 6
313 Views

ABB RobotStudio

Downloading ABB RobotStudio   Go to http://new.abb.com/products/robotics/robotstudio/downloads Click Download Robot Studio x.xx.xx. Wait for the file to download.   Installing RobotStudio Right click on the desktop, select New and click Folder. Rename it to Robot_temp. Open the folder by double clicking it. Locate downloaded zip file and double click to open. Select all files and folders in the zip and drag across to the open Robot_temp folder. When the files have finished copying double click the file named Launch. If you get the User Account Control pop-up click YES. Select English (USA) from the drop down list and click OK. Click the Install Products button. Click the Robot Studio button. When the Welcome window opens click NEXT. Select I accept the terms in the license agreement. Click NEXT. Click ACCEPT. Leave destination folder as presented and click NEXT. Select Complete and click NEXT. Click INSTALL. When the install is complete click FINISH.   Installing RobotWare On the Install Products window which should still be open from previously, click the Robot Ware button. When the Welcome window opens click NEXT. Select I accept the terms in the license agreement. Click NEXT. Click ACCEPT. Leave destination folder as presented and click NEXT. Select Complete and click NEXT. Click INSTALL. When the install is complete click FINISH. Click Exit and Exit again to close the installer. Delete the Robot_temp directory.
View full article
Kasper.Vestrup Explorer
‎2026-01-09 03:28 AM

Labels:
  • Exp-6 3rd Party Programs
  • Experior 6
115 Views

Experior & Remote Viewer – OpenID Connect (OIDC) Login Guide

Overview This document explains how to enable OpenID Connect (OIDC) authentication for Experior and the Experior Remote Viewer. Once configured, users can authenticate via an external Identity Provider (IdP) instead of using local credentials. This setup supports standard OIDC-compatible identity providers (e.g., Azure AD, Keycloak, Auth0, Okta, or similar platforms).   Prerequisites Before starting, ensure the following: Experior is installed and runnable Experior Remote Viewer is available Access to an Identity Provider (IdP) that supports OpenID Connect Ability to register a client/application in the IdP   1. Experior Configuration Runtime Requirements Experior must be started using one of the following modes: -graphicsserver -headless These modes enable the web interface and API required for authentication.   Web API Configuration Update the WebApiSettings.json file to include identity provider settings. Option A – Direct OIDC Configuration Provide explicit configuration values: 1 "IdentityProvider": { 2 "Authority": "https://<idp-domain>/", 3 "Issuer": "https://<idp-domain>/", 4 "Audience": "account", 5 "ClientId": "experior-remote-viewer", 6 "UserIdField": "", 7 "RedirectUri": "http://127.0.0.1:8080/callback", 8 "EndSessionRedirectUri": "http://localhost:8080/", 9 "AuthorizationScope": "openid", 10 "Prompt": "login" 11 }   Option B – Dynamic Configuration via External API Alternatively, configuration can be retrieved from an external service: 1 "ExternalApi": { 2 "BaseUrl": "http://localhost:5050/api", 3 "IdpEndpoint": "/idp" 4 }, 5 "IdentityProvider": { 6 "Authority": "", 7 "Issuer": "", 8 "Audience": "", 9 "ClientId": "", 10 "UserIdField": "", 11 "RedirectUri": "", 12 "EndSessionRedirectUri": "", 13 "AuthorizationScope": "", 14 "Prompt": "login" 15 } In this scenario, Experior will query the external API to retrieve the required IdP configuration. Other Relevant Settings Ensure the following sections are configured as needed: WebUi.Enabled = true CorsConfiguration.AllowAll = true (or restrict appropriately for production) CertificateConfiguration.AllowInsecureCertificate should be false in production   2. Identity Provider Setup Your Identity Provider must be configured with a client application for Experior Remote Viewer. Required Configuration Create a client with the following characteristics: Client ID: experior-remote-viewer (or match your configuration) Protocol: OpenID Connect Redirect URI: Must match RedirectUri in WebApiSettings.json Scopes: At minimum openid Optional but recommended: Enable refresh tokens Configure logout redirect URI Add additional scopes such as profile or email Supported Identity Providers Any OIDC-compliant provider can be used, for example: Azure Active Directory Keycloak Auth0 Okta   3. Remote Viewer Setup The Remote Viewer uses the configured Identity Provider via Experior's API. Ensure: Remote Viewer can reach the Experior Web API Redirect URI configured in the IdP matches the viewer callback endpoint Network configuration allows communication between viewer, Experior, and the IdP   4. Login Flow The authentication flow works as follows: User opens the Remote Viewer User is redirected to the Identity Provider login page User authenticates with the IdP IdP redirects back to the Remote Viewer using the configured callback URL Experior validates the token Access is granted   5. Best Practices Always use HTTPS in production environments Do not allow insecure certificates outside of development Restrict CORS settings to known origins Keep client secrets and configuration secure Align redirect URIs exactly between configuration and IdP   Summary By configuring Experior with an OpenID Connect-compatible Identity Provider, you enable secure, centralized authentication for both Experior and the Remote Viewer. This allows integration with enterprise identity systems and improves security and user management.
View full article
Kasper.Vestrup Explorer
‎2026-05-26 02:06 AM

on ‎2026-05-26 02:06 AM

Labels:
  • Remote Viewer
353 Views

Navigating Remote Viewer scene

This article describes the navigation around the scene inside Remote Viewer on a PC. Two objects are relevant for navigating the scene: Camera: virtual camera that displays the Experior scene streamed to the Remote Viewer. Projection: perspective Field of View Axis: vertical Field of View: 50 degrees Clipping Planes: near 0.3m, far 1000m Physical Camera: false Camera target: movable object which the camera is always pointing at. To visualise the Camera target, go to Settings inside Remote Viewer, and set Show camera target to true.   Rotation To rotate the camera around the camera target, click the left mouse button and drag the mouse.   Translation To pan / move / translate the camera target horisontally, click the right mouse button and drag the mouse. The camera will always move with it. Note: when the camera is too close to the camera target, the translation might appear slow. Maker sure the camera target is visible, and in the correct position. Zoom To move the camera towards/away from the camera target, use the mouse wheel.   Fly camera The camera can be "flown" in a similar way like a First-person view (FPV) drone: To go forward (in the direction of the camera), use the W button / up arrow key. To go left, use: A / left arrow key To go right, use: D / right arrow key To go back, use: S / down arrow key To speed up, use left shift.   Reset camera To reset camera, use the Reset camera button in the scene, or go to Settings, and click Reset camera The camera can be reset into: Default position Position that shows all objects in the scene. To achieve this, go to Settings, and set Reset camera to scene bounds to true
View full article
Kasper.Vestrup Explorer
‎2026-05-26 01:07 AM

Labels:
  • Remote Viewer
176 Views

Advanced Physics Dynamics

Introduction The current implementation of the Physics Engine in Experior 7 presents difficulties in accurately simulating the dynamics of loads under certain scenarios commonly found in conveying system applications. This may partially or entirely alter the results of simulation and emulation models, requiring workarounds to overcome these issues.   To address these challenges, a new implementation called Advanced Dynamics has been developed to provide a generic solution that covers a broad spectrum of complex dynamics scenarios presented in case conveying and pallet conveying systems, with respect to the motion of loads produced by forces exerted by conveyors. However, it is not within the scope of this new implementation to provide a solution that represents a 1:1 version of real physics (e.g., material deformation), considering the computational limitations of real-time simulations.   Development The following section describes the main points that have been reworked to significantly impact the overall physics engine.   Load transition Problem The displacement of the load is affected, either partially or totally, by the collision between the load and the belt that occurs during the transition in merge and divert sections. Flawless transitions depend on the geometry and dimensions of the load. Load orientation (Yaw) is affected during the transition, regardless of whether the configuration is straight-straight or straight-curve sections. Merge configuration old    Orthogonal configuration old   Cylinder transition old   Small Box transition old   Curve-Straight configuration old   Solution Whenever there is a collision between dynamic actors (i.e. loads) and static actors (i.e. belts), PhysX generates contact points that the contact solver uses to determine the velocity and position of the load. However, before the contact solver is applied, the properties of these contact points, such as the vector orientation, are modified to ensure a smooth transition, regardless of the geometry or dimensions of the load. The primary purpose of contact modification is to enable seamless transitions between conveyors, without requiring the use of ramps.   Orthogonal Configuration    Parallel Configuration   Inline-Decline   Contact Points Problem   Loads can exhibit unrealistic behaviors in certain scenarios where they come into contact with more than one surface simultaneously. This is because only the greatest velocity is applied. The current implementation lacks the capability to retrieve information about the contact points generated by the surfaces and the load.   Parallel Configuration old   Orthogonal Configuration old   Solution   PhysX filter allows retrieval of information related to contact points generated by collisions between dynamic and static actors. This makes possible to develop proper mathematics which considers the distance between the load’s center of mass and the position of each contact point to apply forces and torques correctly.   Parallel Configuration New    Orthogonal Configuration New   Friction Specifically, this refers to the friction force a conveyor surface applies to a load. Experior 7 calculates this friction force when the speed of the surface motor on a belt is different from zero. When the speed of the surface is zero, the PhysX engine from Nvidia will take over these calculations. Note: Patch and Two directional refer to the two friction modes from Nvidia PhysX supported in Experior 7. This only affects the friction force when it is being handled by the PhysX engine (i.e.: surface speed is zero). The key differences are: Two-directional combines the load and the surface friction coefficients for the force calculations, whereas Patch gives priority to the surface friction coefficients. According to the Nvidia PhysX documentation, Patch mode has better performance. Two-directional mode is more realistic, especially with static friction, as patch mode has unrealistically strong static friction. This behavior is most noticeable when a load is touching surfaces with non-zero velocity and zero velocity simultaneously. In Experior 7, the friction mode can be set through the command line arguments (patch is the default value). Experior 6 only supports the Two-directional mode.   Problem   The friction force calculations made by Experior 7 and the PhysX engine are inconsistent. An acceleration-deacceleration test showed this, where a load starts from rest on a conveyor. Afterward, the motor is turned on with a speed of 1.5 m/s and then is turned off (motor acceleration and deceleration are disabled). The following images show the load speed plotted against time. As the same physical phenomenon (dynamic and static friction) is responsible for the acceleration and deceleration of the load, we would expect the plotted curves to have a symmetrical behaviour. However, It is noticeable that the load behaves differently when accelerating and decelerating. This shows the inconsistencies between the force calculated by Experior 7 and the PhysX engine.   Solution   According to the Nvidia PhysX documentation, the friction force is calculated using the Coulomb friction model. To make the calculations from Experior 7 more consistent, we are now calculating friction force based on the Coulomb friction model. The following images show the results of the acceleration-deceleration test with the new friction calculations. Due to the symmetry in the curves, we can see that the friction force of the conveyors is now consistent when the motors are on and off.   Load Trajectory Problem   When the surface in contact uses sticky friction, Experior directly defines the load’s LinearVelocity property. However, this approach is inconsistent with PhysX, which computes all the forces exerted on a dynamic actor to determine its velocity and position. Furthermore, when the friction is not sticky, forces and torques are applied without regard of the surface’s orientation.   Incline-Decline old   Curve configuration old   Solution   Forces and torques are calculated based on the alignment of the surface and the information extracted from the contact points. During transitions from straight to curve and from curve to straight, forces and torques are applied independently to each surface. This is determined by the position of the center of the load. Remove the ramps from the conveyors. Incline-Decline new   Curve Configuration new   Stacks Problem The current physics engine configuration does not allow for stable stacking or displacement due to the default collision detection system (Permanent Contact Manifold). PCM is a distance-based collision detection system that can generate fewer contacts, potentially reducing the stability of tall stacks when simulating with insufficient solver iterations. Stacks old   Solver iterations refer to the minimum number of position and velocity iterations used by the contact solver behind the scenes to determine the velocity and position of a load.    Solution The physics engine configuration now includes a new feature called “Average Point”. This feature generates additional contacts per manifold to represent the average point in a manifold. It can stabilize a stacking effect when only a small number of solver iterations are used. The following videos demonstrate the difference when increasing the number of solver iterations from P:4,V:1 to P:20,V:5. Stacks 4 1 new   Stacks 20 5 new   Thanks to the new implementation, stacking and destacking processes no longer require additional functionalities or logic to achieve the correct behavior of the stack (e.g., the use of Group() and Ungroup() from the Load class). However, limitations from PhysX are still present when using a stack with a significant number of loads. The next two videos demonstrate the stacking and destacking processes, where the sensor between the forks only attaches to the load making contact.   Stacking new   Destacking new     Sleep Threshold Problem The PhysX solver continues to execute even when the load is not moving, resulting in unnecessary consumption of computational resources. In the video, it is evident that the arrow of each load which represents the linear velocity, keeps moving around continuously, even though the loads are completely static. Sleep Old   Solution Each dynamic actor contains a property called SleepThreshold, which sets the mass-normalized kinetic energy threshold below which an actor may go to sleep. Once an actor goes to sleep, PhysX will not report or notify it.   If a load on top of a conveyor is in a sleeping state, it will automatically awaken once the motor starts (CurrentSpeed != 0f). This is due to the notification from the motor to the PhysX engine through the method BeginStart(). However, it will take one more frame for the physics engine to move the load. It’s important to note that any motor developed using inheritance from the Electric class must use the method BeginStart when starting the motor.   Sleep new   Sleep Conveyor new   Risks / Side Effects To address the issues that were disclosed, it was necessary to implement new functionalities, which may have some unintended consequences. The following section outlines the potential risks associated with each of the proposed solutions. Performance     Performance decreased 18% Processor: i7-9750H CPU 2.60 GHz Ram: 16 GB Nvidia GeForce RTX 2070   A test was conducted to compare the performance of Advanced Dynamics with the current implementation, Classic Dynamics, which was considered a benchmark due to its efficiency. As shown in the image, Classic Dynamics is capable of handling 850 loads without exceeding the 16 millisecond threshold (the threshold is determined by the cycle task frequency of 60Hz), whereas Advanced Dynamics surpasses it. Based on the results of this specific test, Experior’s performance decreases by approximately 18%. It is important to note that performance can vary due to hardware specifications, as well as the size of the model and assemblies contained within it.   Precision to represent reality In some specific cases, uncertainties about the real-life dynamics of the load may arise due to the broad spectrum of complex scenarios and the lack of physical facilities to test them. Therefore, we are open to discussing and improving based on your feedback.   Although the mathematics defining the dynamics of the load and configuration of the PhysX engine have been reworked, computational limitations still persist due to the contact solver capacity. This is particularly evident when implementing tall stacks (more than 15 loads) or handling loads with very small dimensions. This limitations are expected to improve after updating the PhysX engine version in the near future. Dynamic 1    Dynamic 2   False Expectations Users should not expect to obtain the same results when using Advanced Dynamics as when using Classic Dynamics with regards to load dynamics, particularly when modifying the friction coefficients. The old implementation was developed in a specific way to overcome problems resulting from the lack of information and default configuration of PhysX, such as very high and low coefficient values. As shown in the following video, using the smooth friction type from Classic Dynamics will not produce the same results in Advanced Dynamics.   Expectations   Implementation To fully take advantage of the advanced dynamics, it is strongly suggested to remove the ramps of the belts used in your catalog. A new query property Experior.Core.Environment.Engine.AdvanceDynamics has been introduced, so that developers can handle the proper removal of ramps based on the physics engine dynamics. Users have the option to select the Physics engine dynamics type through the CLA (Command Line Argument) -physicsenginedynamics “advanced”. By default, Experior 7 will use “classic”. This parameter can be set from the cmd or the shortcut configuration as the following images show.     MinPositionIterations and MinVelocityIterations properties have been added to the class Load.  Global SleepThreshold property set automatically to 5e-5 if advanced dynamics is used. Nevertheless, the property SleepThreshold is available from the class Load. Visualization of contact points are displayed in debug visualization mode when using advanced dynamics. New friction coefficient values have been defined. Experior will automatically set the appropriate friction coefficient based on the selected physics engine dynamics. The following image displays the friction coefficient values defined for advanced dynamics mode.
View full article
Kasper.Vestrup Explorer
‎2026-01-30 05:38 AM

on ‎2026-01-30 05:38 AM

Labels:
  • Exp-7 Developer
  • Experior 7
354 Views

Experior 7 - API

Due to our move from a self hosted webpage to the following community structure, the API documentation is now available as static html files you need to download attached file, unzip and then open any one of the html files in the folder.
View full article
Kasper.Vestrup Explorer
‎2026-01-15 06:21 AM

on ‎2026-01-15 06:21 AM

Labels:
  • Exp-7 Developer
  • Experior 7
408 Views

Build a Controller

Step 1:   Make a C# project where the main class extends the Experior.Core.Controller or Experior.Core.Logic class. Experior.Core.Controller is for making controllers that interacts with a model running in the discrete event engine and Experior.Core.Logic is for controllers interacting with a model running in the physics engine.     Step 2:   To start Experior directly within Visual Studio set Start external program. Then you can insert break points in the controller code and debug the source code.     Step 3:   Make sure the output path is the same as Experior     Step 4:     Now build the model you want to control and link the compiled controller with the model.   You can add multiple controllers disable/enable a linked controller or unload an existing controller.  
View full article
Kasper.Vestrup Explorer
‎2026-01-15 05:59 AM

on ‎2026-01-15 05:59 AM

Labels:
  • Exp-6 Developer Guide
  • Experior 6
267 Views

Custom connection

It is possible to extend the functionality of Experior with custom communication protocols. This is done by creating your own plugin and extending Experior.Core.Communication.PLC.Connection.   In case your connection is TCP/IP based you can extend from Experior.Core.Communication.PLC.TCPIP.Connection.   Experior.Core.Communication.PLC.Connection In attached memcom communication plugin a custom connection is made that doesn’t use the network to communicate but instead uses a memory stream. This plugin can be used to quickly test your Input/Output driven components. You do this by connecting an input and an output through the same address of the memcom connection.   For example link the Pushed PLC Input symbol of a button to Byte 1 Bit 0 of the memcom connection and also connect the Lighting PLC output to Byte 1 Bit 0 of the memcom connection. When pressing the button the lamp will light up:   The custom connection uses a memory stream to achieve this because a memory stream has similar behavior as a regular network stream.   The source code contains some notes explaining how to achieve the same functionality without the memory stream (and just share the data buffer).   Whenever the user assigns an input/output from a component to a PLC connection then this input/output is assigned to a PLC Buffer (Experior.Core.Communication.PLC.Buffers.Input/Experior.Core.Communication.PLC.Buffers.Output). These buffers maintain an array of bytes and grows/shrinks whenever new inputs/outputs are added/removed.   So in the constructor of the connection we create the buffers and subscribe to the events that are triggered when their size should change or when new inputs/outputs are assigned to them.   It is possible to have multiple buffers in a connection. Therefore we distinguish between them in a connection using a unique key (string) the Source.   In the example plugin only 1 Input buffer and 1 Output buffer is used, each with a default Source name equal to “0”.   In the constructor we also restore the saved buffer in case it exists. public MemConnection(MemConnectionInfo info) : base(info) { input = new Core.Communication.PLC.Buffers.Input(); // first restore the saved outputbuffer if it exists if (info.outputs != null && info.outputs.Count > 0) { output = info.outputs[outslot]; } else output = new Core.Communication.PLC.Buffers.Output(); //give the input and output buffer a unique slot name input.Source = inpslot; output.Source = outslot; // subscribe to the different events to react upon data changes or to properly allocate the buffers output.BufferChanged += new Core.Communication.PLC.Buffers.Output.BufferChangedEvent(OutputDataUpdated); input.BufferChanged += new Core.Communication.PLC.Buffers.Input.BufferChangedEvent(InputDataUpdated); Experior.Core.Communication.PLC.Connection.Inputs.LengthChanged += new Inputs.LengthChangedEvent(Inputs_LengthChanged); Experior.Core.Communication.PLC.Connection.Outputs.LengthChanged += new Outputs.LengthChangedEvent(Outputs_LengthChanged); Experior.Core.Communication.PLC.Connection.Outputs.ConnectionedAssigned += new Outputs.OutputEvent(Outputs_ConnectionedAssigned); Experior.Core.Communication.PLC.Connection.Outputs.ConnectionedUnAssigned += new Outputs.OutputEvent(Outputs_ConnectionedUnAssigned); Experior.Core.Communication.PLC.Connection.Inputs.ConnectionedAssigned += new Inputs.InputEvent(Inputs_ConnectionedAssigned); Experior.Core.Communication.PLC.Connection.Inputs.ConnectionedUnAssigned += new Inputs.InputEvent(Inputs_ConnectionedUnAssigned); // add sources to the connection AddSource(input); AddSource(output); Experior.Core.Environment.Scene.Loaded += new Core.Environment.Scene.Event(Scene_Loaded); }   When the user assigns an Input/Output to the connection it triggers the Experior.Core.Communication.PLC.Connection.Inputs.ConnectionedAssigned and  Experior.Core.Communication.PLC.Connection.Outputs.ConnectionedAssigned events.   In the example we only use this to set the Source property of the Input/Output private void Inputs_ConnectionedAssigned(Input sender, Core.Communication.PLC.Connection connection) { if (this != connection) return; // here you can react upon the sender being added to this connection // in our case we just want to ensure the proper Source is set sender.Source = inpslot; }   Due to the nature of the example connection it is crucial that the Input and Output buffer have the same size so a big part of the source code is related to this.   When assigning Inputs/Outputs to a connection Experior verifies whether the buffer size should change and in those cases triggers the Experior.Core.Communication.PLC.Connection.Inputs.LengthChanged or Experior.Core.Communication.PLC.Connection.Outputs.LengthChanged events.   At all times you ask the minimum and maximum used byte of a input/output buffer by providing the connection and the Source of the buffer: int max = Experior.Core.Communication.PLC.Connection.Inputs.MaxSize(this, inpslot); int offset = Experior.Core.Communication.PLC.Connection.Inputs.MinSize(this, inpslot);   If the buffer is not large enough anymore you can allocate sufficient bytes: // allocate (max-offset) bytes for the input buffer starting from offset input.Allocate(max - offset, offset, Experior.Core.Communication.PLC.Buffers.Buffer.Units.SINT);   Note: Experior.Core.Communication.PLC.Buffers.Buffer.Units.INT is used to indicate that the given size should be measured in bytes. In case Experior.Core.Communication.PLC.Buffers.Buffer.Units.SINT is used the size will be measured in words of 16 bits.   After the allocation the input.Data property will be an array of bytes with the proper size. When the user tries to connect the connection the EstablishConnection() method is called. When he tries to disconnect the Disconnect() method is called. In our example we override both methods and set the proper state of the connection (Core.Communication.State). When establishing the connection we make sure that the Input/Output buffers are allocated with the same size. In case we use a memorystream we also start listening on the stream (similar as we would be on a networkstream).   When the states of the Input/Outputs are changed this is immediately reflected in changes of the corresponding Input/Output buffers of the associated connection and the BufferChanged events are triggered. In our example we write the changed buffer to the memorystream. A different thread reads the memory stream and when the byte array is received it calls the byte[] DataReceived(string source, byte[] data) method of the connection to indicate that the given source has received the given data. int l = memStream.Read(incoming, 0, incoming.Length); if (l > 0) { DataReceived(inpslot, incoming); }   This triggers the proper events on the changed Inputs/Outputs. In the example without the memorystream we simply share the Data of the buffer and directly call the DataReceived method.   Experior.Core.Communication.PLC.TCPIP.Connection This connection class inherits from Experior.Core.Communication.PLC.Connection and mainly adds some TCPIP specific properties like Port, IP address and distinction between server and client connection: string IP: This getter property is used to get / or set the IPv4 address used by this connection. For a server connection this is 127.0.0.1 (localhost).   int Port: This property is used to get or set the port number for the TCPIP connection.   bool Server: Getter property to indicate whether this connection is used as server or client.
View full article
Kasper.Vestrup Explorer
‎2026-01-15 05:57 AM

Labels:
  • Exp-6 Developer Guide
  • Experior 6
267 Views

Load class

Loads in Experior are used to model pallets, boxes, bags, that are transported by material handling equipment like conveyors and lifts.   The main namespace for loads is Experior.Core.Loads and the Experior.Core.Loads.Load contains some factory methods for creating loads with different load types.   The Experior.Core.Loads.Load class derives from the RigidPart class and hence inherits a lot of its interaction with the PhysX engine from it.   Note that there are some important differences related to loads depending on whether Experior is running in physics mode or discrete mode. In physics mode a load is considered a dynamic object (unless you disable the load or make it Kinematic). This implies that the position of the load and its orientation is determined by the underlying nVidia Physx engine who calculates this by applying all the forces/torques on it. In discrete mode no physics engine is used. There it is important to know that, unless a load is made undeletable, it will always be on a Route (Experior.Core.Routes.Route) or an Action Point (Experior.Core.Routes.ActionPoint). So, by default, if a load is no longer on a Route/Action Point then it will be deleted by the underlying engine.   Below we will illustrate a set of the main methods/properties of the Experior.Core.Loads.Load class.   Some methods/properties related to the interaction of the loads with the physics engine Sleep(): This is used in the physics mode to make the load unresponsive to the physics engine. The load will no longer respond to the forces applied to it. Note that you can WakeUp/Enable a load by clicking on it in the working area.   WakeUp(): This is used in the physics mode to “wakeup” a sleeping load and make it respond again to the physics engine. The load will again respond to the forces applied to it.   Vector3 CenterOfMassOffsetLocalPosition: When the physics engine applies a force to a load to make it moving it applies this force into the center of mass of a load. By default a loads density is equally distributed over the whole volume of the load and hence the center of mass of the load is also the geometrical center of the load. By providing the CenterOfMassOffsetLocalPosition you make it possible to move this center of mass and e.g. put the center of mass lower than the geometrical center to decrease the collapsing of a load.   NOTE: The value provided to this property is an absolute value. The CenterOfMassOffsetLocalPosition property provided in the property window of a feed is a relative one where 1 represents 100%.   Example and illustration. In the example below the CenterOfMassOffsetLocalPosition of the loads with dimensions (0.5f,0,5f,0.5f) is set to (0, -0.2f, 0) when the load enters a sensor: So the force will be applied 200mm below the geometrical center of the load. myLoad.CenterOfMassOffsetLocalPosition = new Vector3(0, -0.2f, 0);   You can clearly see that the force on the load is applied lower than before it entered the sensor.   bool Gravity: This indicates whether a load is subject to gravitational force. If you set it to false a load will not fall, but will remain subject to other forces like the force applied to it on a conveyor.   float Density: This represents the (uniform) density of the load. It is used to calculate the weight of the load ( Volume calculates as length times width times height multiplied with the Density).   bool Embedded: This indicates whether the load is embedded in another entity and hence whether it should be saved when saving the model. When the Embedded property is true the load is not saved. (In discrete mode loads are never saved).   bool Enabled: Setting Enabled to false is similar to calling Sleep() and setting Enabled to True is similar to calling WakeUp().   bool Kinematic: By default a load is a dynamic object by the PhysX engine which implies that its position and orientation will be determined by the physics engine by calculating all forces/torques applied to the load. By setting the Kinematic property to true, the load is made a kinematic object instead of a dynamic one. This implies that the load will no longer respond to the forces applied to it and the position and orientation of the load is controlled by the user. (Using the Methods/properties related to positioning of a load described below).   bool Rigid: Returns true when the load is a rigid body for the PhysX engine.   bool Sleeping : Returns true when the load has been “put to sleep” and is longer taken into account by the physics engine.   DeSelect(): Deselects the load.   Select(): Selects the load. The properties of the load will be shown in the properties window and the load will get the Select color.   HighLight(Color color): Highlights the load by changing the highlight color to the given color. This is only a temporary change. When the load is UnHighLighted is restores its original color (given by the Color property.   UnHighLight(). UnHighlights the load, as a result it will get the color back as defined by the Color property.   Color Color: Returns/sets the normal color of the load (when not selected or highlighted).   bool Selectable: Indicates whether a load can be selected by the user. If you set this property to False the user will not be able to select the load.   bool Selected: Returns True when the load is currently selected, False otherwise.   bool Transparent: Returns True when the color of the load is transparent.   Methods/properties related to deleting of a load Dispose(): Called when deleting the load   bool Deletable : Property to indicate whether the load can be deleted. If this property is set to False, trying to delete the load will fail (e.g. when resetting the model, which normally deletes all loads in the model)   bool UserDeletable: Property to indicate whether the user can delete the load (e.g.by selecting it and pressing the Delete button)   event DisposeEvent OnDisposed : This event is called when the load is completely disposed (deleted)   event DisposeEvent OnDisposing : This event is called beginning to dispose a load   Methods/properties related to grouping/deleting of a load Remark: In discrete mode the grouping/ungrouping of loads happens instantaneously and immediately after calling the Group/UnGroup methods the grouped load or ungrouped loads are available. Due to the nature of the physics engine this is postponed until the physics engine has finished its cycle of applying forces to loads. So in physics mode the grouped load is available when the OnGrouped event is raised.   Group(List<Load> loads): The current load will be grouped with all loads from the given list. They loads are grouped at their current relative position and the current load becomes the master load.   Group(Load load): The current load will be grouped with the given load. Both loads keep their relative position.   Group(Load load, Vector3 localposition): The given load will be grouped with the current load. It will be positioned given the relative position.    Group(List<Load> loads, List<Vector3> positions, List<Matrix> orientations): The given load is grouped with all loads from the given list of loads. Each load of the list is positioned according to the given relative position as provided in the positions list and with the orientation as described in the given orientations list of orientation matrices.   Group(Load load, Vector3 localposition, Matrix localorientation): The given load will be grouped with the current load. It will be positioned given the relative position and with the relative orientation as defined in the given orientation matrix.   Group(Load load, Vector3 localposition, float localyaw, float localpitch, float localroll): The given load will be grouped with the current load. It will be positioned given the relative position and with the relative orientation as defined by the relative Euler angles : localyaw, localpitch, localroll.   UnGroup(List<Load> loads): ungroups all loads from the given list of loads from the current load (masterload).   UnGroup(int loads): this will ungroup the given amount of loads from the current load. If the given number is larger then the total number of grouped loads it will ungroup all of them. If the number is smaller it will ungoup the given amount. The sequence of ungrouping is as follows: the last one grouped will be ungrouped first.   UnGroup(Load load): UnGroups the given load from the current load (masterload).   UnGroup(): UnGroups all loads that form the current load (masterload).   Collection Grouped: Returns the collection of loads that are grouped with the current load (the masterload). The Grouped collection allows to request the Length, Width, Height of the combined grouped load and you can iterate over all slave loads using the Items property of the Grouped property of the master load.   bool IsGrouped: Returns true for a load that has been grouped with a masterload. The materload itself will return false for this IsGrouped property.   event GroupedEvent OnGrouped: Is called when the load has been grouped. (See remark above concerning physics/discrete mode). The delegate has as argument the sender (masterload) and the result.   Below you find an example and screenshots of grouping: int createdloads=1;int totalnumber=10; Core.Resources.Mesh mesh=Common.Meshes.Get("Tote_Red"); Load ld1 = Load.Create(mesh, Length, Height, Width); ld1.Switch(linkedactionpoint); while (createdloads < totalnumber) { // create 4 more loads of given mesh and group them Load ld = Load.Create(mesh, Length, Height, Width); ld1.Group(ld,new Vector3(0,(Height-0.01f)*createdloads,0));//have totes slightly overlap // ld1.Group(ld,new Vector3(0,(Height+0.05f)*createdloads,0)) // create empty space between loads createdloads++; }   Above example results in the following stacks of totes being created depending whether we had loads overlapping or with empty space between them: Example of iterating over the grouped loads:   Experior.Core.Environment.Log.Write("Total dimensions are " + ld1.Grouped.Length + "; " + ld1.Grouped.Height + "; " + ld1.Grouped.Width); foreach (Load grl in ld1.Grouped.Items) { Experior.Core.Environment.Log.Write(" " + grl.Length + "; " + grl.Height + "; " + grl.Width); }   Methods/properties related to movement of a load in discrete mode MoveTo(string destination): This method will initiate a load traveling on its current route to the actionpoint with the name equal to the given destination. If the destination actionpoint is not reachable through routes connected to the current route then a message will be logged :  ‘Can’t continue: “destination” is unreachable (“current actionpoint name“)’   MoveTo(string source, string destination): This method will initiate a load traveling on its current route from the source actionpoint to the actionpoint with the name equal to the given destination.   Release(): This method will release a load that is stopped.   Release(float delay): This method will release a load that is stopped after the given delay has passed. The delay is given in seconds.   Stop(): This method will stop a load on its Route/ActionPoint. The load will wait there until it is released.   Switch(Route to): This method  will instantaneously take the load and put it at the start of the given route.   Switch(Route to, float distance): This method  will instantaneously take the load and put it at the given distance from the start of the given route.   Switch(Route to, bool keepGlobalOrientation): This method  will instantaneously take the load and put it at the start of the given route. When the keepGlobalOrientation argument is true than the load will keep its current global orientation (Yaw, Pitch, Roll), otherwise it will use the properties of the route.   Switch(Route to, float distance, bool keepGlobalOrientation): This method  will instantaneously take the load and put it at the given distance from the start of the given route. When the keepGlobalOrientation argument is true than the load will keep its current global orientation (Yaw, Pitch, Roll), otherwise it will use the properties of the route.   Switch(string actionpoint, bool keepGlobalOrientation): This method will put the load on the actionpoint with the given name.When the keepGlobalOrientation argument is true than the load will keep its current global orientation (Yaw, Pitch, Roll), otherwise it will use the properties of the actionpoint. If no actionpoint can be found with the given name the call is ignored.   Switch(ActionPoint ap, bool keepGlobalOrientation): this method will put the load on the given actionpoint. When the keepGlobalOrientation argument is true than the load will keep its current global orientation (Yaw, Pitch, Roll), otherwise it will use the properties of the actionpoint. In the illustrations below you can see the difference between switching a load (to AP6) with the keepGlobalOrientation argument true or false:       Switch(string actionpoint): This method will put the load on the actionpoint with the given name. If no actionpoint can be found with the given name the call is ignored.   Switch(ActionPoint ap, ActionPoint.Edges edge): This method will put the load on the actionpoint. The edge argument has 3 possible values ActionPoint.Edges.Leading, ActionPoint.Edges.Trailing and the defaultActionPoint.Edges.Center. If its value is Edges.Trailing then the load will be put on the actionpoint in such a way that the position of the actionpoint matches the trailing back of the load. If its value is Edges.Leading then the load will be put on the actionpoint in such a way that the position of the actionpoint matches the leading front of the load.   Note: This assumes that there is sufficient room on the route to do the switch, meaning that the center of the load should be on the route. Suppose you have an ActionPoint at the start of a route. In that case it is only possible to do the switch with edge ActionPoint.Edges.Center or ActionPoint.Edges.Trailing because using ActionPoint.Edges.Leading implies that the center of the load would not fit on the route.   Switch(ActionPoint ap): This method will put the load on the given actionpoint.   ActionPoint ActionPoint: This getter property returns the current actionpoint of the load or null if the load is on a route and not at an actionpoint.   string GoTo: This property allows to get of the name of the current final destination actionpoint. By setting this property to the name of an actionpoint the load will set it as its final destination and travel towards it.   Vector3 RouteOffset: Normally a load travels on the route with the center of the load moving over the route. By using the RouteOffset property you can chnage this and have the center of the load moving at the given relative position from the route.   Below you see an illustration of loads moving where load.RouteOffset = new Vector3(1.2f, 0.3f, 0f);   bool Stopped: This getter property returns True when the load is currently stopped, False otherwise.   float WaitingTime: Setting this property makes a load wait at its current position. The waiting time is provided in seconds. When this waiting time is elapsed the load will trigger the FinishedWaiting event and continue.   FinishedWaiting FinishedWaitingEvent: This event is triggered by a load when its WaitingTime has elapsed.   Methods/properties related to attaching a load to a RigidPart public bool IsAttached: This getter property returns true when the load is currently attached to a RigidPart and hence if following the movement of this part.   event AttachedEvent OnUnAttached: This event is triggered when the load gets unattached of the RigidPart it was attached to.   event AttachedEvent OnAttached: This event is triggered when the load gets attached to a RigidPart was attached to.   Attaching loads is done using one of the Attach methods of the Experior.Core.Parts.RigidPart class.   Custom Data object UserData: The developer can add custom data to a load by using this UserData property. E.g you can create you own TransportOrder class containing data from the WMS like PurchaseOrder,Customer, Source, Destination, DueDate,… and attach it to the load: myload.UserData = aTransportOrder;   You can inspect the data again by casting the UserData back to the class it was given: string customer = (myload.UserData as TransportOrder).Customer;   Methods/properties related to prositioning of a load float Yaw: This getter/setter property reflects the rotation angle (in radians) of the load around the Y-axis   float Pitch: This getter/setter property reflects the rotation angle (in radians) of the load around the X-axis   float Roll: This getter/setter property reflects the rotation angle (in radians) of the load around the Z-axis   Vector3 Position: This property returns the global 3 dimensional coordinates of the center of the load. In the physics mode the position is determined by the physics engine or its movement on tracks and in discrete mode by its movement on the routes. When the load is made Kinematic or Disabled then it makes sense to directly set the position of the load.   Matrix Orientation: This property returns or sets the orientation of the load as defined in the Microsoft.DirectX.Matrix structure.   Translate(Vector3 distance, float time): This will translate a stopped load over the given vector during the given time. After the given time the load remains at its position after the translation until it is released. In case the load continues moving on a route it will jump back to its position on the route. So note that the load should not be moving on a route when calling this translate method otherwise you get some strange wave movement during the given time where the load is trying to translate over the given vector but is pulled back by it having to move on the route.   Translate(Action action, Vector3 distance, float time): This method is similar to the Translate method above except that at the end of the translation of the load over the given vector distance the given action will be executed. The given System.Action is a delegate that you can use to pass a method as a parameter without explicitly declaring a custom delegate. The encapsulated method must correspond to the method signature that is defined by this delegate.This means that the encapsulated method must have no parameters and no return value.   In the example below a load is translated over 3 meter in the Y-direction in 2 seconds and at the end of the movement the load is switched to actionpoint  “AP10” and then released : currentload.Translate(()=>SwitchToAP10(), new Vector3(0, 3.0f, 0), 2f);   where: public void SwitchToAP10() { if(currentload != null) { currentload.Switch("AP10"); currentload.Release(); } }
View full article
Kasper.Vestrup Explorer
‎2026-01-15 05:55 AM

on ‎2026-01-15 05:55 AM

Labels:
  • Exp-6 Developer Guide
  • Experior 6
190 Views

ActionPoint class

Action Points are points on a Route where a load can stop and stay. They are used internally by Experior as vertices or nodes in the routing graph (where parts of the route between the action points are the edges).   They are implemented in Experior using the Experior.Core.Routes.ActionPoint class.   Main properties: string Name: Getter property for the name of this actionpoint. string APName: Gets or sets the name of this actionpoint. Route Parent: This getter property returns the route to which this actionpoint is added. Assembly:  This getter property returns the Assembly object to which this actionpoint belongs. Vector3 Position: This getter property returns the global position of this actionpoint. bool Routing: Gets or sets a value indicating whether this actionpoint should be included as node in the routing graph. bool Selectable: Gets or sets a value indicating whether this actionpoint is pickable by the user. bool Selected: Gets or sets a value indicating whether this actionpoint is selected. Experior.Core.Reports.Statistics.Statistic.Counter Statistic: This getter property returns the counter statistic linked to this actionpoint. ActionPoint.StoppingMode StopMode: This property gets or sets the stopping mode of this actionpoint. Possible values are: StoppingMode.None, StoppingMode.Stop, StoppingMode.Capacity, StoppingMode.StopMotor and only available in discrete event mode StoppingMode.Interval. ActionPoint.Edges Collision: This property gets/sets when an actionpoint triggers its Enter event. float Distance: This property gets/sets the distance of this actionpoint on its route measured from the start of the route. bool Active: This getter property returns whether this actionpoint is active (has load) or not. Load ActiveLoad: This getter property returns whether the current load on this actionpoint (or null in case the actionpoint is not active). string VirtualNode: This property gets/sets whether this actionpoint is a virtual node or not (default). This VirtualNode is used to join a group of nodes into one edge in the route graph. All actionpoints with the same VirtualNode value will behave as 1 node in the routing graph. static ReadOnlyDictionary<string, ActionPoint> Items: Static getter property that returns a read-only dictionary with all existing user actionpoints. Key in the dictionary is the name of the actionpoint while the value is the actual ActionPoint instance. Note: this dictionary only contains actionpoints that were added by the user, it does not contain the actionpoints that were created by code internally in assemblies. The developer should keep track of those.   Main events: event ActionPoint.EnterEvent Enter: This event is raised when a load enters this actionpoint. event ActionPoint.ReleasedEvent Released: This event is raised when a load leaves this actionpoint. It can be because the load was never stopped, or because the load is deleted or released or  switched to another ActionPoint or Route. event ActionPoint.MoveToEvent MoveTo: This event is raised when the MoveTo method is called on the load. event ActionPoint.RemovedEvent Removed: This event is raised when an actionpoint is deleted.   Example: public ActionPoint CreateActionPoint (int index) { ActionPoint ap = new ActionPoint(); ap.Edge = ActionPoint.Edges.Leading; ap.StopMode = ActionPoint.StoppingMode.Stop; ap.Name = index.ToString(); ap.Enter += new ActionPoint.EnterEvent(ap_Enter); ap.Released += new ActionPoint.ReleasedEvent(ap_Released); return ap; } void ap_Enter(ActionPoint ap, Load load) { // Example of gathering and logging some routing info // we will lo the previuous and next actionpoint and the distance to them float nextdistance; float prevdistance; ActionPoint next = Route.FindNextActionPoint(ap, out nextdistance); ActionPoint prev = Route.FindPreviousActionPoint(ap, out prevdistance); if (next != null) Experior.Core.Environment.Log.Write("Next ActionPoint of " + ap.Name + " is " + next.Name + " at distance " + nextdistance); else Experior.Core.Environment.Log.Write("No next ActionPoint found for " + ap.Name ); if (prev != null) Experior.Core.Environment.Log.Write("Previous ActionPoint of " + ap.Name + " is " + prev.Name + " at distance " + prevdistance); else Experior.Core.Environment.Log.Write("No previous ActionPoint found for " + ap.Name); // example of some diverting decision based on load info if (load.Identification == ap.Name) { //divert load to route Int16 idx=0; if (Int16.TryParse(ap.Name, out idx)) { load.Switch(divertroutes[idx].Route); load.Release(); } } else load.Release(); } void ap_Released(ActionPoint ap, Load load) { Experior.Core.Environment.Log.Write("ActionPoint " + ap.APName + " is released by load " + load.Identification); }   Main static methods static string GetValidName(string prefix): Actionpoints require a unique name. This method will create a unique name with the given prefix. static ActionPoint Get(string name): A factory method to create and return an actionpoint with the given name.If there was already an actionpoint with the given name then this existing one is returned. static ActionPoint Release(string name): This static method will release the actionpoint with the given name.
View full article
Kasper.Vestrup Explorer
‎2026-01-15 05:48 AM

Labels:
  • Exp-6 Developer Guide
  • Experior 6
112 Views

Extending the GUI with a Plugin

A plugin can be used to add custom functionality to Experior and you can also use it to extend the GUI by adding menu items and/or adding your own forms. A plugin is a dll that will be automatically loaded by Experior (provided the dll can be found in the installation directory of Experior). You can create your own plugin by creating a separate Visual Studio project where your plugin class derives from Experior.Core.Plugin.    Toolbar.Button To extend the GUI you can create a Button (Core.Environment.UI.Toolbar.Button) and add it to a toolbar.   In the example below a button is created and added to Model Toolbar in a Tab with name TestPlugin : Core.Environment.UI.Toolbar.Button IOButton = new Core.Environment.UI.Toolbar.Button("SensorOutputs", btnIOToggle_Click); IOButton.Tooltip = "Show outputs from sensors"; // add the button to the Model toolbar in a Tab with name "TestPlugin" Core.Environment.UI.Toolbar.Add(IOButton, "TestPlugin");   This will look as follows:   When the example SensorOutputs button is clicked it will trigger the associated btnIOToggle_Click method.   In this example this will update a custom form.   Experior.Core.Forms.Form Experior allows to add your own forms. You create your form similar to a normal System.Windows.Forms.Form.   However if you want to have a form that behaves similar to other Experior forms and is dockable, the created form should derive from Experior.Core.Forms.Form instead.   Also the FormType property has to be overridden. public override Core.Forms.Docking.DockContent.FormTypes FormType { get { return Core.Forms.Docking.DockContent.FormTypes.Permanent; } }   In attached example is a custom form that contains a datagrid will info of all Outputs for the sensors in your model. The form looks as follows when it is docked:   You can download the complete plugin attached to this article
View full article
Kasper.Vestrup Explorer
‎2026-01-15 05:47 AM

on ‎2026-01-15 05:47 AM

Labels:
  • Exp-6 Developer Guide
  • Experior 6
142 Views

Rigid Sensor Part

RigidSensorPart The class Experior.Core.Parts.Sensors.RigidSensorPart derives from the abstract class Experior.Core.Parts.RigidPart. RigidSensorPart objects are used in the PhysX environment to detect and manage collisions with RigidParts such as Loads and Assemblies. Since they rely on the collision detection of the PhysX engine they have no functionality in the discrete mode. RigidSensorParts are available in different shapes (Experior.Core.Parts.Sensors.Cube, Experior.Core.Parts.Sensors.Sphere, Experior.Core.Parts.Sensors.Cylinder) and with different functionality (Experior.Core.Parts.Sensors.LoadMagnet and Experior.Core.Parts.Sensors.EaterCube). All sensor assemblies of the Sensor catalog contain at least one RigidSensorPart.   An example of the creation and usage of a RigidSensorPart can be found here.   Events event EnterEvent Enter; This event is called when the sensorpart collides with a part it should detect according to its Collision property. The delegate it will call has two arguments, the activated sensorpart and the triggering object (can be cast to Load or Assembly).   event LeaveEvent Leave; This event is called when the sensorpart collides with a part it should detect according to its Collision property. The delegate it will call has two arguments, the activated sensorpart and the triggering object (can be cast to Load or Assembly).   Properties virtual bool Active This property returns true when the sensorpart collides with a part it should detect according to its Collision property, false otherwise.   Experior.Core.Environment.Collisions Collision The Collision property has 3 possible values : Core.Environment.Collisions.Both, Core.Environment.Collisions.Loads and Core.Environment.Collisions.Equipment. Core.Environment.Collisions.Both: in this case the sensorpart will detect loads as well as assemblies Core.Environment.Collisions.Loads: in this case the sensorpart only detects loads Core.Environment.Collisions.Equipment: in this case the sensorpart detects rigidparts of an assembly   List<Load> Loads This property returns the list of all loads that are currently colliding with the sensorpart.
View full article
Kasper.Vestrup Explorer
‎2026-01-15 05:43 AM

on ‎2026-01-15 05:43 AM

Labels:
  • Exp-6 Developer Guide
  • Experior 6
160 Views

Interaction with Excel files

Experior provides some methods to read data from an Excel file and to write data into an Excel file.   To do this you can use the Experior.Core.Data.Excel class with the following methods. public static List<List<string>> Read(string filename, string sheetname); public void Write(string filename, string sheetname, List<List<string>> records);   There is also the possibility to verify whether a worksheet exists in a an Excel file with a given name. public static bool Exists(string filename, string sheetname);   By using the classes Excel, ExcelWorkbook, ExcelWorkSheet, from the namespace Experior.Core.Data.OfficeOpenXml you can obtain even more direct control.   For example. string filePath = Experior.Core.Directories.Model + "\\Simulation_results_" + DateTime.Now.Day.ToString() + "_" + DateTime.Now.Month.ToString() + "_" + DateTime.Now.Year.ToString() + "_" + DateTime.Now.Hour.ToString() + "_" + DateTime.Now.Minute.ToString() + "_.xlsx"; // create a new Excel workbook with the given filename and add a Worksheeet named "Simulation results" Experior.Core.Data.OfficeOpenXml.Excel e = new Core.Data.OfficeOpenXml.Excel(new System.IO.FileInfo(filePath)); Experior.Core.Data.OfficeOpenXml.ExcelWorksheet worksheet = e.Workbook.Worksheets.Add("Simulation results"); // write the data into the cells of the worksheet worksheet.Cells[1, 1].Value = "Total occupation time conveyor system"; worksheet.Cells[1, 2].Value = swTotalOnConv.elapsed.ToString(); worksheet.Cells[2, 1].Value = "Waiting time drivers"; for (int i = 0; i < driverWaitingTime.Count; i++) { worksheet.Cells[3 + i, 1].Value = "Waiting time after pattern " + (i + 1).ToString(); worksheet.Cells[3 + i, 1].Value = driverWaitingTime[i].elapsed.ToString("c"); } // Add another worksheet named "Simulated Pattern" Experior.Core.Data.OfficeOpenXml.ExcelWorksheet worksheetPattern = e.Workbook.Worksheets.Add("Simulated pattern"); r = 1; c = 1; foreach (List<string> rows in SimulatedPatternSheet) { c = 1; foreach (string cell in rows) { worksheetPattern.Cells[r, c].Value = cell; c++; } r++; } //save the Excel workbook file e.Save();
View full article
Kasper.Vestrup Explorer
‎2026-01-15 05:42 AM

on ‎2026-01-15 05:42 AM

Labels:
  • Exp-6 Developer Guide
  • Experior 6
158 Views

RigidPart

The Experior.Core.Parts.RigidPart class is the base abstract class to encapsulate rigid bodies that are used by the NVIDIA PhysX engine.   Some important classes that derive from RigidPart are RigidSensorPart (used by sensors) and RigidLoadPart (used inside loads).   Methods & Properties related to attaching loads. The methods below are used to attach loads to a rigidpart and keep them at a given relative position and orientation to the RigidPart. For the physics engine the loads are no longer dynamic actors that are moved according to forces and torques that are applied to them, but instead the loads become kinematic objects after attaching them to a RigidPart. You can use these method e.g. to attach a load to a gripper of a robot or keep it on a fast moving shuttle.   Note: There is an important distinction between the different Attach methods related to the collision of the load with a sensor. This distinction is necessary due to a limitation of the PhysX engine. The physics engine does not give a notification if you use the program to change the position of a load that is in contact with a sensor. Therefore, in attach methods that change the position/orientation of the load the load is taken out of the sensors it was colliding with by the programming (generating the Leave event of the sensor to allow reacting upon this change).   Attach(Load load): This method will attach the given load to the current RigidPart.This implies that if the RigidPart moves/rotates that the attached load will move with it, keeping its relative position/orientation as when it was attached. When the load was colliding with a sensor the Leave event of the sensor is not called (see Note above).   Attach(List<Load> loads): This method will attach all loads from the given list to the current RigidPart. When the loads were colliding with a sensor the Leave event of the sensor is not called (see Note above).   Attach(Load load, Vector3 localposition): This method will attach the given load to the current RigidPart at the given relative localposition from the origin of the rigidpart.   Attach(Load load, Vector3 localposition, float localyaw, float localpitch, float localroll): This method will attach the given load to the current RigidPart at the given relative localposition from the origin of the rigidpart and with a relative orientation determined by the given localyaw, localpitch,localroll Euler angles.   Attach(Load load, Vector3 localposition, Matrix localorientation): This method will attach the given load to the current RigidPart at the given relative localposition from the origin of the rigidpart and with a relative orientation determined by the given orientation matrix localorientation.   Attach(List<Load> loads, List<Vector3> positions, List<Matrix> orientations): This method will attach all loads from the given list to the current RigidPart. The given positions list and given orientations list contains the releative position and relative orientation for the load with the same index in the loads list.   UnAttach(Load load): Unattach the given load from the current RigidPart and make it a dynamic actor again for the physics engine.   UnAttach(): Unattach all loads that are attached to the current RigidPart and make them dynamic actors again for the physics engine.   In the example below a load is attached to the sensor upon the Enter event. private void Entering(Core.Parts.Sensors.RigidSensorPart sensor, object trigger) { //already attached if (((Core.Loads.Load)trigger).IsAttached) return; //avoid that the load gets selected ((Core.Loads.Load)trigger).Selectable = false; //attach load at current relative position/orientation to the sensor part sensor.Attach((Core.Loads.Load)trigger); }   Methods & Properties related to PhysX interaction.   Actor Actor: This property sets/returns the instance of the Experior.PhysX.Actor class representing this RigidPart which is used inside the NVIDIA PhysX engine (NxActor class). Actors are the main objects in a physx simulation.   Experior.Core.Parts.Friction Friction: This property sets/returns the friction definition for this RigidPart as used by the physics engine. The Experior.Core.Parts.Friction class defines the static and the dynamic friction and has some predefined Friction configurations for the user’s convenience. These are Friction.Coefficients.Slippy, Friction.Coefficients.Sticky, Friction.Coefficients.Smooth & Friction.Coefficients.None. When you require more control over the static and dynamic friction values used for your RigidPart then you can provide custom values for the Static and Dynamic property of the Friction property when using Friction.Coefficients.Custom. var cube = new Experior.Core.Parts.Cube(System.Drawing.Color.DarkGray, info.length, info.height, info.width); cube.Friction.Coefficient = Friction.Coefficients.Slippy;   bool Kinematic: By setting the Kinematic property to true, the rigidpart is made a kinematic object instead of a dynamic one. This implies that the part will no longer respond to the forces applied to it and the position and orientation of the part is controlled by the user. When kinematic is false then the part is considered a dynamic object for the physics engine.   Methods & Properties related to relative positioning. bool Configured: This getter property returns true when the RigidPart is added to a parent object (e.g. assembly) and positioned using the LocalPosition, LocalYaw, properties.    float LocalYaw: This getter/setter property reflects the rotation angle (in radians) of the RigidPart around the Y-axis of its parent object.    float LocalPitch: This getter/setter property reflects the rotation angle (in radians) of the RigidPart around the X-axis of its parent object.    float LocalRoll: This getter/setter property reflects the rotation angle (in radians) of the RigidPart around the Z-axis of its parent object.    Matrix LocalOrientation: This property returns or sets the relative orientation of the RigidPart with respect to its parent object as defined in the Microsoft.DirectX.Matrix structure   Vector3 LocalPosition: This property returns or sets the relative 3 dimensional coordinates of the center of the RigidPart with respect to its parent object   Methods & Properties related to editing. bool Dragable: Tthis getter/setter property controls whether you can drag the RigidPart, e.g. The start and end fixpoints in the conveyor assemblies are Dragable by default to allow the user to change the length of the conveyor by dragging the fixpoints to another position. bool Locked: This getter/setter property allows to lock/unlock the RigidPart. When the part is locked it will change color to Colors.LOCKEDCOLOR (Yellow by default). bool Selectable: This getter/setter property allows to control whether the RigidPart can be selected (e.g. by clicking on it). IEntity Parent: This getter property returns the parent entity  form the RigidPart. If a RigidPart is added to an Assembly using then the Parent will return this Assembly.   Property related to rendering RenderingMode RenderOption: This getter/setter property is used to get/set how the RigidPart should be rendered. The following values are possible:   Primitive: The part will only be rendered when the Experior.Core.Environment.Scene.PresentationLevel of Experior is Core.Environment.Scene.PresentationLevels.Primitives   PrimitiveAndNormal: The part will only be rendered when the Experior.Core.Environment.Scene.PresentationLevel is Scene.PresentationLevels.Primitives or Scene.PresentationLevels.Normal or Scene.PresentationLevels.Detailed or only its wireframe when Scene.PresentationLevels.Wireframe.   Normal: The part will only be rendered when the Experior.Core.Environment.Scene.PresentationLevel is Scene.PresentationLevels.Normal, Scene.PresentationLevels.Detailed or only its wireframe when Scene.PresentationLevels.Wireframe   Transparent: The part will only be rendered transparently (you can see through it) when the Experior.Core.Environment.Scene.PresentationLevel is Scene.PresentationLevels.Normal, Scene.PresentationLevels.Detailed. Note: Transparency is only visible in Locked mode, in Edit mode the part is rendered nontransparent.   TransparentPrimitiveAndNormal: The part will only be rendered transparently (you can see through it) when the Experior.Core.Environment.Scene.PresentationLevel is Scene.PresentationLevels.Normal, Scene.PresentationLevels.Detailed and Scene.PresentationLevels.Primitives. Note: Transparency is only visible in Locked mode, in Edit mode the part is rendered nontransparent.
View full article
Kasper.Vestrup Explorer
‎2026-01-15 05:41 AM

on ‎2026-01-15 05:41 AM

Labels:
  • Exp-6 Developer Guide
  • Experior 6
85 Views

Open Office XML

The Experior.Core.Data library includes a tool for creating Office Open XML spreadsheets   The sample below shows how to create a work book with a sheet called “Data” FileInfo file = new FileInfo(@"c:\Test.xlsx"); if (file.Exists) { file.Delete(); // ensures we create a new workbook file= new FileInfo(@"c:\Test.xlsx"); } using (Experior.Core.Data.OfficeOpenXml.Excel excel = new Experior.Core.Data.OfficeOpenXml.Excel(newFile)) { Experior.Core.Data.OfficeOpenXml.ExcelWorksheet sheet = excel.Workbook.Worksheets.Add("Date"); sheet.Cells[1, 1].Value = "Data"; sheet.Cells[3, 1].Value = "1"; sheet.Cells[3, 2].Value = "2"; sheet.Cells[4, 1].Value = "3"; sheet.Cells[4, 2].Value = "4"; excel.Save(); }   Result:     Use the sheet:Cells[x,y].Style to set background color, font, border etc.
View full article
Kasper.Vestrup Explorer
‎2026-01-15 05:39 AM

on ‎2026-01-15 05:39 AM

Labels:
  • Exp-6 Developer Guide
  • Experior 6
173 Views

Internal communication

Experior provides an infrastructure for sending messages between objects.   In the Developer samples catalog an example of how to do this can be found.   The basic steps are; Register an object as a listener. Core.Communication.Internal.AddListener(object listener, RecieveMessage method)   For example. Core.Communication.Internal.AddListener(this, ReceiveMethod);   Where a method like this should be provided. void ReceiveMethod(object sender, object reciever, object message, bool broadcast)   2. Send a message to a known receiver. Core.Communication.Internal.SendMessage(object sender, object reciever, object message)   Broadcast a message to all listeners. Core.Communication.Internal.BroadcastMessage(object sender, object message)   Broadcast a message to all listeners of a specific type. Core.Communication.Internal.BroadcastMessage(object sender, Type recieverType, object message)   Broadcast a message to all listeners of a specific type (FullName). Core.Communication.Internal.BroadcastMessage(object sender, string recieverTypeFullName, object message)   3. When an object should stop listen or is disposed it should be removed. Core.Communication.Internal.RemoveListener(object listener)   Note: The specified delegate of the reciever is executed synchronously.
View full article
Kasper.Vestrup Explorer
‎2026-01-15 05:37 AM

on ‎2026-01-15 05:37 AM

Labels:
  • Exp-6 Developer Guide
  • Experior 6
123 Views

Dynamic Properties

You can add properties to assemblies at runtime.   To enable the feature the class has to use the attribute Experior.Core.Properties.DynamicObjectConverter.   Example: Adding properties two properties Properties.Add(newDynamicProperty { Name = "Value1", Type = typeof(int), Description = "custom property (integer)",Category = "Testing", Value = 1 }); Properties.Add(newDynamicProperty { Name = "Value2", Type = typeof(float), Description = "custom property (float)", Category = "Testing", Value = 10.0f });   By overriding the DynamicPropertyChanged method the object can handle the changes made to the properties added above public override void DynamicPropertyChanged(DynamicProperty property) { Log.Write(property.Name + " is changed to " + property.Value); }   See the sample DynamicProperties class in the Demo catalog for more information
View full article
Kasper.Vestrup Explorer
‎2026-01-15 05:36 AM

on ‎2026-01-15 05:36 AM

Labels:
  • Exp-6 Developer Guide
  • Experior 6
103 Views

Reports – create custom class

This example shows how to create a custom statistics class that shows up in the generated report.   To add public values to the Statistics form window in Experior set the Observe value to true.   public class TestStatistics : Core.Reports.Statistics.Statistic { public override string Title { get { return "Test Statistics"; } } private double example; [DisplayName("Example field")] public double Example { get { return example; } set { if (value != example) { example = value; NotifyPropertyChanged("Example field"); } } } }
View full article
Kasper.Vestrup Explorer
‎2026-01-15 05:35 AM

on ‎2026-01-15 05:35 AM

Labels:
  • Exp-6 Developer Guide
  • Experior 6
152 Views

Thread safe methods in Experior

To safely change properties and call methods in Experior be sure that you are running in the “Engine thread”. If the Property Experior.Core.Environment.InvokeRequried is false, then you are running in the “Engine thread”. Otherwise you need to invoke the method call.   Example code:   private void SomeMethod() { if (Experior.Core.Environment.InvokeRequired) { //Not running in Experior Engine thread Experior.Core.Environment.Invoke(SomeMethod); return; } //Put method code here. //Code is executed in Experior engine thread //and it is safe to call Experior methods. ... }
View full article
Kasper.Vestrup Explorer
‎2026-01-15 05:34 AM

on ‎2026-01-15 05:34 AM

Labels:
  • Exp-6 Developer Guide
  • Experior 6
122 Views

Route class

Routes are used in Experior to move loads following a track (linear, curve) without usage of the physics engine. Therefore routes are mainly used in discrete event mode. Routes are implemented in Experior using the abstract base class Experior.Core.Routes.Route. A straight route is implemented by the Experior.Core.Routes.Linear class, while a curved route is implemented by the Experior.Core.Routes.Curve class.   Routes may contain Action Points which typically represent destination points or decision points. By connecting routes Experior calculates the routing graph based on the nodes (action points) in the network. This routing graph can be used to calculate the shortest path to a new destination (Action Point ).   To incorporate routes in the working area and other components they are usually encapsulated in a TransportSection assembly. The TransportSection assemblies themselves are used as building blocks in the different Track assemblies.   A Route keeps track of the loads that are moving on it and of the Action Points it contains.   Note: In discrete event mode loads are always on a Route or on an Action Point. (Loads that are Deletable will be automatically deleted by Experior when they are not on a Route or Action Point).   Main properties: List ActionPoints: Getter property that returns all action points on this route.   LinkedList Loads: Getter property that returns all loads on this route.   Load First: Getter property returning the first load on this route.   Load Last: Getter property returning the last load on this route.   bool Bidirectional: Property that indicates whether Experior should consider this route as bidirectional or not when constructing the routing graph. Suppose the route between action points AP1 and AP2 is bidirectional than this means that the routing graph will have two edges between the vertices AP1 and AP2. In case the bidirectional property is false only 1 directed edge from AP1 to AP2 is available. Setting the bidirectional property has no impact on the actual movement of the loads: the developer still has to ensure that a load can move in opposite direction.   Motor Motor: Property that gets/sets the Motor used to control the movements of the loads on this Route. Changing the speed of the motor will change the speed by which loads move on its route and changing the speed sign will make the loads move in opposite direction.   Vector3 Start: Property that gets/sets the global position of the startpoint of the route.   Vector3 End: Property that gets/sets the global position of the endpoint of the route.   float Yaw: Getter property that returns the global Yaw of this route.   float Length: Property that gets/sets the total length of this route   bool Vertical: Property that gets or sets whether the route is vertical or not. This has an impact on how loads are positioned on the route.   bool Visible: Gets or sets a value indicating whether this Experior.Core.Routes.Route is visible.   float Yaw: Getter property that returns the global Yaw of this route   Main events: event Route.ArrivedEvent Arrived: This event is raised when a load arrives. This is not synchronized with the discrete event execution.   event Route.LoadAddedEvent LoadAdded: This event is raised when a load is added to the route.   event Route.LoadRemovedEvent LoadRemoved: This event is raised when a load is removed from the route.   static event Route.UpdatedEvent Updated: This event is raised when the routing graph is updated.   Main methods: void Add(Load load): This method will add the given load to the start of this Route.   void Add(Load load, float distance): This method will add the given load to this Route at the given distance from the start.   void Remove(Load load): This method will remove the given load from this Route.   ActionPoint InsertActionPoint(float distance): This method will create and return an actionpoint and position it at the given distance from the start of this route.   void RemoveActionPoint(ActionPoint ap): This method will remove the given actionpoint ap from this route.   void ClearLoads(): This method will remove all loads from this route.   Main static methods: static ActionPoint FindNextActionPoint(ActionPoint ap): Given an actionpoint ap this method will return the next axtionpoint on the route (returns null if no actionpoint is found).   static ActionPoint FindNextActionPoint(Route route): Given a Route route this static method will return the first actionpoint on that route.   static ActionPoint FindNextActionPoint(ActionPoint ap, out float distance): Given an actionpoint ap this static method will return the next actionpoint on the route (if any) and put the distance between the two actionpoints in the distance out parameter. static ActionPoint FindPreviousActionPoint(ActionPoint ap, out float distance): Given an actionpoint ap this static method will return the previous actionpoint on the route of ap and put the distance between the two actionpoints in the distance out parameter. If the route of ap does not have a previous actionpoint then the previous route is looked at to find the previous actionpoint.   static float ShortestDistanceToActionPoint(Load load, string destination): Given a load and the name of an actionpoint this static method will return shortest distance from the current position of the load to the actionpoint by following the shortest path on the linked routes. If no path can be found float.PositiveInfinity is returned and a warning is logged.   static float ShortestDistanceToActionPoint(string sourceAP, string destinationAP): Given the name of a source actionpoint  and the name of a destination actionpoint this static method will return shortest distance between the two actionpoints by following the shortest path on the linked routes. If no path can be found float.PositiveInfinity is returned and a warning is logged.   static void Update(): This static method will result in the updating of the routing graph. (This is also called when a user deletes or adds an actionpoint)   Example: float distance = Route.ShortestDistanceToActionPoint(load, "AP3"); if (float.IsInfinity(distance)) { Experior.Core.Environment.Log.Write("No path found from load " + load.Identification + " to actionpoint AP3"); } else { Experior.Core.Environment.Log.Write("Distance from load " + load.Identification + "to actionpoint AP3=" + distance); } distance = Route.ShortestDistanceToActionPoint("AP2", "AP3"); if (float.IsInfinity(distance)) { Experior.Core.Environment.Log.Write("No path found between AP2 and AP3"); } else { Experior.Core.Environment.Log.Write("Distance from AP2 to AP3=" + distance); }
View full article
Kasper.Vestrup Explorer
‎2026-01-15 01:02 AM

Labels:
  • Exp-6 Developer Guide
  • Experior 6
153 Views
  • « Previous
    • 1
    • 2
    • 3
    • …
    • 8
  • Next »
To The Top!

Forums

  • APC UPS Data Center Backup Solutions
  • EcoStruxure IT
  • EcoStruxure Geo SCADA Expert
  • Metering & Power Quality
  • Schneider Electric Wiser

Knowledge Center

Events & webinars

Ideas

Blogs

Get Started

  • Ask the Community
  • Community Guidelines
  • Community User Guide
  • How-To & Best Practice
  • Experts Leaderboard
  • Contact Support

    Ask our Experts

    Have a question related to our products, solutions or services? Get quick support on community Forums

    Email Us

    For Community platform-related support, please email us

Subscribing is a smart move!
You can subscribe to this board after you log in or create your free account.
Forum-Icon

Create your free account or log in to subscribe to the board - and gain access to more than 10,000+ support articles along with insights from experts and peers.

Register today for FREE

Register Now

Already have an account? Login

Terms & Conditions Privacy Notice Change your Cookie Settings © 2026 Schneider Electric

Welcome!

Welcome to your new personalized space.

of

Explore