Pyserial/Eye-tracker: Reading from serial port whilst displaying stimuli - python-2.7

I am using Pyserial (+Python 2.7) to read in eye-tracking coordinates taken from an eye-tracker (CRS Live-Track set as serial port). Using the code below I am able to successfully start the tracker, read/save a line of coordinates, stop the tracker, and close. My problem is I need to continuously read in the coordinates whilst carrying out other tasks such as stimuli display. As it stands, I can't do anything whilst I'm reading in data ('trial1 = ser.readline'). I have to wait until I've read in the data before I continue. Is there a way to read in the data from the serial port continuously whilst I am displaying stimuli/collecting responses etc.?
I need to turn the tracker on, collect the data for the duration of the trial, and then tracker off.
import serial, time
ser = serial.Serial(
port='COM3',
baudrate=9600,
parity=serial.PARITY_ODD,
stopbits=serial.STOPBITS_TWO,
bytesize=serial.SEVENBITS,
)
x = ser.is_open #check port is open
if x:
print "port is open"
print "port name is: %s" %(ser.name) #check which port
ser.flushInput()
ser.flushOutput()
running = True
while running:
ser.write('$Raw\r') #start eye-tracker
trial1 = ser.readline() #read a line
###i need to do stuff here###
ser.write('$Stop\r') #stop eye-tracker
running = False
ser.flushInput()
ser.flushOutput()
print trial1 #print coordinates output
ser.close()
Cheers,
Steve

ioHub by Sol Simpson provides asynchronous device monitoring from within PsychoPy. i.e it operates on an entirely separate process so you don't have to pause while monitoring the port in the main PsychoPy thread.
Serial port documentation in ioHub seems scarce but there is a demo here: https://github.com/psychopy/psychopy/blob/master/psychopy/demos/coder/iohub/serial/customparser.py

Another option would be to try threads. You could put your eye tracker in one thread and the rest of your code in another. There is a stack overflow answer about multithreading (not using psychopy and eye trackers) from 2010. If you scroll down you will see that someone links to a blog post about an updated approach that they think is easier.

Related

Live555MediaServer restarts the stream at every new connection. Why setting "reuseSource" to true is not working as expected?

Live555MediaServer can be used to stream video files as rtsp streams. I have 2 clients (vlc) that connect to the server, A and B. I want to see the exact video stream in both the clients. Here is the problem: I connect A and after 10 seconds I connect B. When B is connected the video that I see starts over from the beginning, while A keeps streaming as it was.
I would like the 2 concurrent streams to be synchronized.
The live555 doc says that setting reuseFirstSource to True should work. So I tried to set reuseSource to true at DynamicRTSSPServer:121 but it didn't work. When I connect to the server using client B the video restarts from the beginning.
Boolean const reuseSource = True;
I expect to see the 2 concurrent streams synchronized even if one starts with a delay with respect to the other one.
I finally found a workaround and why there was this 'bug'.
Quick answer: set if condition at line 67 to false, i.e.
if (smsExists && isFirstLookupInSession) {
becomes
if (false) {
Explaination: Every time a new session is starting, the isFirstLookupInSession variable is set to true and the session is removed and recreated.
I wrote to the support of live555 and Finlayson told me and I quote
“LIVE555 Media Server” code was always intended to work this way, and was intended to be a ‘stand-alone appliance’ that does not have its code modified (e.g., by changing the value of “reuseFirstSource”).
Thus the only solution for creating a RTSP server through Live555 is to create your own server starting from the testProgs examples.
The workaround proposed here could generate unwanted behaviors, but for a simple rtsp server with multiple streams it's fine.

Slow Serial Connection between Arduino and Python

I currently have a project where my goal is to graph (in real time) the air flow going through an air flow sensor. The sensor is connected via IIC to an Arduino Uno, which is then collects the data and sends it to my COM3 Serial line with a baudrate of 1,000,000. In python, I read, line by line, the Serial line, and then graph the data. My goal is to graph about 500 data points/second (500hz), but it seems that Python is reading in the data too slowly.
Here is a small 'test' I performed:
I blew on the air flow sensor. From the Serial Monitor on my Arduino program, I immediately see the readings spike. However, from Python's console output (which is just reading the serial line and printing out the contents), the spike from my blowing is significantly delayed. The longer the program runs, the more backed up Python gets with keeping up with the Serial line.
From the Arduino side:
Serial.println((double)average, 4);
//Serial.print(" , ");
// Serial.println((double)Flow, 4);
delay(2);
}
And on the Python side:
print("PRESS 's' TO BEGIN RECORDING DATA!")
while not pressedStart:
if keyboard.is_pressed('s'):
print("Timer and Program Started!")
startTime = hour.time()
pressedStart = True
while pressedStart: #Program begins reading Serial Line when 's' is pressed.
while flowData.inWaiting()==0:
pass
dataArray = flowData.readline().split(",")
currentAverage = float(dataArray[0])
averageArray.append(currentAverage)
print(currentAverage) #this line is as far as my question goes. Why does Python print out this number
#more slowly than Arduino sends it out????
Python is a scripting language. It runs through an interpreter and therefore runs very slowly. Although and Arduino micro-controller is very under-powered, it runs faster than your python because python is that much slower. Unless you are willing to have less frequent data points by increasing the Arduino delay, I don't think this can be solved. Good luck still!

Socket is not connected Pepper

I use pythonsdk and naoqi for programming my pepper robot. i created a session and call the main by it is follows:
try
session = qi.Session()
session.connect("tcp://#.#.#.#:9559")
except RuntimeError:
print ("Cannot connect to robot ")
main(session)
each run of my program may take about 2 hourse. Actually it is a toutrial based interaction which is a loop of two phase: robot speech and playing a video clip on pepper's tablet, then a new topic and new video clip and so on.
but after a while i got these errors:
RuntimeError: Session not connected.
RuntimeError: Socket is not connected
so what these errors mean? and how can i overcome them? Thanks in advance
You should make sure your session remains alive, by using it from the scope it was created:
session = qi.Session()
session.connect("tcp://#.#.#.#:9559")
main(session)

Simple libtorrent Python client

I tried creating a simple libtorrent python client (for magnet uri), and I failed, the program never continues past the "downloading metadata".
If you may help me write a simple client it would be amazing.
P.S. When I choose a save path, is the save path the folder which I want my data to be saved in? or the path for the data itself.
(I used a code someone posted here)
import libtorrent as lt
import time
ses = lt.session()
ses.listen_on(6881, 6891)
params = {
'save_path': '/home/downloads/',
'storage_mode': lt.storage_mode_t(2),
'paused': False,
'auto_managed': True,
'duplicate_is_error': True}
link = "magnet:?xt=urn:btih:4MR6HU7SIHXAXQQFXFJTNLTYSREDR5EI&tr=http://tracker.vodo.net:6970/announce"
handle = lt.add_magnet_uri(ses, link, params)
ses.start_dht()
print 'downloading metadata...'
while (not handle.has_metadata()):
time.sleep(1)
print 'got metadata, starting torrent download...'
while (handle.status().state != lt.torrent_status.seeding):
s = handle.status()
state_str = ['queued', 'checking', 'downloading metadata', \
'downloading', 'finished', 'seeding', 'allocating']
print '%.2f%% complete (down: %.1f kb/s up: %.1f kB/s peers: %d) %s %.3' % \
(s.progress * 100, s.download_rate / 1000, s.upload_rate / 1000, \
s.num_peers, state_str[s.state], s.total_download/1000000)
time.sleep(5)
What happens it is that the first while loop becomes infinite because the state does not change.
You have to add a s = handle.status (); for having the metadata the status changes and the loop stops. Alternatively add the first while inside the other while so that the same will happen.
Yes, the save path you specify is the one that the torrents will be downloaded to.
As for the metadata downloading part, I would add the following extensions first:
ses.add_extension(lt.create_metadata_plugin)
ses.add_extension(lt.create_ut_metadata_plugin)
Second, I would add a DHT bootstrap node:
ses.add_dht_router("router.bittorrent.com", 6881)
Finally, I would begin debugging the application by seeing if my network interface is binding or if any other errors come up (my experience with BitTorrent download problems, in general, is that they are network related). To get an idea of what's happening I would use libtorrent-rasterbar's alert system:
ses.set_alert_mask(lt.alert.category_t.all_categories)
And make a thread (with the following code) to collect the alerts and display them:
while True:
ses.wait_for_alert(500)
alert = lt_session.pop_alert()
if not alert:
continue
print "[%s] %s" % (type(alert), alert.__str__())
Even with all this working correctly, make sure that torrent you are trying to download actually has peers. Even if there are a few peers, none may be configured correctly or support metadata exchange (exchanging metadata is not a standard BitTorrent feature). Try to load a torrent file (which doesn't require downloading metadata) and see if you can download successfully (to rule out some network issues).

Android usb host input bulktransfer fails to read randomly when data available

The following code is inside a thread and reads input data coming over usb. Approximately every 80 readings it misses one of the packets coming from an stm32 board. The board is programmed to send data packets to the android tablet every one second.
// Non Working Code
while(running){
int resp = bulktransfer(mInEp,mBuf,mBuf.lenght,1000);
if(resp>0){
dispatchMessage(mBuf);
}else if(resp<0)
showsBufferEmptyMessage();
}
I was looking the Missile Launcher example in android an other libraries on the internet and they put a delay of 50ms between each poll. Doing this it solves the missing package problem.
//Working code
while(running){
int resp = bulktransfer(mInEp,mBuf,mBuf.lenght,1000);
if(resp>0){
dispatchMessage(mBuf);
}else if(resp<0)
showsBufferEmptyMessage();
try{
Thread.sleep(50);
}catch(Exception e){}
}
Does anyone knows the reason why the delay works. Most of the libraries on github has this delay an as I mention before the google example too.
I am putting down my results regarding this problem. After all seems that the UsbConnection.bulkTransfer(...) method has some bug when called continuously. The solution was to use the asynchronous API, UsbRequest class. Using this method I could read from the input endpoint without delay and no data was lost during the whole stress test. So the direction to take is asynchronous UsbRequest instead of synchronously bulktransfer.