restructure the repository
This commit is contained in:
parent
63230b7754
commit
936acf8703
12 changed files with 9 additions and 344 deletions
22
Notes.md
22
Notes.md
|
@ -1,22 +0,0 @@
|
|||
# Resources
|
||||
|
||||
- [vrpn-rs description of VRPN protocol](https://github.com/vrpn/vrpn-rs/blob/main/Protocol.md)
|
||||
|
||||
# Design
|
||||
|
||||
Allow for a session based design - data needs to be collected per block
|
||||
and immediatly made available. Minimal or no internal state keeping!
|
||||
|
||||
- first collect names and ids of message_types and senders (stored in session)
|
||||
- register listeners in session
|
||||
- listeners inject captured data with signals
|
||||
|
||||
- keep naming "classic" ??? ... above session is a tracker with a sender with sensors
|
||||
|
||||
# Todo
|
||||
- Testset for Quaternion rotations
|
||||
- Axis as subscene
|
||||
|
||||
# Internal Notes
|
||||
|
||||
- Graphics Interaction Lab OptiTrack system is at 212.201.64.122
|
197
VRPN.gd
197
VRPN.gd
|
@ -1,197 +0,0 @@
|
|||
extends Node
|
||||
class_name VRPN
|
||||
|
||||
# tracking associated data
|
||||
enum TrackingData { POS_QUAT, VELOCITY, ACCELERATION }
|
||||
|
||||
# magic cookie
|
||||
const magic_cookie_start : String = "vrpn: ver."
|
||||
# kinda redundant as we take the seq number as well
|
||||
static var header_size : int = aligned_size(20)
|
||||
|
||||
|
||||
var sensors : Dictionary[int,String] = {}
|
||||
var messages : Dictionary[int,String] = {}
|
||||
|
||||
signal connected(s:StreamPeerTCP)
|
||||
signal data(data:Array)
|
||||
signal disconnected
|
||||
signal error
|
||||
|
||||
@export var tracker_receivers : Array[VRPN_Receiver] = []
|
||||
|
||||
@onready var _stream: StreamPeerTCP = StreamPeerTCP.new()
|
||||
|
||||
@export var vrpn_server : String = "127.0.0.1"
|
||||
@export var vrpn_port : int = 3883
|
||||
|
||||
func _ready() -> void:
|
||||
|
||||
self.connect_to_host(vrpn_server,vrpn_port)
|
||||
|
||||
if not connected.has_connections():
|
||||
connected.connect(self._on_connected)
|
||||
if not data.has_connections():
|
||||
data.connect(self._on_data)
|
||||
if not disconnected.has_connections():
|
||||
disconnected.connect(self._on_disconnected)
|
||||
if not error.has_connections():
|
||||
error.connect(self._on_error)
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
var old_status = _stream.get_status()
|
||||
_stream.poll()
|
||||
var new_status = _stream.get_status()
|
||||
if old_status != new_status:
|
||||
match new_status:
|
||||
_stream.STATUS_NONE:
|
||||
emit_signal("disconnected")
|
||||
_stream.STATUS_CONNECTING:
|
||||
print("Connecting.")
|
||||
_stream.STATUS_CONNECTED:
|
||||
print("Connected.")
|
||||
emit_signal("connected",_stream.poll()
|
||||
)
|
||||
_stream.STATUS_ERROR:
|
||||
print("Error with socket stream.")
|
||||
emit_signal("error")
|
||||
|
||||
if new_status == _stream.STATUS_CONNECTED:
|
||||
var available_bytes: int = _stream.get_available_bytes()
|
||||
if available_bytes > 0:
|
||||
var res = _stream.get_partial_data(available_bytes)
|
||||
if res[0] != OK:
|
||||
emit_signal("error")
|
||||
else:
|
||||
emit_signal("data", res[1])
|
||||
|
||||
func connect_to_host(host: String, port: int) -> void:
|
||||
print("Connecting to %s:%d" % [host, port])
|
||||
if _stream.connect_to_host(host, port) != OK:
|
||||
print("Error connecting to host.")
|
||||
emit_signal("error")
|
||||
|
||||
func send(data: PackedByteArray) -> bool:
|
||||
if _stream.get_status() != _stream.STATUS_CONNECTED:
|
||||
print("Error: Stream is not currently connected.")
|
||||
return false
|
||||
var error: int = _stream.put_data(data)
|
||||
if error != OK:
|
||||
print("Error writing to stream: ", error)
|
||||
return false
|
||||
return true
|
||||
|
||||
|
||||
func _on_data(data : Array):
|
||||
var bytes = PackedByteArray(data)
|
||||
var as_cookie = bytes.get_string_from_ascii()
|
||||
|
||||
# Cookie Hack!
|
||||
if as_cookie.begins_with(VRPN.magic_cookie_start): #
|
||||
# kaboom we just send back the same cookie :)
|
||||
self.send(bytes)
|
||||
else:
|
||||
VRPN.marshall_block(bytes,self)
|
||||
|
||||
|
||||
func _on_connected(s : StreamPeerTCP):
|
||||
print("Connected to",s.get_connected_host()) # Replace with function body.
|
||||
|
||||
func _on_disconnected():
|
||||
print("Disconnected") # Replace with function body.
|
||||
|
||||
func _on_error():
|
||||
print("Error") # Replace with function body.
|
||||
|
||||
|
||||
static func marshall_block(data : PackedByteArray,session : VRPN) -> void:
|
||||
|
||||
# need to fix that
|
||||
var block_offset : int = 0
|
||||
|
||||
while data.size() > block_offset:
|
||||
# reader for stream
|
||||
var header := StreamPeerBuffer.new()
|
||||
# get block addresses
|
||||
header.data_array = data.slice(block_offset,block_offset+header_size)
|
||||
# make sure we read as big endian
|
||||
header.big_endian = true
|
||||
|
||||
# read header
|
||||
var length := header.get_32() as int # length of message
|
||||
var time_sec := header.get_32() as int # datetime sec
|
||||
var time_msec := header.get_32() as int # datetime micro sec
|
||||
var sender_id := header.get_32() as int # sender id
|
||||
var message_type := header.get_32() as int # type of message (payload)
|
||||
var sequence_num := header.get_32() as int # inofficial sequence number (padding)
|
||||
|
||||
if false:
|
||||
print("length '%d'" % length)
|
||||
print("time_sec '%d'" % time_sec)
|
||||
print("time_msec '%d'" % time_msec)
|
||||
print("sender_id '%d'" % sender_id)
|
||||
print("message_type '%d'" % message_type)
|
||||
print("sequence_num '%d'" % sequence_num)
|
||||
|
||||
marshall_body(data.slice(block_offset+header_size,block_offset+length),message_type,sender_id,session)
|
||||
|
||||
# next datablock
|
||||
block_offset += aligned_size(length)
|
||||
|
||||
static func decode_string(stream : StreamPeerBuffer) -> String:
|
||||
var len = stream.get_32()
|
||||
return stream.get_string(len)
|
||||
|
||||
|
||||
static func marshall_body(data : PackedByteArray,message_type : int, sender_id: int, session : VRPN):
|
||||
var body := StreamPeerBuffer.new()
|
||||
body.data_array = data
|
||||
body.big_endian = true
|
||||
|
||||
# only take message_type directly for negative (-1,-2)
|
||||
# messages that provide dynamic descriptors
|
||||
if message_type < 0:
|
||||
# message and sender descriptions
|
||||
match message_type:
|
||||
-1: # sensor names
|
||||
var name = decode_string(body)
|
||||
print("sensor name is '%s' with '%d" % [name,sender_id])
|
||||
session.sensors[sender_id] = name
|
||||
-2: # message names
|
||||
var name = decode_string(body)
|
||||
print("message name is '%s' for message_type '%d'" % [name,sender_id])
|
||||
session.messages[sender_id] = name
|
||||
return
|
||||
|
||||
# now we use the string identifiers
|
||||
# because they are supposedly dynamically assigned
|
||||
match session.messages[message_type]:
|
||||
'vrpn_Tracker Pos_Quat': # quat pos
|
||||
# get id
|
||||
var sensor_id = body.get_32()
|
||||
var padding = body.get_32() # padding
|
||||
var pos = Vector3(body.get_double(),body.get_double(),body.get_double())
|
||||
# VRPN quaternions are w,xyz
|
||||
var quat_w = body.get_double()
|
||||
var quat_x = body.get_double()
|
||||
var quat_y = body.get_double()
|
||||
var quat_z = body.get_double()
|
||||
#var quat = Quaternion(quat_x,quat_y,quat_z,quat_w).normalized()
|
||||
# bug? Documentation of Godot Quaternion c'tor is x,y,x,w
|
||||
# but implementation follow classic w,x,y,z order
|
||||
var quat = Quaternion(quat_w,quat_x,quat_y,quat_z).normalized()
|
||||
|
||||
for r in session.tracker_receivers:
|
||||
r._on_pos_quat({
|
||||
"tracker" : session.sensors[sender_id],
|
||||
"sensor" : sensor_id,
|
||||
"position" : pos,
|
||||
"rotation" : quat
|
||||
})
|
||||
_:
|
||||
pass
|
||||
#print("unhandled message type {0}".format([message_type]))
|
||||
|
||||
|
||||
static func aligned_size(actual_size : int, alignment : int = 8) -> int:
|
||||
return (actual_size + alignment - 1) & ~(alignment - 1)
|
|
@ -1 +0,0 @@
|
|||
uid://dmq3i7qmo1qe0
|
|
@ -1,17 +0,0 @@
|
|||
extends Node3D
|
||||
|
||||
class_name VRPN_Receiver
|
||||
|
||||
@export var tracker_name : String = "Tracker0"
|
||||
@export var tracker_sensor : int = 0
|
||||
@export var tracker_use_position : bool = true
|
||||
@export var tracker_use_rotation : bool = true
|
||||
|
||||
func _on_pos_quat(tracker_data : Dictionary):
|
||||
|
||||
if tracker_data['tracker'] == tracker_name and tracker_data['sensor'] == tracker_sensor:
|
||||
if tracker_use_position:
|
||||
self.global_position = tracker_data['position']
|
||||
if tracker_use_rotation:
|
||||
var rotation := tracker_data['rotation'] as Quaternion
|
||||
self.global_basis = Basis(rotation)
|
|
@ -1 +0,0 @@
|
|||
uid://dpj1wrvfsiq4v
|
|
@ -1,8 +1,8 @@
|
|||
[gd_scene load_steps=5 format=3 uid="uid://bj5ykdjle10tt"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://dmq3i7qmo1qe0" path="res://VRPN.gd" id="2_24d08"]
|
||||
[ext_resource type="Script" uid="uid://dpj1wrvfsiq4v" path="res://VRPN_Receiver.gd" id="2_170dk"]
|
||||
[ext_resource type="PackedScene" uid="uid://b426fy7d6jw2d" path="res://axis.blend" id="3_170dk"]
|
||||
[ext_resource type="Script" uid="uid://dmq3i7qmo1qe0" path="res://addons/vrpn/scripts/VRPN.gd" id="2_24d08"]
|
||||
[ext_resource type="Script" uid="uid://dpj1wrvfsiq4v" path="res://addons/vrpn/scripts/VRPN_Receiver.gd" id="2_170dk"]
|
||||
[ext_resource type="PackedScene" uid="uid://b426fy7d6jw2d" path="res://addons/vrpn/assets/axis.blend" id="3_170dk"]
|
||||
|
||||
[sub_resource type="PlaneMesh" id="PlaneMesh_24d08"]
|
||||
size = Vector2(6, 2)
|
||||
|
@ -21,9 +21,9 @@ shadow_enabled = true
|
|||
[node name="VRPN" type="Node3D" parent="Root" node_paths=PackedStringArray("tracker_receivers")]
|
||||
script = ExtResource("2_24d08")
|
||||
tracker_receivers = [NodePath("RB1"), NodePath("RB2"), NodePath("../SpinTracker/Offset0/Tracker0"), NodePath("../SpinTracker/Tracker1"), NodePath("../SpinTracker/Offset2/Tracker2")]
|
||||
vrpn_server = "212.201.64.122"
|
||||
|
||||
[node name="RB1" type="Node3D" parent="Root/VRPN"]
|
||||
visible = false
|
||||
script = ExtResource("2_170dk")
|
||||
tracker_name = "RB1"
|
||||
|
||||
|
@ -31,6 +31,7 @@ tracker_name = "RB1"
|
|||
transform = Transform3D(0.1, 0, 0, 0, 0.1, 0, 0, 0, 0.1, 0, 0, 0)
|
||||
|
||||
[node name="RB2" type="Node3D" parent="Root/VRPN"]
|
||||
visible = false
|
||||
script = ExtResource("2_170dk")
|
||||
tracker_name = "RB2"
|
||||
|
||||
|
@ -46,11 +47,11 @@ mesh = SubResource("PlaneMesh_24d08")
|
|||
|
||||
[node name="SpinTracker" type="Node3D" parent="Root"]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.764802, 0)
|
||||
visible = false
|
||||
|
||||
[node name="Tracker1" type="Node3D" parent="Root/SpinTracker"]
|
||||
script = ExtResource("2_170dk")
|
||||
tracker_name = "Tracker1"
|
||||
tracker_use_position = false
|
||||
|
||||
[node name="axis2" parent="Root/SpinTracker/Tracker1" instance=ExtResource("3_170dk")]
|
||||
transform = Transform3D(0.1, 0, 0, 0, 0.1, 0, 0, 0, 0.1, 0, 0, 0)
|
||||
|
@ -65,6 +66,7 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1, 0, 0)
|
|||
[node name="Tracker2" type="Node3D" parent="Root/SpinTracker/Offset2"]
|
||||
script = ExtResource("2_170dk")
|
||||
tracker_name = "Tracker2"
|
||||
tracker_use_position = false
|
||||
|
||||
[node name="axis" parent="Root/SpinTracker/Offset2/Tracker2" instance=ExtResource("3_170dk")]
|
||||
transform = Transform3D(0.1, 0, 0, 0, 0.1, 0, 0, 0, 0.1, 0, 0, 0)
|
||||
|
@ -78,6 +80,7 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0)
|
|||
|
||||
[node name="Tracker0" type="Node3D" parent="Root/SpinTracker/Offset0"]
|
||||
script = ExtResource("2_170dk")
|
||||
tracker_use_position = false
|
||||
|
||||
[node name="axis" parent="Root/SpinTracker/Offset0/Tracker0" instance=ExtResource("3_170dk")]
|
||||
transform = Transform3D(0.1, 0, 0, 0, 0.1, 0, 0, 0, 0.1, 0, 0, 0)
|
BIN
axis.blend
BIN
axis.blend
Binary file not shown.
|
@ -1,62 +0,0 @@
|
|||
[remap]
|
||||
|
||||
importer="scene"
|
||||
importer_version=1
|
||||
type="PackedScene"
|
||||
uid="uid://b426fy7d6jw2d"
|
||||
path="res://.godot/imported/axis.blend-5b7f41137e49e6b98e717dd423c9150b.scn"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://axis.blend"
|
||||
dest_files=["res://.godot/imported/axis.blend-5b7f41137e49e6b98e717dd423c9150b.scn"]
|
||||
|
||||
[params]
|
||||
|
||||
nodes/root_type=""
|
||||
nodes/root_name=""
|
||||
nodes/apply_root_scale=true
|
||||
nodes/root_scale=1.0
|
||||
nodes/import_as_skeleton_bones=false
|
||||
nodes/use_node_type_suffixes=true
|
||||
meshes/ensure_tangents=true
|
||||
meshes/generate_lods=true
|
||||
meshes/create_shadow_meshes=true
|
||||
meshes/light_baking=1
|
||||
meshes/lightmap_texel_size=0.2
|
||||
meshes/force_disable_compression=false
|
||||
skins/use_named_skins=true
|
||||
animation/import=true
|
||||
animation/fps=30
|
||||
animation/trimming=false
|
||||
animation/remove_immutable_tracks=true
|
||||
animation/import_rest_as_RESET=false
|
||||
import_script/path=""
|
||||
_subresources={
|
||||
"nodes": {
|
||||
"PATH:Camera": {
|
||||
"import/skip_import": true
|
||||
},
|
||||
"PATH:Light": {
|
||||
"import/skip_import": true
|
||||
}
|
||||
}
|
||||
}
|
||||
blender/nodes/visible=0
|
||||
blender/nodes/active_collection_only=false
|
||||
blender/nodes/punctual_lights=true
|
||||
blender/nodes/cameras=true
|
||||
blender/nodes/custom_properties=true
|
||||
blender/nodes/modifiers=1
|
||||
blender/meshes/colors=false
|
||||
blender/meshes/uvs=true
|
||||
blender/meshes/normals=true
|
||||
blender/meshes/export_geometry_nodes_instances=false
|
||||
blender/meshes/tangents=true
|
||||
blender/meshes/skins=2
|
||||
blender/meshes/export_bones_deforming_mesh_only=false
|
||||
blender/materials/unpack_enabled=true
|
||||
blender/materials/export_materials=1
|
||||
blender/animation/limit_playback=true
|
||||
blender/animation/always_sample=true
|
||||
blender/animation/group_tracks=true
|
1
icon.svg
1
icon.svg
|
@ -1 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128"><rect width="124" height="124" x="2" y="2" fill="#363d52" stroke="#212532" stroke-width="4" rx="14"/><g fill="#fff" transform="translate(12.322 12.322)scale(.101)"><path d="M105 673v33q407 354 814 0v-33z"/><path fill="#478cbf" d="m105 673 152 14q12 1 15 14l4 67 132 10 8-61q2-11 15-15h162q13 4 15 15l8 61 132-10 4-67q3-13 15-14l152-14V427q30-39 56-81-35-59-83-108-43 20-82 47-40-37-88-64 7-51 8-102-59-28-123-42-26 43-46 89-49-7-98 0-20-46-46-89-64 14-123 42 1 51 8 102-48 27-88 64-39-27-82-47-48 49-83 108 26 42 56 81zm0 33v39c0 276 813 276 814 0v-39l-134 12-5 69q-2 10-14 13l-162 11q-12 0-16-11l-10-65H446l-10 65q-4 11-16 11l-162-11q-12-3-14-13l-5-69z"/><path d="M483 600c0 34 58 34 58 0v-86c0-34-58-34-58 0z"/><circle cx="725" cy="526" r="90"/><circle cx="299" cy="526" r="90"/></g><g fill="#414042" transform="translate(12.322 12.322)scale(.101)"><circle cx="307" cy="532" r="60"/><circle cx="717" cy="532" r="60"/></g></svg>
|
Before Width: | Height: | Size: 994 B |
|
@ -1,37 +0,0 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://cdprcmtx102rp"
|
||||
path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://icon.svg"
|
||||
dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
svg/scale=1.0
|
||||
editor/scale_with_editor_scale=false
|
||||
editor/convert_colors_with_editor_theme=false
|
|
@ -13,4 +13,4 @@ config_version=5
|
|||
config/name="uvrpn"
|
||||
run/main_scene="uid://bj5ykdjle10tt"
|
||||
config/features=PackedStringArray("4.4", "Forward Plus")
|
||||
config/icon="res://icon.svg"
|
||||
config/icon="uid://cdprcmtx102rp"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue