Skip to content

Commit 4233cdc

Browse files
authored
Better sending of PSN packets (#5)
* updated docstings * better send example * byte encoding / decoding debug * tracker timestamp is unsigned long long too * fixed missing bit for tracker sub chunk * fixed missing bit for tracker sub chunk * typo in example * ran ruff * Added sending example to readme * Added unicast PSN sending * merged both uni- and multicast in one function * typo in example * typo in example * better example for uni-multi-casting psn * more extensive pack unpack test * updated README * ruff on example
1 parent 3972e65 commit 4233cdc

File tree

4 files changed

+310
-173
lines changed

4 files changed

+310
-173
lines changed

README.md

100644100755
Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ python -m pip install https://codeload.github.com/open-stage/python-psn/zip/refs
2525

2626
## Usage
2727

28+
### Receiving PSN data
2829
```python
2930
import pypsn
3031

@@ -45,15 +46,54 @@ receiver.start() # start the receiving thread
4546

4647
receiver.stop() # stop receiving
4748

49+
```
50+
51+
### Senfing PSN data
52+
```python
53+
import pypsn
54+
55+
# create a psn_info object with appropriate data
56+
psn_info = pypsn.PsnInfoPacket(
57+
info=pypsn.PsnInfo(
58+
timestamp=1312,
59+
version_high=2,
60+
version_low=0,
61+
frame_id=1,
62+
packet_count=1,
63+
),
64+
name="system_name_001",
65+
trackers=(
66+
[
67+
pypsn.PsnTrackerInfo(
68+
tracker_id=i,
69+
tracker_name="tracker_" + str(i),
70+
)
71+
for i in range(0, 8))
72+
]
73+
),
74+
)
75+
76+
# convert the object to a byte string
77+
psn_info_packet_bytes = pypsn.prepare_psn_info_packet_bytes(psn_info)
78+
79+
# send the PSN info via multicast
80+
pypsn.send_psn_packet(
81+
psn_packet=psn_info_packet_bytes,
82+
mcast_ip="236.10.10.10",
83+
ip_addr="192.168.1.42",
84+
mcast_port=56565,
85+
)
86+
4887
```
4988
See examples folder for some more examples.
5089

5190
## Development, status
5291

5392
- Supporting PSN V2
54-
- Parsing and sending (via [Multicast Expert](https://github.com/multiplemonomials/multicast_expert))
93+
- Parsing and sending (via [Multicast Expert](https://github.com/multiplemonomials/multicast_expert)) or via Unicast
5594
- Using threading module
5695
- Linux (Rpi OS incl.), Windows and macOS tested
96+
- PSN messages recognized by GrandMa3 2.1
5797
- Typed, no-strict
5898
- Initial pytest testing provided together with CI/CD setup
5999

examples/simple_send_and_receive/send_psn.py

Lines changed: 88 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,49 @@
11
#! /bin/env python3
22
"""
3-
Usage: python send_psn.py 192.168.1.4 <--- change IP address
3+
Usage:
4+
5+
multicast: python send_psn.py 1 192.168.1.4 236.10.10.10
6+
unicast: python send_psn.py 1 192.168.1.4
7+
8+
Args:
9+
- number of trackers to generate
10+
- local IP adress
11+
- multricast adress (opt)
12+
13+
Variables mapping for GrandMa3 users:
14+
15+
- pos.xyz -> Position X Y Z
16+
- speed.xyz -> Speed X Y Z
17+
- ori.xyz -> Rot X Y Z
18+
- accel.xyz -> None
19+
- trgtpos.xyz -> None
420
521
"""
622

723
import sys
24+
import time
825
import pypsn
926

27+
try:
28+
tracker_num = int(sys.argv[1])
29+
ip_addr = sys.argv[2]
30+
mcast_ip = None
31+
32+
if sys.argv[3]:
33+
mcast_ip = sys.argv[3]
34+
35+
except Exception as e:
36+
print("Args: tracker_num ip_addr mcast_ip (opt).")
37+
print(e)
38+
39+
start_time_us = time.time_ns() // 1000
1040

1141
psn_info = pypsn.PsnInfoPacket(
1242
info=pypsn.PsnInfo(
13-
timestamp=1312,
43+
timestamp=start_time_us,
1444
version_high=2,
1545
version_low=0,
16-
frame_id=56,
46+
frame_id=1,
1747
packet_count=1,
1848
),
1949
name="system_name_001",
@@ -23,13 +53,19 @@
2353
tracker_id=i,
2454
tracker_name="tracker_" + str(i),
2555
)
26-
for i in range(0, 7)
56+
for i in range(0, tracker_num)
2757
]
2858
),
2959
)
3060

3161
psn_data = pypsn.PsnDataPacket(
32-
info=psn_info.info,
62+
info=pypsn.PsnInfo(
63+
timestamp=start_time_us,
64+
version_high=2,
65+
version_low=0,
66+
frame_id=1,
67+
packet_count=1,
68+
),
3369
trackers=(
3470
[
3571
pypsn.PsnTracker(
@@ -50,6 +86,7 @@
5086
y=0.0,
5187
z=0.0,
5288
),
89+
status=0.5,
5390
accel=pypsn.PsnVector3(
5491
x=0.0,
5592
y=0.0,
@@ -60,15 +97,14 @@
6097
y=0.0,
6198
z=0.0,
6299
),
63-
status=0,
64-
timestamp=psn_info.info.timestamp,
100+
timestamp=start_time_us,
65101
)
66102
for tracker in psn_info.trackers
67103
]
68104
),
69105
)
70106

71-
print("\n--- PSN infos to be sent ---")
107+
print("\n--- PSN infos to be sent at 1Hz ---")
72108
print("system name: " + psn_info.name)
73109
print("timestamp: " + str(psn_info.info.timestamp))
74110
print("version_high: " + str(psn_info.info.version_high))
@@ -79,7 +115,7 @@
79115
for tracker in psn_info.trackers:
80116
print(str(tracker.tracker_id) + ": " + str(tracker.tracker_name))
81117

82-
print("\n--- PSN data to be sent ---")
118+
print("\n--- PSN data to be sent at 60Hz ---")
83119
print("timestamp: " + str(psn_data.info.timestamp))
84120
print("version_high: " + str(psn_data.info.version_high))
85121
print("version_low: " + str(psn_data.info.version_low))
@@ -108,19 +144,48 @@
108144
+ str(tracker.timestamp)
109145
)
110146

111-
psn_info_packet_bytes = pypsn.prepare_psn_info_packet_bytes(psn_info)
112-
psn_data_packet_bytes = pypsn.prepare_psn_data_packet_bytes(psn_data)
147+
print("\n--- Sendin PSN data in loop ---")
148+
counter = 0.0
113149

114-
pypsn.send_psn_packet(
115-
psn_packet=psn_info_packet_bytes,
116-
mcast_ip="236.10.10.10",
117-
ip_addr=sys.argv[1],
118-
mcast_port=56565,
119-
)
150+
while True:
151+
time.sleep(1 / 60)
152+
elapsed_time_us = time.time_ns() // 1000 - start_time_us
120153

121-
pypsn.send_psn_packet(
122-
psn_packet=psn_data_packet_bytes,
123-
mcast_ip="236.10.10.10",
124-
ip_addr=sys.argv[1],
125-
mcast_port=56565,
126-
)
154+
if counter < 6.0:
155+
counter += 0.1
156+
else:
157+
counter = 0.0
158+
159+
psn_info.info.timestamp = elapsed_time_us
160+
psn_info_packet_bytes = pypsn.prepare_psn_info_packet_bytes(psn_info)
161+
162+
pypsn.send_psn_packet(
163+
psn_packet=psn_info_packet_bytes,
164+
mcast_ip=mcast_ip,
165+
ip_addr=ip_addr,
166+
port=56565,
167+
)
168+
169+
psn_data.info.timestamp = elapsed_time_us
170+
171+
if psn_data.info.frame_id < 255:
172+
psn_data.info.frame_id += 1
173+
else:
174+
psn_data.info.frame_id = 0
175+
176+
for tracker in psn_data.trackers:
177+
tracker.timestamp = elapsed_time_us
178+
tracker.pos.x = counter
179+
tracker.speed.x = counter
180+
tracker.ori.x = counter
181+
tracker.accel.x = counter
182+
tracker.trgtpos.x = counter
183+
184+
psn_data_packet_bytes = pypsn.prepare_psn_data_packet_bytes(psn_data)
185+
186+
pypsn.send_psn_packet(
187+
psn_packet=psn_data_packet_bytes,
188+
mcast_ip=mcast_ip,
189+
ip_addr=ip_addr,
190+
port=56565,
191+
)

0 commit comments

Comments
 (0)