I have a program which runs a camera for a set number of exposures and a set length of exposures through a serial port. The program talks to a server which gives error values, if the error values are within an acceptable range, then the exposure starts and a countdown clock runs until the exposure ends. The following variables are used to make this happen.
T="Length of exposure in seconds"
N="Number of exposures"
then a while loop runs the program using the following
def countdown(n):
for i in range(int(n)):
c = int(n) - int(i)
print c ,'seconds left','\r',
time.sleep(1)
While x < T loop:
countdown(n)
I would like to run a thread which is constantly probing the error number from the server, and if the error number grows to large, it changes to the value of i to equal n.
def errortest():
test=struct.pack("B",10)
s.send(test)
data = s.recv(BUFFER_SIZE)
if ord(data) < (75) and ord(data) > 0:
print ord(data)
time.sleep(5)
else:
print ("error! Stopping exposure")
i=n
My problem is that the variables aren't being shared between the functions. I had some success with setting "i" and "n" as global variables, but this has caused other problems as well, depending on the order in which I invoke or write the different functions. I've also tried return i=n, but n is not shared. It is especially a problem as both threads are running concurrently and not sharing variables. This is why I cannot get queue to work because it pauses the for loop at each instance of q.get().
Is there a better way than using global variables to share variable values between functions running as concurrent threads?
You might want to try sharing your variables within a class. You'll find many tutorials if you google for them. If you want to distribute your tasks into different programs, xmlrpc is a simple possibility.
Related
I want to program that changes a rooms lights. The system runs on a controller that I can access via MQTT and REST. I have a way to change the intensity but it is very abrupt. Because I want the rest of the system to continue running while the change is happening (because I have Sensors running the rest of the lighting) I can't just use a loop to steadily increase the intensity. I looked into Timers but I can't get them to work properly for what I need. Is there a way to do that?
Here is my Problem with the loop:
client.message_callback_add(path("zones",Office,"devices",Sensor1_Presence,"data","presence"), on_message_Presence_callback)
client.message_callback_add(path("zones",Office,"devices",Sensor2_Presence,"data","presence"), on_message_colorchange_callback)
#client.message_callback_add(path("zones","#"), on_message_callback)
startTimer()
WeatherTimer()
client.connect(MQTT_HOST, port=MQTT_PORT)
client.loop_forever()
I want to be able to start and stop the function (preferably with a bool)
I have a change function that changes the specific parameters already:
def change_parameter(URL, parameter_name ,parameter_value):
r = requests.put(
f"https://{MQTT_HOST}/rest/v1/{URL}",
headers=litecom_headers(),
verify=False,
json={f"{parameter_name}": parameter_value}
)
return r.status_code
Is there a way to do what I want to do?
Thanks in advance!
I assume you have the python script controlling your lights running on your desktop pc?
If so, you most certainly have at least 2 cpu cores at your disposal and can make use of python's ProcessPoolExecutor to run your parameter changing function in parallel. Then you can just gradually change your parameter in small steps until you reach the desired value.
To get a smooth effect you then just have to experiment with the step-size and the sleep value between the steps until you are satisfied with the results.
Pseudo-ish implementation:
def change_param_smooth(URL, parameter_name, target_value, stepsize, duration):
current_value = 0 // get the current value from your device
while current_value < target_value:
current_value += step_size
# avoid overshooting
if current_value > target_value:
current_value = target_value
change_parameter(URL, parameter_name, current_value)
time.sleep(duration)
I have written some code to make the turtlebot turn around. The code is working. What I want to know is how fast the turtlebot is running and how I can control it. Forexample, how can I ensure that the turtlebot turns 5 degrees in one minute?
Last part of the question. After pressing Ctrl-C, the turtlebot stops but the script keeps running. Why? and how can I stop that?
this post does not really help.
went through this post .Does that mean that the while loop below runs 5 times a second regardless of the values I put in the for loops? Or does it mean ROS tries its best to make sure that the loop runs 5 times a second to the best of my machine's ability?
Thank you very much.
# 5 HZ
angle = 5
r = rospy.Rate(5);
while not rospy.is_shutdown():
# code to turn
for x in range(0,100):
rospy.loginfo("turn")
turn_cmd.angular.z = radians(angle)
new_angle = (angle + new_angle) % 360
self.cmd_vel.publish(turn_cmd)
r.sleep()
# code to pause
for x in range(0,100):
rospy.loginfo("stop")
turn_cmd.angular.z = radians(0)
self.cmd_vel.publish(turn_cmd)
r.sleep()
def shutdown(self):
# stop turtlebot
rospy.loginfo("Stop turning")
self.cmd_vel.publish(Twist())
rospy.sleep(1)
According to ROS Wiki, the rospy.Rate convenience class makes a best effort to maintain the loop running at the specified frequency by considering the execution time of the loop since the last successful r.sleep(). This means in your case: as long as the code execution time within the loop does not exceed 1/5 seconds, rospy.Rate will make sure the loop runs at 5Hz.
Regarding the script not stopping when pressing Ctrl-C:
KeyboardInterrupt will be handled differently than in normal Python scripts when using rospy.
rospy catches the KeyboardInterrupt signal to set the rospy.is_shutdown() flag to true. This flag is only checked at the end of each loop, therefore if pressing Ctrl-C during the for-loop executions, the script cannot be stopped because the flag is not checked immediately.
A manual way to signal a shutdown of the node is to use rospy.signal_shutdown(). For this, the disable_signals option needs to be set to true when initializing the ROS node (see Section 2.3 here). Note that you will additionally have to manually invoke the correct shutdown routines to ensure a proper cleanup.
def function():
while True:
...omission...(this function is repeated permanently)
i =0
while i < 4:
driver.execute_script("""window.open("URL")""")
driver.switch_to.window(driver.window_handles[-1])
time.sleep(1)
function()
time.sleep(1)
i += 1 #open new tab and run function.
it doesn't work because while true loop is repeated permanently. Is there any ways to run multiple functions together?
https://imgur.com/a/4SIVekS This picture shows what I want
According to your picture, what you want is to launch the function a set number of times (4?), and run those in parrallel.
On a single core, as is the normal behavior, straight up parallel processing is impossible. You need to access other cores and manage a decentralized processing. while is useless there. I'm worried the level of difficulty is over your current skills, but here we go.
The overall flow that you (probably, depends on the actual memory safety of your functions) need is:
- to create a thread pool with the set number of threads for the number of runs you want.
- indicate the function you need to run
- start them, making sure the start itself is non-blocking.
- ensure one functions's processing doesn't impact another's results. race conditions are a common problem.
- gather results, again, in a non-blocking way.
You can use several methods. I highly recommend you read up a lot on the following documentations.
Threading:
https://docs.python.org/3/library/threading.html
Multiprocessing:
https://docs.python.org/3/library/multiprocessing.html
I don't understand your question because I don't understand what your function is supposed to do.
while True:
will always create an infinite loop. "while" is a command that tells python to loop through the following block so long as the expression following it evaluates to True. True always evaluates to True.
It seems like you want to use a conditional, like you do in "while x < 4".
x < 4
...is an expression that evaluates to true when x is less than 4, and false if x is not less than 4. Everything below the line:
while x < 4:
will then run if x is less than 4, and when it's done running that code, it will go back and evaluate if x is less than 4 again, and if it is, run the code again. To include another while loop inside of that loop, that new loop also needs an expression to evaluate. If you want to evaluate the same expression, write it out:
while x < 4:
# do something
while x < 4:
#do more things
# do even more things
# change x at some point, or else you're in an infinite loop.
However, there's no reason to do that specifically, because you're already doing it. All of the code is only running when x < 4, so checking that condition again right there is redundant, and doing it in another loop doesn't make sense. If the inside loop is also incrementing x, then the outside loop won't loop and doesn't need to increment x.
Also, if you want a function to check a condition based on a variable outside the function, you'll want to pass things to that function.
I am working on a problem where i should collect data from running program numerous times. For example, every time the program finishes commands, it give certain value t, which is different every time run it. My task is to collect t from N runs of the program. t is going to be different every run. here is the program:
import random
th=0
t=0
tr=0
result=[]
for i in range(7):
i=random.randint(0,1)
result.append(i)
print(result)
a=0
b=len(result)-1
while th<50:
j=random.randint(a,b)
i=j-1
k=j+1
if k<b
k=0
if result[i]==result[k]:
if result[j]!=result[i]:
result[j]==result[i]
th=0
t+=1
else:
th+=1
t+=1
else:
th+=1
t+=1
tr= t-th
print(tr)
print (result)
In this program every run gives you new result. In this generated array there will be obviously every time different arrangement of 0 and 1 and therefore, different t. So resulting t, tr, will be ofcourse different.
I don't know wheter i should do it in new window, or there is a certain function that can do this. Also, if this question is to easy, and there is literature for it, please write what is the name of this kind of problem. thanks :)
btw, im working in python 3.6
See how to make one Python script launch another: you can write a Python script to run the other script and gather the output. You can receive the output as return value from a function call, and tally it just as you would from any function.
Note that your "running program" and your master script need to agree on the form of the information returned: know the data types you're receiving. If you're in doubt, start by having your master script print out what it receives, and the type of each returned value.
I am trying to run my code in parallel using the python "from multiprocessing import Process, Value" model.However, I am creating a shared variable and using it as flag, so if one process find the result it will set the flag value to 1 and exit.Other processes should exit when the flag value is changed but for some reason the flag value did not change for these processes. this is the code:
from multiprocessing import Process, Value
gflag= Value('i',0)#this is the global flag shared between process
gflag=0
while True:
if not piece:
break
list1= piece.splitlines()
p = Process(target=Dowork, args=(gflag,inValue,list1,var1,))
p.start()
if(gflag==1):
exit()
piece = f.read(10000)
def doWork(gflag,inputvalue,diclist,var1):
for p in diclist:
calResult= doSomeCal(p,var1)
if( calResult == inputvalue):
gflag=1
exit()
if(gflag==1):
print"exit now"
exit()
Question is how to stop all the threads when on of them find the result?
The main problem with your attempted solution is that, because you assign to gflag within doWork, it's a local variable, not a global. To fix that, you need to add global gflag at the start of the function.
But even if you fixed that, it wouldn't solve your problem. When you write gflag=1, that doesn't update the shared value stored in gflag, it just rebinds the name gflag to the local int 1. You want to use gflag.value. (Note that once you fix this, the previous problem goes away… but it's still often better to use the global declaration for human readers, even when the compiler doesn't need it.)
And finally, doWork doesn't actually check the flag until after it's finished doing all the work, so the flag doesn't help you to exit the child processes earlier. You probably want to put that if statement inside the for loop, so it checks the flag once per element, instead of only once at the end.