Kivy graphics with ethernet data reception - python

My kivy code has to move a widget smoothly linearly from point A to point B and also receive UDP packet via ethernet cable. For now the widget moves smoothly from A to C (C between line AB)and then stops to receive data (may be 0.5 to 1 second) and then the widget moves again.
The movement is not smooth due to this. Any idea how to solve this issue?
I am using socket module from python for data reception.
I even tried thread programming. It did not help, same issue.
class DemoCreator(AnchorLayout):
ev_status = NumericProperty(None) # get ev status(UDP packet)
def receive_ev_status(self):
r = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
r.bind(('', 5555))
prev_data = 0
data, _ = r.recvfrom(1024)
if not data:
data = prev_data
return int.from_bytes(data, 'little')
def update_ev_status(self, dt):
self.ev_status = self.receive_ev_status()
class DemoApp(App):
def build(self):
hmi = DemoCreator()
hmi.map_box.host_car.start((450, 0)
Clock.schedule_interval(hmi.update_ev_status, 0.5)
Clock.schedule_interval(hmi.map_box.update_car, 1 / 60)
return hmi
if __name__ == '__main__':
DemoApp().run()
how to receive data using ports for a kivy application without disturbing its graphics ?

The problem is your use of Clock.schedule_interval() for your ethernet reception. The Clock.schedule family schedules methods to be run on the main thread, so your ethernet work is being done on the same (GUI) thread as your widget motion. That affects the GUI performance. Put your ethernet code in another thread by using something like threading.Thread(target=self.ethernet_recv).start(). The target method will need to do your looping to call your self.receive_ev_status() at 0.5 second intervals.
Have a look at this documentation

Related

Problems with programs not closing that were opened by python

I am trying to make a python code that takes the output of an Arduino and starts a Program when a button is pressed. When I press the button on the Arduino it starts the wanted program, but the moment I close the opened the Program it opens itself again and it does that a lot of times. Until I guess, there aren't any more "button High" actuations. Here is my code:
import time
import serial
import subprocess
chonk = serial.Serial('COM5', 9600, timeout=1)
while True:
dataUwU = chonk.readline()
print(dataUwU)
if b'1H' in dataUwU:
subprocess.call("C:\Program Files (x86)\Google\Chrome\Application\chrome.exe")
while b'1H' in dataUwU:
dataUwU = chonk.readline()
print(dataUwU)
if b'2H' in dataUwU:
subprocess.call(r"C:\Users\lastname\AppData\Local\Programs\Microsoft VS Code\Code.exe")
while b'2H' in dataUwU:
dataUwU = chonk.readline()
pass
In the Variable dataUwU saved is the State of the buttons. I dont't understand the weird behavior! Can anyone help? Thanks in advance!!!
You should care about debouncing the button input since most of mechanical buttons (or switches) suffer static noise when you push down or push up them. Even if the button state seem to switch between high and low clearly, the actual waveform show the bounce or fluctuations in a short period as shown below.
So, I guess the Arduino transmits "the button is pressed" packet multiple times even if you pressed the button one time, triggering the subprocess call opening the program multiple times. The second and the subsequent calls may wait until the firstly opened program closed.
If it's correct, your problem can be solved by removing or handling the bounce. To remove the bounce, a capacitor should be connected in parallel with the button to filter the high-frequency noise. If you don't want like hardware, you can modify Arduino sketch to ignore the bounce and figure out the true switch state transition. Please refer to the official debounce example.
Edit) I'm not sure it works, but try this python code instead of modifying the Arduino sketch. You can adjust the DEBOUNCE_DELAY. The shorter the delay, the faster the response, but more vulnerable to the bounce.
import time
import serial
import subprocess
chonk = serial.Serial('COM5', 9600, timeout=1)
t_last_changed = time.time()
last_state = None
button_state = None
DEBOUNCE_DELAY = 0.5
while True:
dataUwU = chonk.readline()
print(dataUwU)
if dataUwU != last_state:
t_last_changed = time.time()
if(time.time() - t_last_changed > DEBOUNCE_DELAY):
if dataUwU != button_state:
button_state = dataUwU
if b'1H' in dataUwU:
subprocess.call("C:\Program Files (x86)\Google\Chrome\Application\chrome.exe")
while b'1H' in dataUwU:
dataUwU = chonk.readline()
print(dataUwU)
if b'2H' in dataUwU:
subprocess.call(r"C:\Users\lastname\AppData\Local\Programs\Microsoft VS Code\Code.exe")
while b'2H' in dataUwU:
dataUwU = chonk.readline()
pass
last_state = dataUwU
Edit2) Even if the python code works, I recommend you to handle the bounce at Arduino because Arduino is better at handling timing-critical tasks than Python code running on your PC.

Controlling Stepper motors and Camera simultaneously

what is the best way to control a stepper motor and camera simultaneously?
Suppose the camera is placed on a linear stage (stepper motor) and I want to move the stage in 1 mm steps and capture a frame at the end of each step. Both devices (Camera and the stage) are connected to my computer (Ubuntu 18.04.3 LTS) via 2 different USB 2.0 ports.
My script for the camera looks something like:
def camera():
...
...
...
while(True):
cv2.imshow('live', frame)
ueye.is_ExitCamera(hCam2)
cv2.destroyAllWindows()
if __name__ == "__main__":
camera()
and outputs live broadcast from the camera.
For the motor something like:
i = 0
while i < 6: # Move 6 times
stepper.Move(0.5) # Moves forward by 0.5 mm
time.sleep(1) # Sleeps for a second
i += 1
time.sleep(2)
print("\nProcess End\n")
close() # closes port
and moves and sleeps as desired.
Both scripts run sucessfully when executed seperately. However, how do I combine these scripts so that I can take a picture at the end of each step? For the example adressed above for moving 6 times, I want to get 6 images at the end, captured at the end of each step. Should one use multithreading, multiprocessing?... Both devices are connected to my computer via 2 seperate USB 2.0 ports. I'm not a beginner in programming, but not an expert either so any suggestions will be kindly appreciated.
It there a reason that you can't call some function that captures an image on each step?
# import modules for camera and stepper control
def step_and_capture(steps=6):
images = []
for x in range(steps):
stepper.Move(0.5)
image = cam_capture_method() # returns a photo or it could write to somewhere
time.sleep(1)
# save the images to folder?
if __name__ == "__main__":
step_and_capture()

vtkRenderWindowInteractor stalling program

I've been working on a prototype application in Python for stereoscopic imaging of a 3D model using VTK, but I'm running into some issues on the interface end of things. The goal of the code below at the moment is to zoom in on both renderWindows when the middlemouse is pressed. However, upon calling the vtkRenderWindowInteractor.Start() function, my vtkRenderWindowInteractors are effectively stalling out the entire program as if they were being run in the same thread. Even more curious is that keyboard interrupts are not being thrown when I use CTRL-C (I'm working in UNIX shell) until I close the render windows manually using the 'x' button. If I just close the window manually without hitting CTRL-C, the program picks up directly after the Start() call (e.g. in the code below, the infinite while loop). I've provided a sequence of screen captures at the end of this post to visualize exactly what is happening in the case that my explanation is confusing.
I've tried multiple workarounds to remedy this but none so far have worked. Threading the renders into isolated threads made no difference even when I tried using ncurses for input, while forking them to a new process resulted in some OS issues that I'd rather not deal with. The most current interactor styles method (shown below) where I just use built-in VTK listeners works to a degree, allowing me to detect inputs when the windows are in focus and the interactors are active, but because of the lack of association between the camera and the MyInteractorStyle class, I can't really access the cameras without the inclusion a loop after the Start() call, which leads me right back to where I started.
Any thoughts? Am I just misunderstanding how VTK's render tools are supposed to be used?
from vtk import*
import os.path
#import thread
#import time
#import threading
#import curses
class MyInteractorStyle(vtk.vtkInteractorStyleTrackballCamera):
pos1 = [0, 0, 200]
foc1 = [0, 0, 0]
pos2 = [40, 0, 200]
foc2 = [0, 0, 0]
def __init__(self,parent=None):
self.AddObserver("MiddleButtonPressEvent", self.middleButtonPressEvent)
self.AddObserver("MiddleButtonReleaseEvent", self.middleButtonReleaseEvent)
def middleButtonPressEvent(self,obj,event):
print "Middle button pressed"
self.pos1[2] += 10
self.pos2[2] += 30
self.OnMiddleButtonDown()
return
def middleButtonReleaseEvent(self,obj,event):
print "Middle button released"
self.OnMiddleButtonUp()
return
def main():
# create two cameras
camera1 = vtkCamera()
camera1.SetPosition(0,0,200)
camera1.SetFocalPoint(0,0,0)
camera2 = vtkCamera()
camera2.SetPosition(40,0,200)
camera2.SetFocalPoint(0,0,0)
# create a rendering window and renderer
ren1 = vtkRenderer()
ren1.SetActiveCamera(camera1)
ren2 = vtkRenderer()
ren2.SetActiveCamera(camera2)
# create source
reader = vtkPolyDataReader()
path = "/home/compilezone/Documents/3DSlicer/SlicerScenes/LegoModel-6_25/Model_5_blood.vtk"
reader.SetFileName(path)
print(path)
reader.Update()
# create render window
renWin1 = vtkRenderWindow()
renWin1.AddRenderer(ren1)
renWin2 = vtkRenderWindow()
renWin2.AddRenderer(ren2)
# create a render window interactor
inputHandler = MyInteractorStyle()
iren1 = vtkRenderWindowInteractor()
iren1.SetRenderWindow(renWin1)
iren1.SetInteractorStyle(inputHandler)
iren2 = vtkRenderWindowInteractor()
iren2.SetRenderWindow(renWin2)
iren2.SetInteractorStyle(inputHandler)
# mapper
mapper = vtkPolyDataMapper()
mapper.SetInput(reader.GetOutput())
# actor
actor = vtkActor()
actor.SetMapper(mapper)
# assign actor to the renderer
ren1.AddActor(actor)
ren2.AddActor(actor)
# enable user interface interactor
iren1.Initialize()
iren2.Initialize()
renWin1.Render()
renWin2.Render()
iren1.Start()
iren2.Start()
print "Test"
while 1:
pos1 = iren1.GetInteractorStyle().pos1
foc1 = iren1.GetInteractorStyle().foc1
pos2 = iren2.GetInteractorStyle().pos2
foc2 = iren2.GetInteractorStyle().foc2
print
if __name__ == '__main__':
main()
Program running
KeyboardInterrupt (CTRL-C hit and echoed in terminal but nothing happens)
Render windows manually closed, KeyboardInterrupt thrown
Calling Start() on a RenderWindowInteractor starts the event loop necessary to execute render events, much as the event loop in a GUI. So what you're trying to do, starting two event loops, doesn't really make sense.
A conceptual workaround would be to not call Start on the RenderWindowInteractors but to write a small GUI with multiple toolkit-specific RenderWindowInteractors and use that GUI's event loop.
As an example, here's how this is done with GUI toolkit-specific code in tvtk's wxVtkRenderWindowInteractor class, which doesn't call start on the RenderWindowInteractor but instead uses the GUI's event loop to manage events:
def wxVTKRenderWindowInteractorConeExample():
"""Like it says, just a simple example
"""
# every wx app needs an app
app = wx.PySimpleApp()
# create the top-level frame, sizer and wxVTKRWI
frame = wx.Frame(None, -1, "wxVTKRenderWindowInteractor", size=(400,400))
widget = wxVTKRenderWindowInteractor(frame, -1)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(widget, 1, wx.EXPAND)
frame.SetSizer(sizer)
frame.Layout()
# It would be more correct (API-wise) to call widget.Initialize() and
# widget.Start() here, but Initialize() calls RenderWindow.Render().
# That Render() call will get through before we can setup the
# RenderWindow() to render via the wxWidgets-created context; this
# causes flashing on some platforms and downright breaks things on
# other platforms. Instead, we call widget.Enable(). This means
# that the RWI::Initialized ivar is not set, but in THIS SPECIFIC CASE,
# that doesn't matter.
widget.Enable(1)
widget.AddObserver("ExitEvent", lambda o,e,f=frame: f.Close())
ren = vtk.vtkRenderer()
widget.GetRenderWindow().AddRenderer(ren)
cone = vtk.vtkConeSource()
cone.SetResolution(8)
coneMapper = vtk.vtkPolyDataMapper()
coneMapper.SetInput(cone.GetOutput())
coneActor = vtk.vtkActor()
coneActor.SetMapper(coneMapper)
ren.AddActor(coneActor)
# show the window
frame.Show()
app.MainLoop()
(Note that this code is not altered and has some clear differences with what you are trying to do.)
Also, the reason that ctrl+C doesn't work is because the VTK event loop doesn't do anything with this event. Some GUIs do respect this event, including wxpython. But if you aren't using a GUI that respects this event (for example, Qt) you can manually tell the python interpreter to intercept this event and crash instead of forwarding the event to the GUI event loop:
import signal
signal.signal(signal.SIGINT, signal.SIG_DFL)
For anyone who happens to stumble along this with the same problem of being unable to manipulate the camera from the vtkInteractorStyle classes, check out the Dolly(), Pan(), Spin(), Rotate(), Zoom(), and UniformScale(). All of these should let you access the camera from your whichever child class of vtkInteractorStyle you're using. Good luck!
EDIT: Even better, just attach your camera to your class that inherits from vtkInteractorStyle as a property, e.g.:
style = MyInteractorStyleClass()
style.camera = myCam
This way you can access it from anywhere within your custom class! Pretty basic, but it flew right past me.

Opening a new GUI from existing one in PYQT freezes the GUI [duplicate]

i have a QMainWindow that starts a QThread and waits for data from the network. updates UI when it receive any data.
the problem is : it sometimes crash. and sometimes doesn't , all i do i start it and wait for data.
here is the thread class :
class ListenerThread(QtCore.QThread):
def __init__(self,host,port,window):
super(ListenerThread,self).__init__(window)
self.host = host
self.port = port
self.window = window
def run(self):
soc = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
soc.bind((self.host, self.port))
while True:
data, address = soc.recvfrom(9999)
print address
if data:
dataList = data.split("\\")
company = dataList[1]
projectName = dataList[2]
assets = dataList[3]
assetType = dataList[4]
assetName = dataList[5]
# parent here is the main window(the main thread) : updateCombo is a function that updates combo box inside the main window
self.parent().updateCombo(self.window.comboBoxCompany,company)
self.parent().updateCombo(self.window.dropDownProjects,projectName)
self.parent().select(assets,assetName)
why is this happening ?? put in mind that the main Window by itself works fine.
the function (updateCombo) is working fine also ( when you call it from it's class).
but main window keeps crashing when i send data ! any idea why ?
GUI widgets may be accessed only from main thread, meaning the thread that calls QApplication.exec(). Access to GUI widgets from any other thread – what you're doing with your calls to self.parent() – is undefined behaviour, in your case this means crashes.
You signals and slots to communicate between background threads and the GUI in a safe manner.
And please read the documentation about Qt's threading functionality, because the above is actually essential knowledge when dealing with multi-threaded GUI applications, not only in Qt, but in any other GUI framework, too.

Data Acquistion using Python

I'm working on a project using National Instruments boards to do data acquistion. I have functional C codes for doing the tasks, but would like to use Python, so the GUI programming is less painful. In my C-code, I use the API call setTimer, which raises a WM_TIMER event at regular intervals. Is there a similar, mechanism in a Tk loop? I tried using the following code.
def DAQ(self):
if self.do_DAQ:
result = self.myDAQ.getData()
currTime = time.time() - self.start_time
self.time_label.config(text="{:.1f} seconds".format(currTime))
self.volt_label.config(text="{:.4f} volts".format(result))
self.time_data[self.i] = currTime
self.volt_data[self.i] = result
self.i += 1
self.after(1962, self.DAQ)
The magic "1962" in the after() was determined by trial and error to give about a 2 second delay, but the time slices drift depending on what else is in the queue. Is there a way I can do this so my time slices are more accurate? Specifically, can I force Tk to do my DAQ event before other things in the queue?
Here's a sort of quickie example of what I'm talking about in my comment:
import Tkinter as tk
import threading
import random
import time
from Queue import Queue, Empty
root = tk.Tk()
time_label = tk.Label(root, text='<unknown> seconds')
volt_label = tk.Label(root, text='<unknown> volts')
time_label.pack()
volt_label.pack()
def DAQ(q):
while True:
q.put((time.time(), random.randrange(100)))
time.sleep(2)
def update_data(queue, root):
try:
timestamp, volts = queue.get_nowait()
except Empty:
pass
else:
time_label.config(text='{:.1f} seconds'.format(timestamp))
volt_label.config(text='{:.4f} volts'.format(volts))
root.after(100, update_data, queue, root)
data_queue = Queue()
t = threading.Thread(target=DAQ, args=(data_queue,))
t.daemon = True
t.start()
update_data(data_queue, root)
root.mainloop()
Obviously the above DAQ() function is just a stand-in for the real thing. The point is, as #ballsdotballs suggested in their answer, you can sample at whatever rate you want in your DAQ thread, add the values to a queue, and then update the GUI at a more appropriate rate.
I actually do NIDAQmx with Python using PyDAQmx. We take data at 20kHz (by setting the clock timer on the NI board, and streaming the data to a file in chunks of 2000 at 10hz).
I would highly recommend separating your GUI process from your data acquisition process if temporal precision is important.
If you are just wanting to log the data every 2 seconds, you could set your sample clock on your NIDAQ to something like 1000, buffer size 1000, and use an AutoRegisterEveryNSamplesEvent callback to write the last index of data for every other buffer (which should be every two seconds) to a file or pipe it to your GUI process. This will ensure that your processing queue for your GUI won't affect the precision that your data is sampled with.

Categories

Resources