Custom Components: Creating a Simulation Class
Creating the Files
This tutorial will use the Editor.CSharp
solution. This particular solution will contain some example C# code that will be written in this tutorial, but it can be used to store any additional C# code that may be written by the user and exported into Nominal Editor. When opening the solution in Visual Studio (as an example), the following screen will be displayed, with none or some code.
Note
This tutorial will use Visual Studio 2022 as the main compiler and IDE for the C# Editor. Provided you are able the build the solution, there are other alternatives for the IDE if wanted.
A new C# file will need to be created here, which will be done in the Solution Explorer. This is typically found on the right-hand side of the screen. Right-click on the Editor.CSharp
solution and select Add
→ New Folder
. Inside the folder, right-click on the folder and select Add
→ New Item
. In this case, it will be named ExampleSolarPanel.cs
.
Once created, by default, the script will look something like the following:
Instead, to keep the code consistent, change the code to have the following. Note that the namespace is important here and for these examples, the namespace should be Editor
without any of the sub-namespace. When importing custom C# scripts within Nominal Editor, the namespace is required and needs to be known.
namespace Editor;
public class ExampleSolarPanel
{
}
Inheritance
Similar to many other languages, C# has inheritance with its object-oriented programming. This particular component will inherit all of the properties and methods that a solar panel already has, so it can be inherited from this solution. Most components are found within the NominalSystems.Classes
namespace, including all sensors, power objects, data objects, software and actuators. To include this namespace, use the using
tag at the top of the script, which will ensure that the script has reference to these components. The Solar Panel
can be inherited in the class definition. The class should now look like the following:
using NominalSystems.Classes;
namespace Editor;
public class ExampleSolarPanel : SolarPanel
{
}
The next functions to add are the constructor and the overridden functions OnBegin
and OnUpdate
. These can be overridden using the override
keyword.
public ExampleSolarPanel() { }
protected override void OnBegin(double time) {
base.OnBegin(time);
}
protected override void OnUpdate(double time, double step) {
base.OnUpdate(time, step);
}
Warning
All components using Nominal’s simulation system MUST have a default constructor. This is required for the serializer to work and components without a constructor may not be added to the simulation correctly. This is not the same requirement for the OnBegin
and OnUpdate
events.
Simulation Functions
The OnBegin
and OnUpdate
functions are simulation functions that are called by the simulator. When the simulation first starts running, it will call every component that is added to the simulation’s OnBegin
event and pass in the time that the simulation is starting. This is typically zero seconds for a majority of simulations. The purpose of this function is to initialize any variables or perform checks on the variable data. The OnUpdate
event is called every simulation tick and passes in the current simulation time at the tick and the step between each frame. This event should be used to update data and publish data to messages.
In each case, when overriding these functions, it is a requirement that the base.OnBegin(time)
, and the same with the update function, are called within the function. This ensures the base functionality within the solar panel is called still. Without making these calls, the function will be purely overridden and the solar panel will not function as expected. Although we are building a custom solar panel, we still require the base functionality of the component.
There are additional simulation functions that can be overridden if required, based on the use case. These include:
- OnFinish: Called when the simulation stops running
- OnReset: Called when the simulation resets from another point in time
- OnPostAttachChild: Called when a component is added to this component
More functions can be found by typing override
in Visual Studio and seeing the options that pop up. Alternatively, these functions can be found in the API manual in the documentation for the solar panel component (or any child component).