Streaming data to Python via unicast and multicast

NatNet, VRPN, TrackD, and Plugins
Post Reply
csims
Posts: 2
Joined: Mon Nov 09, 2015 7:42 am

Streaming data to Python via unicast and multicast

Post by csims »

I'm attempting to read streaming data from Motive Tracker. I'm trying to read the data using a Python application running on a second computer. I've adapted the example in PacketClient.cpp, and managed to get a version working to connect via Multicast. A simpler program that tries to connect via Unicast doesn't work. Comments on both short programs are below. Can anyone provide any insight as to what's going on?

I'm using Motive Tracker v1.5.0, NatNet Streaming Module v2.5.0.0. Both computers are running Windows 7 with firewall disabled.

Version #1, connect via unicast.

Code: Select all

## This version doesn't work. Why not??
##    It connects to the correct server address and 
##    data port via socket.connect().
##    Motive Tracker is set to broadcast via Unicast.

import socket as socket
import struct as struct

SOCKET_BUFSIZE = 0x100000

client_address = '172.22.193.58'
server_address = '172.22.193.57' ## Motive Tracker set to Unicast
command_port = 1510
data_port = 1511

## Connect to server address
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, 0)
sock.connect((server_address, data_port)) ## <--- Using the server address
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, SOCKET_BUFSIZE)

## Set to non-blocking
sock.setblocking(0)

## The socket connects without error, but never reads any data
while True:
    try:
        ## This never reads any data
        msg, address = sock.recvfrom(SOCKET_BUFSIZE)
    except:
        pass
    else:
        print(msg, "\n")

Version #2, connect via multicast.

Code: Select all

## Connect via Multicast. This version works.

import socket as socket
import struct as struct

SOCKET_BUFSIZE = 0x100000

client_address = '172.22.193.58'
server_address = '172.22.193.57' ## Motive Tracker set to Multicast
multicast_address = '239.255.42.99'
command_port = 1510
data_port = 1511

# Bind client address at data port
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, 0)
sock.bind((client_address, data_port))
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, SOCKET_BUFSIZE)
    
# Add the client IP address to the multicast group
mreq = struct.pack("=4s4s",
                    socket.inet_aton(multicast_address),
                    socket.inet_aton(client_address))
sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)

# Set to non-blocking
sock.setblocking(0)

while True:
    try:
        msg, address = sock.recvfrom(SOCKET_BUFSIZE)
    except:
        pass
    else:
        print(msg, "\n")
Last edited by csims on Mon Nov 09, 2015 10:05 am, edited 1 time in total.
csims
Posts: 2
Joined: Mon Nov 09, 2015 7:42 am

Re: Streaming data to Python via unicast and multicast

Post by csims »

Okay, about an hour after posting this I discovered two issues that resolve the problem (at least in my version of the software).

1) In unicast mode, Motive Tracker apparently sends data over the command port, not the data port. The PacketClient.cpp example creates both a command and data socket, but the data socket is irrelevant in unicast mode.

2) Tracker will not begin streaming data over the command port until it first receives a command from the client.

For future reference, below is a minimal working example of reading from Motive Tracker in unicast mode on a remote machine via Python:

Code: Select all

import socket as socket
import struct as struct

NATNET_PING = 0

MAX_PACKETSIZE = 100000
SOCKET_BUFSIZE = 0x100000

client_address = '172.22.193.58'
server_address = '172.22.193.57'
command_port = 1510

def ConnectCommandSocket():
    "Create a command socket."
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, 0)
    sock.bind((client_address, command_port))
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, SOCKET_BUFSIZE)
    sock.setblocking(0)
    return sock

commandSocket = ConnectCommandSocket()

## Send a ping command so that Tracker will begin streaming data
msg = struct.pack("I", NATNET_PING)
result = commandSocket.sendto(msg, (server_address, command_port))

while True:
    try:
        msg, address = commandSocket.recvfrom(MAX_PACKETSIZE + 4)
    except socket.error:
        pass
    else:
        print(msg, "\n")
steven.andrews
NaturalPoint Employee
NaturalPoint Employee
Posts: 720
Joined: Mon Jan 19, 2015 11:52 am

Re: Streaming data to Python via unicast and multicast

Post by steven.andrews »

Hello csims,

Thank you for all of the valuable information you provided and thank you for your patience as we have been looking into this behavior.

If it is at all possible, you will want to make sure you are using the latest versions of Motive and our NatNet SDK. Using the latest versions of Motive 1.9 and NatNet 2.9, we have been able to verify that the streaming is working as expected.

We did find a problem with the Multicast/Unicast setting. However, if you set Unicast and restart the application, things should work for you. Basically, when change multicast/unicast the application needs to be restarted in order for the change to take place.

Best regards,
Steven
--
Steven Andrews
OptiTrack | Customer Support Engineer
Post Reply