An extensible C++17 library for controlling Thorlabs Kinesis motion devices.
Explore the docs »
View Usage
·
Report Bug
·
Request Feature
Table of Contents
DegorasKinesis is a production-quality, extensible C++17 library for controlling Thorlabs Kinesis motion devices. It grows out of a validated proof of concept (the M30X / M30XY benchtop DC servo drivers) and is rebuilt as a reusable library that additional Kinesis device families can join without architectural changes.
It currently ships drivers for the single-axis M30X and the dual-axis M30XY benchtop DC-servo stages and the K10CR2/M motorized rotation stage (an integrated-stepper device, in degrees), behind a hardware-agnostic motion interface, with deterministic resource ownership, a thread-safe per-device locking model, an explicit error model, and an asynchronous status-polling/callback facility.
The library is organised in layers. The layer-boundary rule: a given vendor SDK module header is included only in its own Layer-2 adapter, so a new device on a different Kinesis module is added as a new Layer-2 adapter plus a thin Layer-3 personality — by composition, never a shared base class — reusing the lower layers unchanged.
| Layer | Folders | Knows about | Examples |
|---|---|---|---|
| 1 — generic infrastructure | Global/, Common/, Helpers/ |
nothing vendor-specific | export macro; OperationResult, DeviceError, motion vocabulary; StatusPoller<StatusT>, waitForCondition, JSON helpers |
| K — shared Kinesis family | Kinesis/ |
the Kinesis-family C API shared across modules | discovery/per-serial locks, KinesisSimulatorSession, MotorStatusFlags + decodeMotorStatus (the shared MOT status word), categoryFromKinesis, enumerateByTypeId |
| 2 — per-SDK-module adapter | DCServo/, IntStepper/ |
one Kinesis module's C API | DCServoChannel (Benchtop DC Servo, BDC_*); IntStepperController (Integrated Stepper, ISC_*) |
| 3 — device personalities | Devices/ |
one device's identity & axis count | M30X (1 axis), M30XY (2 axes), K10CR2 (1 rotation axis, degrees), behind IMotionDevice |
Within Layer 1: Global/ holds the export macro, Common/ the motion vocabulary and result/error model, and
Helpers/ the generic infrastructure. The shared Kinesis/ layer holds the module-agnostic Kinesis plumbing
reused by every adapter (the status word is identical across the DC-servo and integrated-stepper modules).
Headers are consumed individually as #include "DegorasKinesis/<Folder>/<file>.h", or a whole group via a
module aggregator: #include <DegorasKinesis/Modules/Devices> (also Common, Helpers, Kinesis,
DCServo, IntStepper).
- C++17
- CMake (>= 3.21) and Ninja, driven by CMake Presets
- MSYS2 MinGW (UCRT64) toolchain — GCC
- Thorlabs Kinesis SDK (Benchtop DC Servo + Integrated Stepper Motors), vendored under
thirdparty/
- An MSYS2 MinGW prefix providing GCC, Ninja and (optionally) windres. UCRT64 is the reference prefix.
- CMake >= 3.21.
- The
MINGW_ROOTenvironment variable pointing at the prefix (e.g.E:/msys64/ucrt64). The providedCMakeUserPresets.jsonsets this for the local machine — adjust it for yours.
The CMake project root is the inner DegorasKinesis/ directory. Configure and build with a preset:
cd DegorasKinesis
cmake --preset local-mingw-dynamic-deb
cmake --build --preset local-mingw-dynamic-debProject presets in CMakePresets.json cover mingw-{dynamic,static}-{deb,rel}; the local-* user presets
just add your MINGW_ROOT. Build options: DEGORASKINESIS_BUILD_SHARED (default ON),
DEGORASKINESIS_BUILD_TESTING, DEGORASKINESIS_BUILD_EXAMPLES.
Artifacts land in build/<preset>/bin/ at the repository root. The build stages, next to the binaries,
both the vendored Thorlabs DLLs and the MinGW C++ runtime (libstdc++-6.dll, libgcc_s_seh-1.dll,
libwinpthread-1.dll), so the executables run without the toolchain on PATH.
#include <DegorasKinesis/Modules/Kinesis> // KinesisSimulatorSession
#include <DegorasKinesis/Modules/Devices> // M30XY, K10CR2, IMotionDevice, status types
using namespace dpkin;
using namespace dpkin::kinesis; // KinesisSimulatorSession, discovery, status decode
using dpkin::types::Channel;
using dpkin::types::OperationResult;
int main()
{
// Optional: connect to the Kinesis Simulator (a no-op against real hardware).
KinesisSimulatorSession sim;
types::ThorlabsSNList serials;
if (M30XY::getDeviceList(serials) != OperationResult::OPERATION_OK || serials.empty())
return 1;
M30XY dev(serials.front()); // no device I/O in the constructor
if (dev.doConnect() != OperationResult::OPERATION_OK)
return 1;
dev.doEnableChannels(true);
dev.doHomeAll();
dev.waitForHomed(Channel::X_CHANNEL, std::chrono::seconds(60));
dev.doMoveAbsolute(Channel::X_CHANNEL, 5.0); // millimetres
dev.waitForMoveFinished(Channel::X_CHANNEL, std::chrono::seconds(30));
dev.doDisconnect(); // also handled by the destructor
}The single-axis M30X and the rotation-stage K10CR2 are used the same way with one channel
(Channel::X_CHANNEL); a non-existent channel returns OperationResult::INVALID_CHANNEL. For the K10CR2,
positions and distances are in degrees rather than millimetres. Device::isCompatibleSerial(serial) checks
whether a serial number belongs to that device type (Thorlabs serials begin with the device type id). See the
examples/ directory for complete programs (M30X_control, M30XY_control, K10CR2_control); each accepts an
optional device serial on the command line and otherwise uses the first discovered device of that type.
There is no test-framework dependency: the testing/ executables are plain assert()-based checks, named
UT_* for hardware-free unit tests and Test_* for integration tests (build with
DEGORASKINESIS_BUILD_TESTING=ON). The examples/ demos (Example_*) build with
DEGORASKINESIS_BUILD_EXAMPLES=ON; each is a self-contained subproject (<name>/CMakeLists.txt +
main.cpp) — the generic basic_device_discovery, basic_device_connection, multi_device_control and the
device-specific M30X_control, M30XY_control, K10CR2_control. Everything runs from build/<preset>/bin/.
UT_*— vocabulary/error mapping, status decode, the status poller, and JSON round-trip. No hardware.Test_M30XYSim/Test_M30XSim/Test_K10CR2Sim [serial]— full SDK round-trip against the Kinesis Simulator (serial55000002for the K10CR2); each optionally takes a device serial, else uses the first discovered; self-skip if absent.Test_Concurrency— same-serial aliasing and two-device concurrent stress.Test_M30XYMonitor [seconds] [serial]/Test_K10CR2Monitor [seconds] [serial]— connect and continuously print decoded status while running a scripted home / jog / move sequence; you can also drive the stage manually in the simulator and watch it evolve.Test_M30XYHardware— gated behind--i-have-hardware; conservative moves only. Read its safety notice before running on real optics.
Warning
The Kinesis Simulator exposes the devices and the full command/status path works, but it cannot be assigned a stage (travel range), so it does not physically translate position. The device tests therefore assert the SDK contract and only log position. Full physical-motion validation requires real hardware.
- Install/export + CMake package config (
find_package(DegorasKinesis)→Degoras::Kinesis) and a vcpkg overlay port. Seedocs/PACKAGING.md. - Integrated Stepper Motors module (K10CR2/M rotation stage) as the
IntStepper/Layer-2 adapter. - Further Kinesis device families (e.g. KCube / brushless) as new Layer-2 adapters, reusing the shared
Kinesis/layer. - Migrate the generic, project-agnostic infrastructure (status poller, wait helper, JSON utilities) into LibDegorasBase so it is shared rather than reimplemented per project.
Distributed under the GNU General Public License v3.0 (or later). See the full text in the
LICENSE file for details.
Degoras Project Team — Spanish Navy Observatory SLR station (SFEL), San Fernando.
- Ángel Vera Herrera — avera@roa.es · angelvh.engr@gmail.com
- Jesús Relinque Madroñal — jrelinque@roa.es
- Thorlabs Kinesis — the underlying motion-control SDK.
- Real Instituto y Observatorio de la Armada (ROA) and the SFEL SLR station, San Fernando.
- Best-README-Template.