qtm-rt-pyside6 0.3.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. qtm_rt_pyside6-0.3.4/.github/workflows/ci.yml +37 -0
  2. qtm_rt_pyside6-0.3.4/.github/workflows/publish.yml +52 -0
  3. qtm_rt_pyside6-0.3.4/.gitignore +31 -0
  4. qtm_rt_pyside6-0.3.4/CLAUDE.md +99 -0
  5. qtm_rt_pyside6-0.3.4/LICENSE +21 -0
  6. qtm_rt_pyside6-0.3.4/PKG-INFO +155 -0
  7. qtm_rt_pyside6-0.3.4/README.md +131 -0
  8. qtm_rt_pyside6-0.3.4/THIRD_PARTY_LICENSES +46 -0
  9. qtm_rt_pyside6-0.3.4/examples/README.md +71 -0
  10. qtm_rt_pyside6-0.3.4/examples/basic_example.py +71 -0
  11. qtm_rt_pyside6-0.3.4/examples/discovery_example.py +43 -0
  12. qtm_rt_pyside6-0.3.4/examples/gui_3d_example/main.py +657 -0
  13. qtm_rt_pyside6-0.3.4/examples/gui_3d_example/main.qml +570 -0
  14. qtm_rt_pyside6-0.3.4/examples/gui_example.py +310 -0
  15. qtm_rt_pyside6-0.3.4/examples/parameters_example.py +94 -0
  16. qtm_rt_pyside6-0.3.4/pyproject.toml +54 -0
  17. qtm_rt_pyside6-0.3.4/qtm_rt_pyside6/__init__.py +23 -0
  18. qtm_rt_pyside6-0.3.4/qtm_rt_pyside6/connection.py +750 -0
  19. qtm_rt_pyside6-0.3.4/qtm_rt_pyside6/discovery.py +181 -0
  20. qtm_rt_pyside6-0.3.4/qtm_rt_pyside6.egg-info/PKG-INFO +155 -0
  21. qtm_rt_pyside6-0.3.4/qtm_rt_pyside6.egg-info/SOURCES.txt +27 -0
  22. qtm_rt_pyside6-0.3.4/qtm_rt_pyside6.egg-info/dependency_links.txt +1 -0
  23. qtm_rt_pyside6-0.3.4/qtm_rt_pyside6.egg-info/requires.txt +2 -0
  24. qtm_rt_pyside6-0.3.4/qtm_rt_pyside6.egg-info/top_level.txt +1 -0
  25. qtm_rt_pyside6-0.3.4/requirements-dev.txt +5 -0
  26. qtm_rt_pyside6-0.3.4/setup.cfg +4 -0
  27. qtm_rt_pyside6-0.3.4/tests/__init__.py +0 -0
  28. qtm_rt_pyside6-0.3.4/tests/test_connection.py +679 -0
  29. qtm_rt_pyside6-0.3.4/tests/test_discovery.py +156 -0
@@ -0,0 +1,37 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ lint:
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - uses: actions/checkout@v6
14
+ - uses: actions/setup-python@v6
15
+ with:
16
+ python-version: "3.x"
17
+ - run: pip install ruff
18
+ - run: ruff check .
19
+ - run: ruff format --check .
20
+
21
+ test:
22
+ runs-on: ubuntu-latest
23
+ strategy:
24
+ matrix:
25
+ python-version: ["3.10", "3.11", "3.12", "3.13", "3.x"]
26
+ env:
27
+ QT_QPA_PLATFORM: offscreen
28
+ steps:
29
+ - uses: actions/checkout@v6
30
+ - uses: actions/setup-python@v6
31
+ with:
32
+ python-version: ${{ matrix.python-version }}
33
+ - run: sudo apt-get update && sudo apt-get install -y libegl1
34
+ - run: |
35
+ pip install -r requirements-dev.txt
36
+ pip install -e .
37
+ - run: pytest -v
@@ -0,0 +1,52 @@
1
+ name: Publish
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+
7
+ permissions:
8
+ contents: write
9
+ id-token: write
10
+
11
+ jobs:
12
+ build:
13
+ runs-on: ubuntu-latest
14
+ steps:
15
+ - uses: actions/checkout@v6
16
+ with:
17
+ fetch-depth: 0
18
+ - uses: actions/setup-python@v6
19
+ with:
20
+ python-version: "3.x"
21
+ - run: pip install build
22
+ - run: python -m build
23
+ - uses: actions/upload-artifact@v7
24
+ with:
25
+ name: dist
26
+ path: dist/
27
+
28
+ publish-pypi:
29
+ needs: build
30
+ runs-on: ubuntu-latest
31
+ environment: pypi
32
+ permissions:
33
+ id-token: write
34
+ steps:
35
+ - uses: actions/download-artifact@v8
36
+ with:
37
+ name: dist
38
+ path: dist/
39
+ - uses: pypa/gh-action-pypi-publish@release/v1
40
+
41
+ upload-release-assets:
42
+ needs: build
43
+ runs-on: ubuntu-latest
44
+ steps:
45
+ - uses: actions/download-artifact@v8
46
+ with:
47
+ name: dist
48
+ path: dist/
49
+ - run: gh release upload "${{ github.event.release.tag_name }}" dist/*
50
+ env:
51
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
52
+ GH_REPO: ${{ github.repository }}
@@ -0,0 +1,31 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # Distribution / packaging
7
+ build/
8
+ dist/
9
+ *.egg-info/
10
+ *.egg
11
+
12
+ # Virtual environments
13
+ .venv/
14
+ venv/
15
+ ENV/
16
+
17
+ # IDE / AI tools
18
+ .idea/
19
+ .vscode/
20
+ .claude/
21
+ *.swp
22
+ *.swo
23
+
24
+ # Testing
25
+ .pytest_cache/
26
+ .coverage
27
+ htmlcov/
28
+
29
+ # OS
30
+ .DS_Store
31
+ Thumbs.db
@@ -0,0 +1,99 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+ ## Project Overview
6
+
7
+ PySide6-based SDK for QTM Real-Time Protocol. Uses Qt's network stack (`QTcpSocket`, `QUdpSocket`) and signals/slots pattern instead of asyncio. Reuses packet parsing code from the original `qtm-rt` SDK, pulled in as a pip dependency (`qtm-rt>=3.0.0`).
8
+
9
+ ## Development Commands
10
+
11
+ ```bash
12
+ # Setup environment (use Python 3.10+)
13
+ py -3.10 -m venv .venv
14
+ .venv/Scripts/activate # Windows
15
+ pip install -r requirements-dev.txt
16
+ pip install -e .
17
+
18
+ # Run all tests
19
+ pytest -v
20
+
21
+ # Run a single test file or test
22
+ pytest tests/test_connection.py -v
23
+ pytest tests/test_connection.py::TestQTMConnectionInit::test_creates_socket -v
24
+
25
+ # Run examples (requires QTM running)
26
+ python examples/basic_example.py
27
+ python examples/discovery_example.py
28
+ ```
29
+
30
+ ```bash
31
+ # Lint and format
32
+ ruff check .
33
+ ruff format --check .
34
+ ruff format . # auto-fix formatting
35
+ ```
36
+
37
+ Tests use `pytest-qt` (configured in `pyproject.toml` with `qt_api = pyside6`). Use `qtbot.waitSignal()` for signal assertions.
38
+
39
+ Version is derived from git tags via `setuptools-scm`. Tag a release with `v0.1.0` format.
40
+
41
+ ## Architecture
42
+
43
+ ### Module Structure
44
+
45
+ - **`qtm_rt`** - Original SDK installed from PyPI (`qtm-rt>=3.0.0`). We import `packet` and `receiver` for binary parsing
46
+ - **`qtm_rt_pyside6/connection.py`** - `QTMConnection(QObject)` main class using `QTcpSocket`
47
+ - **`qtm_rt_pyside6/discovery.py`** - `QTMDiscovery(QObject)` for UDP broadcast discovery
48
+
49
+ ### Signal Pattern
50
+
51
+ The SDK uses Qt signals instead of async/await:
52
+
53
+ ```python
54
+ # Connection state
55
+ connected = Signal()
56
+ disconnected = Signal()
57
+ error = Signal(str)
58
+
59
+ # Streaming (high-frequency)
60
+ packetReceived = Signal(object) # QRTPacket
61
+ eventReceived = Signal(object) # QRTEvent
62
+
63
+ # Request/response (generic)
64
+ responseReceived = Signal(str, object) # (command_name, data)
65
+ ```
66
+
67
+ ### Response Handling
68
+
69
+ Commands that expect responses emit via `responseReceived(command, data)`. Use the helper for cleaner code:
70
+
71
+ ```python
72
+ connection.onResponse("getparameters", self.handle_parameters)
73
+ connection.getParameters(["3d"])
74
+ ```
75
+
76
+ ### Reused Components from `qtm-rt`
77
+
78
+ - `qtm_rt.packet` - `QRTPacket`, `QRTEvent`, all struct definitions and namedtuples
79
+ - `qtm_rt.receiver` - `Receiver` class for packet reassembly (called from `_onReadyRead`)
80
+
81
+ ### Data Flow
82
+
83
+ 1. `QTMConnection.connectToHost(host)` -> `QTcpSocket.connectToHost()`
84
+ 2. Socket `connected` signal -> send version command -> emit `connected` signal
85
+ 3. `streamFrames(components)` -> sends command to QTM
86
+ 4. Socket `readyRead` -> `Receiver.data_received()` -> packet handlers -> emit `packetReceived`
87
+
88
+ ### Protocol Defaults
89
+
90
+ - TCP port: 22223 (little-endian)
91
+ - UDP discovery port: 22226
92
+ - Protocol version: "1.25"
93
+ - Logger name: `"qtm_rt_pyside6"`
94
+
95
+ ### Valid Identifiers
96
+
97
+ **Streaming components:** `2d`, `2dlin`, `3d`, `3dres`, `3dnolabels`, `3dnolabelsres`, `analog`, `analogsingle`, `force`, `forcesingle`, `6d`, `6dres`, `6deuler`, `6deulerres`, `gazevector`, `eyetracker`, `image`, `timecode`, `skeleton`, `skeleton:global`
98
+
99
+ **Parameter names for `getParameters()`:** `all`, `general`, `3d`, `6d`, `analog`, `force`, `gazevector`, `eyetracker`, `image`, `skeleton`, `skeleton:global`, `calibration`
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Qualisys AB
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,155 @@
1
+ Metadata-Version: 2.4
2
+ Name: qtm-rt-pyside6
3
+ Version: 0.3.4
4
+ Summary: PySide6 SDK for QTM Real-Time Protocol
5
+ Author-email: Qualisys AB <support@qualisys.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/qualisys/qualisys_pyside6_sdk
8
+ Classifier: Operating System :: OS Independent
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.10
12
+ Classifier: Programming Language :: Python :: 3.11
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Classifier: Programming Language :: Python :: 3.13
15
+ Classifier: Topic :: Scientific/Engineering
16
+ Classifier: Topic :: Utilities
17
+ Requires-Python: >=3.10
18
+ Description-Content-Type: text/markdown
19
+ License-File: LICENSE
20
+ License-File: THIRD_PARTY_LICENSES
21
+ Requires-Dist: PySide6>=6.0.0
22
+ Requires-Dist: qtm-rt>=3.0.0
23
+ Dynamic: license-file
24
+
25
+ # Qualisys PySide6 SDK
26
+
27
+ [![PyPI](https://img.shields.io/pypi/v/qtm-rt-pyside6)](https://pypi.org/project/qtm-rt-pyside6/)
28
+
29
+ PySide6-based SDK for the Qualisys Real-Time (RT) protocol. Stream motion capture data from QTM using Qt's native networking and signals/slots.
30
+
31
+ ## Installation
32
+
33
+ Requires Python 3.10+ and PySide6 6.0+.
34
+
35
+ We recommend using a virtual environment to avoid conflicts with other packages:
36
+
37
+ ```bash
38
+ # Create and activate a virtual environment
39
+ python -m venv .venv
40
+
41
+ # Windows
42
+ .venv\Scripts\activate
43
+
44
+ # macOS / Linux
45
+ source .venv/bin/activate
46
+ ```
47
+
48
+ Then install the package:
49
+
50
+ ```bash
51
+ pip install qtm-rt-pyside6
52
+ ```
53
+
54
+ ## Quick Start
55
+
56
+ ```python
57
+ import sys
58
+ from PySide6.QtCore import QCoreApplication
59
+ from qtm_rt_pyside6 import QTMConnection, QRTPacket
60
+
61
+ def on_packet(packet: QRTPacket):
62
+ print(f"Frame {packet.framenumber}")
63
+ result = packet.get_3d_markers()
64
+ if result:
65
+ header, markers = result
66
+ for marker in markers:
67
+ print(f" {marker.x}, {marker.y}, {marker.z}")
68
+
69
+ app = QCoreApplication(sys.argv)
70
+
71
+ connection = QTMConnection()
72
+ connection.connected.connect(lambda: connection.streamFrames(["3d"]))
73
+ connection.packetReceived.connect(on_packet)
74
+ connection.error.connect(lambda msg: print(f"Error: {msg}"))
75
+ connection.connectToHost("127.0.0.1")
76
+
77
+ sys.exit(app.exec())
78
+ ```
79
+
80
+ ## API
81
+
82
+ ### QTMConnection Signals
83
+
84
+ | Signal | Description |
85
+ |--------|-------------|
86
+ | `connected()` | Successfully connected and version negotiated |
87
+ | `disconnected()` | Disconnected from QTM |
88
+ | `error(str)` | Connection or protocol error |
89
+ | `packetReceived(QRTPacket)` | Data packet during streaming |
90
+ | `eventReceived(QRTEvent)` | QTM event (capture started, etc.) |
91
+ | `responseReceived(str, object)` | Command response (command_name, data) |
92
+
93
+ ### QTMConnection Methods
94
+
95
+ Core methods to get started:
96
+
97
+ - `connectToHost(host, port=22223, version="1.25", timeout_ms=5000)` — Connect to QTM
98
+ - `disconnectFromHost()` — Close the connection
99
+ - `streamFrames(components, frames="allframes", udp_port=None, udp_address=None)` — Start streaming; pass `udp_port` to receive frames over UDP instead of TCP
100
+ - `streamFramesStop()` — Stop streaming
101
+ - `getParameters(parameters)` — Request current configuration as XML
102
+
103
+ See the class docstring or run `help(QTMConnection)` for the full method
104
+ list — control, load/save, trigger, LED, quit, XML settings, etc.
105
+
106
+ ### Components
107
+
108
+ Valid streaming components: `2d`, `2dlin`, `3d`, `3dres`, `3dnolabels`, `3dnolabelsres`, `analog`, `analogsingle`, `force`, `forcesingle`, `6d`, `6dres`, `6deuler`, `6deulerres`, `gazevector`, `eyetracker`, `image`, `timecode`, `skeleton`, `skeleton:global`
109
+
110
+ ## Examples
111
+
112
+ Ready-to-run scripts live in [examples/](examples/) — see
113
+ [examples/README.md](examples/README.md) for what each one demonstrates
114
+ and how to run it. `basic_example.py` is the shortest path to verify
115
+ your setup; the GUI examples (`gui_example.py` and `gui_3d_example/`)
116
+ show how to wire the SDK into a desktop application.
117
+
118
+ ## Known Limitations
119
+
120
+ - **No automatic reconnection.** If the connection drops, you must call `connectToHost()` again. Listen to the `disconnected` signal to detect this.
121
+ - **Single-threaded.** `QTMConnection` and `QTMDiscovery` are `QObject` subclasses and must be used from the thread that created them (typically the main thread). Use Qt signals for cross-thread communication.
122
+ - **Password sent in plain text.** `takeControl(password)` transmits the password unencrypted over TCP. This is a QTM protocol limitation — use on trusted networks only.
123
+
124
+ ## Development
125
+
126
+ To work on the SDK itself:
127
+
128
+ ```bash
129
+ git clone https://github.com/qualisys/qualisys_pyside6_sdk.git
130
+ cd qualisys_pyside6_sdk
131
+
132
+ # Create and activate a virtual environment
133
+ python -m venv .venv
134
+
135
+ # Windows
136
+ .venv\Scripts\activate
137
+
138
+ # macOS / Linux
139
+ source .venv/bin/activate
140
+
141
+ # Install dev dependencies (pytest, pytest-qt, ruff, build) and the package
142
+ pip install -r requirements-dev.txt
143
+ pip install -e .
144
+ ```
145
+
146
+ Run tests and linting:
147
+ ```bash
148
+ pytest -v
149
+ ruff check .
150
+ ruff format --check .
151
+ ```
152
+
153
+ ## License
154
+
155
+ MIT — see [LICENSE](LICENSE) and [THIRD_PARTY_LICENSES](THIRD_PARTY_LICENSES).
@@ -0,0 +1,131 @@
1
+ # Qualisys PySide6 SDK
2
+
3
+ [![PyPI](https://img.shields.io/pypi/v/qtm-rt-pyside6)](https://pypi.org/project/qtm-rt-pyside6/)
4
+
5
+ PySide6-based SDK for the Qualisys Real-Time (RT) protocol. Stream motion capture data from QTM using Qt's native networking and signals/slots.
6
+
7
+ ## Installation
8
+
9
+ Requires Python 3.10+ and PySide6 6.0+.
10
+
11
+ We recommend using a virtual environment to avoid conflicts with other packages:
12
+
13
+ ```bash
14
+ # Create and activate a virtual environment
15
+ python -m venv .venv
16
+
17
+ # Windows
18
+ .venv\Scripts\activate
19
+
20
+ # macOS / Linux
21
+ source .venv/bin/activate
22
+ ```
23
+
24
+ Then install the package:
25
+
26
+ ```bash
27
+ pip install qtm-rt-pyside6
28
+ ```
29
+
30
+ ## Quick Start
31
+
32
+ ```python
33
+ import sys
34
+ from PySide6.QtCore import QCoreApplication
35
+ from qtm_rt_pyside6 import QTMConnection, QRTPacket
36
+
37
+ def on_packet(packet: QRTPacket):
38
+ print(f"Frame {packet.framenumber}")
39
+ result = packet.get_3d_markers()
40
+ if result:
41
+ header, markers = result
42
+ for marker in markers:
43
+ print(f" {marker.x}, {marker.y}, {marker.z}")
44
+
45
+ app = QCoreApplication(sys.argv)
46
+
47
+ connection = QTMConnection()
48
+ connection.connected.connect(lambda: connection.streamFrames(["3d"]))
49
+ connection.packetReceived.connect(on_packet)
50
+ connection.error.connect(lambda msg: print(f"Error: {msg}"))
51
+ connection.connectToHost("127.0.0.1")
52
+
53
+ sys.exit(app.exec())
54
+ ```
55
+
56
+ ## API
57
+
58
+ ### QTMConnection Signals
59
+
60
+ | Signal | Description |
61
+ |--------|-------------|
62
+ | `connected()` | Successfully connected and version negotiated |
63
+ | `disconnected()` | Disconnected from QTM |
64
+ | `error(str)` | Connection or protocol error |
65
+ | `packetReceived(QRTPacket)` | Data packet during streaming |
66
+ | `eventReceived(QRTEvent)` | QTM event (capture started, etc.) |
67
+ | `responseReceived(str, object)` | Command response (command_name, data) |
68
+
69
+ ### QTMConnection Methods
70
+
71
+ Core methods to get started:
72
+
73
+ - `connectToHost(host, port=22223, version="1.25", timeout_ms=5000)` — Connect to QTM
74
+ - `disconnectFromHost()` — Close the connection
75
+ - `streamFrames(components, frames="allframes", udp_port=None, udp_address=None)` — Start streaming; pass `udp_port` to receive frames over UDP instead of TCP
76
+ - `streamFramesStop()` — Stop streaming
77
+ - `getParameters(parameters)` — Request current configuration as XML
78
+
79
+ See the class docstring or run `help(QTMConnection)` for the full method
80
+ list — control, load/save, trigger, LED, quit, XML settings, etc.
81
+
82
+ ### Components
83
+
84
+ Valid streaming components: `2d`, `2dlin`, `3d`, `3dres`, `3dnolabels`, `3dnolabelsres`, `analog`, `analogsingle`, `force`, `forcesingle`, `6d`, `6dres`, `6deuler`, `6deulerres`, `gazevector`, `eyetracker`, `image`, `timecode`, `skeleton`, `skeleton:global`
85
+
86
+ ## Examples
87
+
88
+ Ready-to-run scripts live in [examples/](examples/) — see
89
+ [examples/README.md](examples/README.md) for what each one demonstrates
90
+ and how to run it. `basic_example.py` is the shortest path to verify
91
+ your setup; the GUI examples (`gui_example.py` and `gui_3d_example/`)
92
+ show how to wire the SDK into a desktop application.
93
+
94
+ ## Known Limitations
95
+
96
+ - **No automatic reconnection.** If the connection drops, you must call `connectToHost()` again. Listen to the `disconnected` signal to detect this.
97
+ - **Single-threaded.** `QTMConnection` and `QTMDiscovery` are `QObject` subclasses and must be used from the thread that created them (typically the main thread). Use Qt signals for cross-thread communication.
98
+ - **Password sent in plain text.** `takeControl(password)` transmits the password unencrypted over TCP. This is a QTM protocol limitation — use on trusted networks only.
99
+
100
+ ## Development
101
+
102
+ To work on the SDK itself:
103
+
104
+ ```bash
105
+ git clone https://github.com/qualisys/qualisys_pyside6_sdk.git
106
+ cd qualisys_pyside6_sdk
107
+
108
+ # Create and activate a virtual environment
109
+ python -m venv .venv
110
+
111
+ # Windows
112
+ .venv\Scripts\activate
113
+
114
+ # macOS / Linux
115
+ source .venv/bin/activate
116
+
117
+ # Install dev dependencies (pytest, pytest-qt, ruff, build) and the package
118
+ pip install -r requirements-dev.txt
119
+ pip install -e .
120
+ ```
121
+
122
+ Run tests and linting:
123
+ ```bash
124
+ pytest -v
125
+ ruff check .
126
+ ruff format --check .
127
+ ```
128
+
129
+ ## License
130
+
131
+ MIT — see [LICENSE](LICENSE) and [THIRD_PARTY_LICENSES](THIRD_PARTY_LICENSES).
@@ -0,0 +1,46 @@
1
+ This project uses the following third-party libraries:
2
+
3
+ ================================================================================
4
+ PySide6 — The Qt Company
5
+ ================================================================================
6
+
7
+ License: GNU Lesser General Public License v3.0 (LGPL-3.0)
8
+ Homepage: https://www.qt.io/qt-for-python
9
+ Source: https://code.qt.io/cgit/pyside/pyside-setup.git
10
+
11
+ PySide6 provides Python bindings for the Qt framework. It is used as a runtime
12
+ dependency and is dynamically linked. Users may replace PySide6 with any
13
+ compatible version under the terms of the LGPL v3.
14
+
15
+ The full text of the LGPL v3 license is available at:
16
+ https://www.gnu.org/licenses/lgpl-3.0.html
17
+
18
+ ================================================================================
19
+ Qualisys Python SDK (qtm_rt) — Qualisys AB
20
+ ================================================================================
21
+
22
+ License: MIT
23
+ Homepage: https://github.com/qualisys/qualisys_python_sdk
24
+ Included as: Git submodule (qtm_rt/)
25
+
26
+ The MIT License (MIT)
27
+
28
+ Copyright (c) 2015-2016 Qualisys
29
+
30
+ Permission is hereby granted, free of charge, to any person obtaining a copy
31
+ of this software and associated documentation files (the "Software"), to deal
32
+ in the Software without restriction, including without limitation the rights
33
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
34
+ copies of the Software, and to permit persons to whom the Software is
35
+ furnished to do so, subject to the following conditions:
36
+
37
+ The above copyright notice and this permission notice shall be included in all
38
+ copies or substantial portions of the Software.
39
+
40
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
41
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
42
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
43
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
44
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
45
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
46
+ SOFTWARE.
@@ -0,0 +1,71 @@
1
+ # Examples
2
+
3
+ Ready-to-run scripts demonstrating `qtm-rt-pyside6`. Each example is
4
+ self-contained — install the package, start QTM, and run.
5
+
6
+ ## Prerequisites
7
+
8
+ - A QTM installation reachable on the network (or `127.0.0.1` if local).
9
+ - `qtm-rt-pyside6` installed (`pip install qtm-rt-pyside6`, or
10
+ `pip install -e .` from a checkout).
11
+ - For the streaming examples, QTM should be playing back data — load a
12
+ file in QTM and choose **Play → Play with Real-Time output**, or run
13
+ a live capture.
14
+ - The 3D and Widgets GUI examples need a display; the rest run in a
15
+ plain console.
16
+
17
+ ## Quick reference
18
+
19
+ | Script | What it shows | Run |
20
+ |---|---|---|
21
+ | [`basic_example.py`](basic_example.py) | Stream 3D markers to the console, exit cleanly after 100 frames | `python basic_example.py` |
22
+ | [`discovery_example.py`](discovery_example.py) | UDP-broadcast discovery of QTM instances on the network | `python discovery_example.py [interface_ip]` |
23
+ | [`parameters_example.py`](parameters_example.py) | Request QTM configuration as XML and parse 3D markers, 6DOF bodies, and skeletons out of it | `python parameters_example.py` |
24
+ | [`gui_example.py`](gui_example.py) | Qt Widgets app combining discovery, connect/disconnect, and a live data table with frame rate | `python gui_example.py` |
25
+ | [`gui_3d_example/main.py`](gui_3d_example/main.py) | Qt Quick 3D viewer showing markers as spheres and skeletons as bones, with an orbit camera | `python gui_3d_example/main.py` |
26
+
27
+ If you're new to the SDK, start with `basic_example.py` to confirm the
28
+ connection works, then look at `discovery_example.py` or one of the GUI
29
+ examples depending on what you're building.
30
+
31
+ ## Notes on individual examples
32
+
33
+ ### `basic_example.py`
34
+ Minimal connect-and-stream loop. Exits automatically after 100 frames
35
+ (`FRAME_LIMIT`) so it's safe to run unattended.
36
+
37
+ ### `discovery_example.py`
38
+ Sends a UDP broadcast on port 22226 and prints every QTM instance that
39
+ replies within the 2-second timeout.
40
+
41
+ On machines with multiple network interfaces, the broadcast may not
42
+ reach the QTM subnet when bound to "any" interface. Pass the local
43
+ interface IP as the first argument to bind explicitly:
44
+
45
+ ```
46
+ python discovery_example.py 192.168.10.100
47
+ ```
48
+
49
+ ### `parameters_example.py`
50
+ Connects, requests `3d`, `6d`, and `skeleton` parameters, parses the
51
+ returned XML, and prints marker / body / skeleton names. Useful as a
52
+ template for any "fetch and inspect QTM configuration" task.
53
+
54
+ ### `gui_example.py`
55
+ PySide6 / QtWidgets app with discovery, connection management, and a
56
+ live data table. A good starting point for desktop tools built on top
57
+ of the SDK.
58
+
59
+ ### `gui_3d_example/`
60
+ PySide6 / Qt Quick 3D scene that streams 3D markers, 6DOF bodies, and
61
+ skeletons from QTM and renders them as primitives with an orbit
62
+ camera. The Python `main.py` provides the data backend; `main.qml`
63
+ defines the scene.
64
+
65
+ ## Known limitation: TCP streaming only in these examples
66
+
67
+ All streaming examples use TCP (the default). The SDK also supports
68
+ UDP streaming via `streamFrames(..., udp_port=...)` — see the
69
+ `QTMConnection` docstring or `help(QTMConnection)` for details. None
70
+ of the bundled examples currently demonstrate UDP; contributions
71
+ welcome.