From 05cd07935d3fd9200537470f66201f65d312f517 Mon Sep 17 00:00:00 2001 From: Gold856 <117957790+Gold856@users.noreply.github.com> Date: Thu, 21 Dec 2023 01:51:57 -0500 Subject: [PATCH 1/5] Add documentation for simulation extensions --- simulation/README.md | 38 +++++++++++++++++++++++++++ simulation/halsim_ds_socket/README.md | 6 +++++ 2 files changed, 44 insertions(+) create mode 100644 simulation/README.md create mode 100644 simulation/halsim_ds_socket/README.md diff --git a/simulation/README.md b/simulation/README.md new file mode 100644 index 00000000000..8c8fa1b8045 --- /dev/null +++ b/simulation/README.md @@ -0,0 +1,38 @@ +# Simulation Extensions +This is where WPILib's simulation extensions are housed. Simulation extensions are referred to by a few names: simulation plugins, sim extensions, HALSIM extensions, but they all refer to the same thing, which are dynamically loaded libraries that can use HALSIM functions to register callbacks that update HAL data. The robot program loads simulation extensions by looking for the `HALSIM_EXTENSIONS` environment variable which contains colon separated paths to the libraries. + +# Writing a custom simulation extension +All simulation extensions contain a `int HALSIM_InitExtension(void)` function, which is the entry point. The function declaration should look like this: + +```c++ +extern "C" { +#if defined(WIN32) || defined(_WIN32) +__declspec(dllexport) +#endif +int HALSIM_InitExtension(void) { +} +} +``` + +The function is contained with an `extern "C"` block so it can be called by the robot program and has `__delspec(dllexport)` for Windows. From here, you can interface with the HAL to provide data. + +## Using HALSIM functions +Several devices in the HAL have functions that allow you to feed data from an external source into the HAL. The full list can be found in the HAL subdirectory in `include/hal/simulation`. For example, the AccelerometerData header declares functions that update the X, Y, and Z axes with data. Some functions accept callbacks; the I2CData header declares functions which accept other functions with parameters that allow it to accept data. This allows the implementation of a simulation extension that interfaces with an I2C bus and connects it to the HAL, allowing the use of real I2C hardware in simulation. + +## Building the extension +To build an extension for use in a robot project, you'll need to build with Gradle. The easiest way to get a working build.gradle file is to copy the build.gradle file from halsim_xrp. It doesn't have any tests, and it only depends on halsim_ws_core. The important line is `lib project: ':wpinet', library: 'wpinet', linkage: 'shared'`. This tells Gradle to link the extension with wpinet using shared libraries. Other libraries can be included in a similar way by referencing the Gradle subproject name. Note that you do not need to include the HAL since it is automatically included. + +# Using a custom extension +After setting up a build.gradle file for a custom extension, follow the guides to build and publish your own local build of allwpilib. Once you've published a local build, follow the instructions in [DevelopmentBuilds.md](/DevelopmentBuilds.md) to use the locally published build in a robot project. Then, place this line your robot project's build.gradle file: +```groovy +wpi.sim.addDep("Custom Sim Extension", "edu.wpi.first.halsim", "pluginName") +``` +where `Custom Sim Extension` is the name of the extension shown by VS Code and `pluginName` is the same as `pluginName` declared in the build.gradle file for the simulation extension. + +# Built-in extensions +halsim_ds_socket: Allows the real Driver Station to control the robot program. +halsim_gui: Provides the simulation GUI. +halsim_ws_client: A websockets client that allows robot hardware interface state to be transmitted over websockets. +halsim_ws_core: A websockets library for use by other extensions. Not directly usable. +halsim_ws_server: A websockets server that allows robot hardware interface state to be transmitted over websockets. +halsim_xrp: A client that supports the XRP protocol, allowing the robot program to control and receive data from the XRP. diff --git a/simulation/halsim_ds_socket/README.md b/simulation/halsim_ds_socket/README.md new file mode 100644 index 00000000000..c963d6ffe03 --- /dev/null +++ b/simulation/halsim_ds_socket/README.md @@ -0,0 +1,6 @@ +# HAL DS Socket +This is an extension that allows the Driver Station to communicate with the robot program. Note that not everything has been reimplemented, since lots of DS data like battery voltage doesn't apply in simulation. + +# Configuration + +The only environment variable the extension supports is `DS_TIMEOUT_MS`, which is the amount of milliseconds it takes for a UDP packet to arrive from the DS before the robot program automatically disables. Default value is 100 milliseconds. From be974a7ba7854e8259ba15bd01f372903df7ffc1 Mon Sep 17 00:00:00 2001 From: Gold856 <117957790+Gold856@users.noreply.github.com> Date: Sun, 24 Dec 2023 03:05:11 -0500 Subject: [PATCH 2/5] Touch up docs --- simulation/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/simulation/README.md b/simulation/README.md index 8c8fa1b8045..0a0241cb0b3 100644 --- a/simulation/README.md +++ b/simulation/README.md @@ -1,5 +1,5 @@ # Simulation Extensions -This is where WPILib's simulation extensions are housed. Simulation extensions are referred to by a few names: simulation plugins, sim extensions, HALSIM extensions, but they all refer to the same thing, which are dynamically loaded libraries that can use HALSIM functions to register callbacks that update HAL data. The robot program loads simulation extensions by looking for the `HALSIM_EXTENSIONS` environment variable which contains colon separated paths to the libraries. +This is where WPILib's simulation extensions are housed. Simulation extensions are referred to by various names: simulation plugins, simulation modules, sim extensions, HALSIM extensions, but they all refer to the same thing, which are dynamically loaded libraries that can use HALSIM functions to register callbacks that update HAL data. The robot program loads simulation extensions by looking for the `HALSIM_EXTENSIONS` environment variable which contains colon separated paths to the libraries. # Writing a custom simulation extension All simulation extensions contain a `int HALSIM_InitExtension(void)` function, which is the entry point. The function declaration should look like this: @@ -14,7 +14,7 @@ int HALSIM_InitExtension(void) { } ``` -The function is contained with an `extern "C"` block so it can be called by the robot program and has `__delspec(dllexport)` for Windows. From here, you can interface with the HAL to provide data. +The function is contained with an `extern "C"` block so it can be called by the robot program and has `__declspec(dllexport)` for Windows. From here, you can interface with the HAL to provide data. ## Using HALSIM functions Several devices in the HAL have functions that allow you to feed data from an external source into the HAL. The full list can be found in the HAL subdirectory in `include/hal/simulation`. For example, the AccelerometerData header declares functions that update the X, Y, and Z axes with data. Some functions accept callbacks; the I2CData header declares functions which accept other functions with parameters that allow it to accept data. This allows the implementation of a simulation extension that interfaces with an I2C bus and connects it to the HAL, allowing the use of real I2C hardware in simulation. From 7e94d2214c06d3027c88d566c2e55c8093c7da65 Mon Sep 17 00:00:00 2001 From: Gold856 <117957790+Gold856@users.noreply.github.com> Date: Wed, 27 Dec 2023 16:15:05 -0500 Subject: [PATCH 3/5] Separate the different extensions --- simulation/README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/simulation/README.md b/simulation/README.md index 0a0241cb0b3..d49f25f4266 100644 --- a/simulation/README.md +++ b/simulation/README.md @@ -31,8 +31,13 @@ where `Custom Sim Extension` is the name of the extension shown by VS Code and ` # Built-in extensions halsim_ds_socket: Allows the real Driver Station to control the robot program. + halsim_gui: Provides the simulation GUI. + halsim_ws_client: A websockets client that allows robot hardware interface state to be transmitted over websockets. + halsim_ws_core: A websockets library for use by other extensions. Not directly usable. + halsim_ws_server: A websockets server that allows robot hardware interface state to be transmitted over websockets. + halsim_xrp: A client that supports the XRP protocol, allowing the robot program to control and receive data from the XRP. From c5635cc95e84c1413d6ea3c45b4e48d576320bd6 Mon Sep 17 00:00:00 2001 From: Gold856 <117957790+Gold856@users.noreply.github.com> Date: Wed, 27 Dec 2023 16:16:10 -0500 Subject: [PATCH 4/5] Clarify configuration value --- simulation/halsim_ds_socket/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/simulation/halsim_ds_socket/README.md b/simulation/halsim_ds_socket/README.md index c963d6ffe03..c8f307838b1 100644 --- a/simulation/halsim_ds_socket/README.md +++ b/simulation/halsim_ds_socket/README.md @@ -3,4 +3,4 @@ This is an extension that allows the Driver Station to communicate with the robo # Configuration -The only environment variable the extension supports is `DS_TIMEOUT_MS`, which is the amount of milliseconds it takes for a UDP packet to arrive from the DS before the robot program automatically disables. Default value is 100 milliseconds. +The only environment variable the extension supports is `DS_TIMEOUT_MS`, which is the amount of milliseconds it takes for a UDP packet to arrive from the DS before the robot program automatically disables. Default value is `100`, representing 100 milliseconds. From ca2fef60494a66f8adb9266f133a89f14853570a Mon Sep 17 00:00:00 2001 From: Gold856 <117957790+Gold856@users.noreply.github.com> Date: Wed, 10 Jan 2024 15:13:19 -0500 Subject: [PATCH 5/5] Address review --- simulation/README.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/simulation/README.md b/simulation/README.md index d49f25f4266..7d2c40e69e0 100644 --- a/simulation/README.md +++ b/simulation/README.md @@ -1,5 +1,5 @@ # Simulation Extensions -This is where WPILib's simulation extensions are housed. Simulation extensions are referred to by various names: simulation plugins, simulation modules, sim extensions, HALSIM extensions, but they all refer to the same thing, which are dynamically loaded libraries that can use HALSIM functions to register callbacks that update HAL data. The robot program loads simulation extensions by looking for the `HALSIM_EXTENSIONS` environment variable which contains colon separated paths to the libraries. +This is where WPILib's simulation extensions are housed. Simulation extensions are referred to by various names: simulation plugins, simulation modules, sim extensions, HALSIM extensions, but they all refer to the same thing, which are dynamically loaded libraries that can use HALSIM functions to register callbacks that update HAL data. The robot program loads simulation extensions by looking for the `HALSIM_EXTENSIONS` environment variable, which contains the paths to the libraries separated by colons on Linux/Mac, and semicolons on Windows. # Writing a custom simulation extension All simulation extensions contain a `int HALSIM_InitExtension(void)` function, which is the entry point. The function declaration should look like this: @@ -16,8 +16,11 @@ int HALSIM_InitExtension(void) { The function is contained with an `extern "C"` block so it can be called by the robot program and has `__declspec(dllexport)` for Windows. From here, you can interface with the HAL to provide data. +## Extension registration +Extensions can register themselves by calling `HAL_RegisterExtension`. This will register the extension's name, and a pointer to some sort of data. A separate extension can listen for extension registration by calling `HAL_RegisterExtensionListener`. It takes a callback accepting the data initially passed into `HAL_RegisterExtension`. This can be used to detect if a specific extension was loaded, and take action if it was. Note that extensions must opt-in to registration; extensions that do not register will not trigger the registration listener. + ## Using HALSIM functions -Several devices in the HAL have functions that allow you to feed data from an external source into the HAL. The full list can be found in the HAL subdirectory in `include/hal/simulation`. For example, the AccelerometerData header declares functions that update the X, Y, and Z axes with data. Some functions accept callbacks; the I2CData header declares functions which accept other functions with parameters that allow it to accept data. This allows the implementation of a simulation extension that interfaces with an I2C bus and connects it to the HAL, allowing the use of real I2C hardware in simulation. +Several devices in the HAL have functions that allow you to feed data from an external source into the HAL. The full list can be found in the HAL subdirectory in `include/hal/simulation`. For example, the AccelerometerData header declares functions that update the X, Y, and Z axes with data. Some functions accept callbacks; the I2CData header declares functions which accept other functions with parameters that allow it to accept data. This allows the implementation of a simulation extension that interfaces with an I2C bus and connects it to the HAL, allowing the use of real I2C hardware in simulation. Note that these callbacks are called synchronously and in the same thread as the robot program; long delays in callbacks will block the main thread and can cause loop overruns. ## Building the extension To build an extension for use in a robot project, you'll need to build with Gradle. The easiest way to get a working build.gradle file is to copy the build.gradle file from halsim_xrp. It doesn't have any tests, and it only depends on halsim_ws_core. The important line is `lib project: ':wpinet', library: 'wpinet', linkage: 'shared'`. This tells Gradle to link the extension with wpinet using shared libraries. Other libraries can be included in a similar way by referencing the Gradle subproject name. Note that you do not need to include the HAL since it is automatically included.