Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions Python/XA/KDC101/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# KDC101 Examples
Software examples for Thorlabs' KDC101 KCube

## kdc101_simple_example.py

This example shows basic functionality like connect, home, move and conversion between physical and device units.

## kdc101_test_script.py

This example shows the usage of more advanced methods.

121 changes: 121 additions & 0 deletions Python/XA/KDC101/kdc_simple_example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
"""
Example Title: KDC101 simple example
Example Date of Creation(YYYY-MM-DD) 2026-07-26
Example Date of Last Modification on Github 2026-07-26
Version of Python 3.13
Version of the Thorlabs XA 1.7.14
Version of Python wrapper 1.2.1.27471
==================
Example Description: The example shows how to connect to a KDC101 device, enable it, home it, and move it to an absolute position.
The example also shows how to convert between device units and physical units.
"""

import platform

from thorlabs_xa.products.kdc101 import Kdc101
from thorlabs_xa.shared.system_manager import SystemManager
from thorlabs_xa.shared.enums import TLMC_ScaleType, TLMC_EnableState, TLMC_Unit, TLMC_MoveMode, TLMC_OperatingMode,TLMC_ResultCode,TLMC_Wait
from thorlabs_xa.shared.params import TLMC_DeviceInfo, TLMC_Unit
from thorlabs_xa.shared.xa_error_factory import XADeviceException

KDC101_PART_NUMBER = "KDC101"
DEFAULT_TIMEOUT = 500

# Use simulated device to test the example if you do not have a KDC101 connected to your system. The simulation will be created with the following configuration:
SIMULATION_CONFIG_STRING = { "PartNumber" : KDC101_PART_NUMBER, "SerialNumber" : "27001234", "ActuatorType" : "MTS25-Z8" }

def create_simulation(system_manager: SystemManager) -> TLMC_DeviceInfo:

system_manager.create_simulation(SIMULATION_CONFIG_STRING)

device_info = TLMC_DeviceInfo()

device_info.device_type_description = SIMULATION_CONFIG_STRING["PartNumber"]
device_info.device = SIMULATION_CONFIG_STRING["SerialNumber"]
device_info.transport = ""

return device_info

def main():

# Create system manager for device discovery and management.
system_manager = SystemManager.instance()

if platform.system() == "Linux":
# If using Linux, we are required to state the port explicitly. Replace if you require an alternative port.
system_manager.startup("deviceDiscovery.connections=/dev/ttyUSB0")
else:
# If using Windows, we can use the default settings.
system_manager.startup()

# Find devices
devices = system_manager.get_device_list()
device_info: TLMC_DeviceInfo | None = None
if not devices:
print("No devices found, check that your device is powered and is visible to your system. Continuing with simulation!")
device_info = create_simulation(system_manager)
else:
print("Devices found:")
for listed_device_info in devices:
if listed_device_info.part_number == KDC101_PART_NUMBER:
device_info = listed_device_info
print("KDC101 found.")

if not device_info:
print("No KDC101 devices found, check that your device is powered and is visible to your system. Continuing with simulation!")
device_info = create_simulation(system_manager)


try:
# Create device object and enable device.
device = system_manager.open_device_as(device_info.device, device_info.transport, TLMC_OperatingMode.TLMC_OperatingMode_Default, Kdc101)

print("Enabling KDC101...")
device.set_enable_state(TLMC_EnableState.TLMC_Enabled)

enable_state = device.get_enable_state(DEFAULT_TIMEOUT)

if enable_state == TLMC_EnableState.TLMC_Enabled:
print("KDC101 enabled.")
else:
print("KDC101 not enabled as expected.")
return

# --- HOME ---
print("Homing...")
device.home(TLMC_Wait.TLMC_InfiniteWait)

# Get position after home
home_position_deviceunits = device.get_position_counter(TLMC_Wait.TLMC_InfiniteWait)
print(f"Position after home in device units: {home_position_deviceunits}")
# Converting position to physical units
home_position_physical, physical_unit = device.convert_from_device_units_to_physical(TLMC_ScaleType.TLMC_ScaleType_Distance, home_position_deviceunits)
print(f"Position after home: {home_position_physical} {physical_unit.name}")

# --- ABSOLUTE MOVE ---
#convert 2mm to device units
newposition_deviceunits = device.convert_from_physical_to_device(TLMC_ScaleType.TLMC_ScaleType_Distance, TLMC_Unit.TLMC_Unit_Millimetres, 2)

print("Move absolute to 2mm... ")
device.move(TLMC_MoveMode.TLMC_MoveMode_Absolute, newposition_deviceunits, TLMC_Wait.TLMC_InfiniteWait)

except XADeviceException as e:

print("Encountered error, code: ", e.error_code, TLMC_ResultCode(e.error_code).name)


finally:

if device is not None:
print("Shutting down KDC101...")
device.disconnect()
device.close()

print("Shutting down system...")
system_manager.shutdown()

print("Completed.")



main()
45 changes: 29 additions & 16 deletions Python/XA/xa_source/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,88 +7,101 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [1.3.0] - 2026-06-29

### Changed

- Internal native API improvements.
- Internal python API improvements.

## [1.2.1] - 2026-06-04

### Changed

- Resynchronize of wrapper python enumerations with those in the native API.

## [1.2.0] - 2026-06-02

### Added

- KST101 product API support (#10003).
- KST201 product API support (#10003).
- KST101 product API support.
- KST201 product API support.

## [1.1.11] - 2026-06-01

### Fixed

- In the native API, device with serial number unitialized in HW info is now discovered (#9926).
- In the native API, device with serial number uninitialized in HW info is now discovered.

## [1.1.10] - 2026-04-13

### Fixed

- In the native API, the conversion factor used to convert MicrostepsPerEncoderCount in StepperLoopParams is now correct (#9906).
- In the native API, the conversion factor used to convert MicrostepsPerEncoderCount in StepperLoopParams is now correct.

## [1.1.9] - 2026-04-10

### Fixed

- In the native API's StepperLoopParams, MicrostepsPerEncoderCount is now a signed 32-bit integer (previously unsigned) (#9906).
- In the native API's StepperLoopParams, MicrostepsPerEncoderCount is now a signed 32-bit integer (previously unsigned).

## [1.1.8] - 2026-04-10

### Changed

- Internal native API improvements (#9902).
- Internal native API improvements.

## [1.1.7] - 2026-04-08

### Fixed

- Removed deflection and velocity fields from the CurrentLoopParams structure (#9904).
- Removed deflection and velocity fields from the CurrentLoopParams structure.

## [1.1.6] - 2026-03-31

### Changed

- Added GitHub changelog URL to package metadata (#9903).
- Added GitHub changelog URL to package metadata.

## [1.1.5] - 2026-03-27

### Changed

- Internal native API improvements (#9899).
- Internal native API improvements.

## [1.1.4] - 2026-03-26

### Changed

- Internal native API improvements (#9895).
- Internal native API improvements.

## [1.1.3] - 2026-03-26

### Fixed

- Connected product information now correctly reported as "rotational - continuous" (rather than "rotational - fixed range") for FW103, FW6, FW12, HDR50 and NR360S stages (#9883).
- Connected product information now correctly reported as "rotational - continuous" (rather than "rotational - fixed range") for FW103, FW6, FW12, HDR50 and NR360S stages.

## [1.1.2] - 2026-03-20

### Added

- Added native API support for PDXC3 (#9879).
- Added native API support for PDXC3.

## [1.1.1] - 2026-03-03

### Changed

- Internal native API improvements (#9858).
- Internal native API improvements.

## [1.1.0] - 2026-02-19

### Added

- LTS product API support (#9851).
- KDC product API support (#9850).
- LTS product API support.
- KDC product API support.

## [1.0.0] - 2026-01-21

### Added

- Initial python wrapper API implementation (#9719, #9720).
- Initial python wrapper API implementation.
2 changes: 1 addition & 1 deletion Python/XA/xa_source/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ def get_tag(self):
author_email = "techsupport@thorlabs.com",
description = "Thorlabs XA Python SDK",
project_urls={
"Changelog": "https://github.com/Thorlabs/Motion_Control_Examples/blob/main/Python/XA/CHANGELOG.md"
"Changelog": "https://github.com/Thorlabs/Motion_Control_Examples/blob/main/Python/XA/xa_source/CHANGELOG.md"
},
long_description = read_me_content,
long_description_content_type="text/markdown",
Expand Down
20 changes: 7 additions & 13 deletions Python/XA/xa_source/src/thorlabs_xa/shared/c_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ class C_TLMC_CurrentLoopParams(Structure):
("integralLimit", c_uint16),
("integralDeadBand", c_uint16),
("feedForward", c_uint16),
("scalingFactor", c_float)
]


Expand Down Expand Up @@ -394,17 +395,6 @@ class C_TLMC_ProfileModeParams(Structure):
("reserved", c_int8 * 4)
]

class C_TLMC_PZ_IoTriggerParams(Structure):
_pack_ = 1
_fields_ = [
("numberOfPortsPerChannel", c_uint16),
("portNumber", c_uint16),
("portType", c_uint16),
("mode", c_uint16),
("polarity", c_uint16),
("triggerParameter1", c_int32),
("triggerParameter2", c_int32)
]

class C_TLMC_PZ_LnnxControlLoopParams(Structure):
_pack_ = 1
Expand Down Expand Up @@ -627,7 +617,7 @@ class C_TLMC_SettingItemChangedNotificationData(Structure):

class C_TLMC_StageAxisParams(Structure):
_pack_ = 1
_fields_ = [("typeId", c_uint16),
_fields_ = [("productId", c_uint16),
("axisId", c_uint16),
("partNumber", c_char * 16),
("serialNumber", c_uint32),
Expand All @@ -638,7 +628,11 @@ class C_TLMC_StageAxisParams(Structure):
("maxDeceleration", c_uint32),
("maxVelocity", c_uint32),
("gearBoxRatio", c_uint16),
("reserved", c_uint8 * 22)
("microSteps", c_uint16),
("positionScale", c_float),
("velocityScale", c_float),
("accelerationScale", c_float),
("reserved", c_uint8 * 8)
]


Expand Down
10 changes: 0 additions & 10 deletions Python/XA/xa_source/src/thorlabs_xa/shared/device_factory.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
from thorlabs_xa.implementations.device_feature_groups.kdc101_feature_group import Kdc101FeatureGroup
from thorlabs_xa.implementations.device_feature_groups.kpc101_feature_group import Kpc101FeatureGroup
from thorlabs_xa.implementations.device_feature_groups.kst201_feature_group import Kst201FeatureGroup
from thorlabs_xa.implementations.device_feature_groups.lnnx_feature_group import LnnxFeatureGroup
from thorlabs_xa.implementations.device_feature_groups.linear_translation_stage_feature_group import LinearTranslationStageFeatureGroup
from thorlabs_xa.implementations.device_feature_groups.lnnx_logical_channel_feature_group import LnnxLogicalChannelFeatureGroup

from thorlabs_xa.products.kdc101 import Kdc101
from thorlabs_xa.products.kpc101 import Kpc101
from thorlabs_xa.products.kst201 import Kst201
from thorlabs_xa.products.lnnx import Lnnx
from thorlabs_xa.products.linear_translation_stage import LinearTranslationStage
from thorlabs_xa.products.lnnx_logical_channel import LnnxLogicalChannel

from thorlabs_xa.native_sdks.native_functions import NativeFunctions

Expand All @@ -28,12 +24,6 @@ def create(self, device_handle: int, device_info: TLMC_DeviceInfo) -> Device:

# Note: It is expected that this will produce a pylance error until all device types are implemented
match device_info.device_type:
case TLMC_DeviceType.TLMC_DeviceType_LnnxBaseUnit:
feature_group = LnnxFeatureGroup(device_handle, self.native_functions)
return Lnnx(device_handle, device_info, feature_group, self.native_functions)
case TLMC_DeviceType.TLMC_DeviceType_LnnxLogicalChannel:
feature_group = LnnxLogicalChannelFeatureGroup(device_handle, self.native_functions)
return LnnxLogicalChannel(device_handle, device_info, feature_group, self.native_functions)
case TLMC_DeviceType.TLMC_DeviceType_Kdc101:
feature_group = Kdc101FeatureGroup(device_handle, self.native_functions)
return Kdc101(device_handle, device_info, feature_group, self.native_functions)
Expand Down
Loading