|
|
|
![]() |
|
|||||||
|
||||||||
![]() |
| Thread Tools | Rate Thread | Display Modes |
|
#1
|
||||
|
||||
|
Quick Question about Threads
I'm currently writing some robot code, and I've been wondering about using multiple threads in java. As far as I know, it's the same as using threads in any other java application, but some people on my team think differently. Here's what I think should work. I'm not sure that starting the thread in the constructor is the best idea, and I'm also not sure that I'm using thread.sleep() the right way. I know that I could start the thread from somewhere else by using new Thread(Vision).start();, but what would work with java for FRC?
Code:
public class Vision implements Runnable{
public Vision(){
new Thread(this).start();
}
public void run() {
while(processImages){
//image stuff here
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
}
|
|
#2
|
||||
|
||||
|
Re: Quick Question about Threads
It would work. But I am very sceptical of you starting a thread in a constructor. I can't imagine a situation where that would be a good idea (in frc coding at least). But yes, the Thread class works just like Java SE.
|
|
#3
|
||||
|
||||
|
Re: Quick Question about Threads
As to Thread.sleep(), I would refer you here: http://stackoverflow.com/questions/3...h-thread-sleep
|
|
#4
|
||||
|
||||
|
Re: Quick Question about Threads
You're right, starting a thread in the constructor is wrong. It should be placed in a method named startVision instead of the constructor. Also, we're using thread.sleep instead of thread.yield because it seems to give us more consistent vision loop timings, but I'm not really sure why. It also keeps the cpu usage away from 100%. We know that the vision loop will slow down when other stuff starts up, but it's nice to be able to watch the cpu usage and see what functions use the most resources. What do you think the best way to free up the CPU?
|
|
#5
|
|||
|
|||
|
Re: Quick Question about Threads
Might be because of this?
Thread.sleep(100); Never used threading for FRC, but I have for game programming. In which my sleep time varies based off a few factors (Another words, it's not just a while loop with a constant sleep time). Not sure how to implement this in FRC, just throwing out the possibility. Also, you're sleeping for a tenth of a second. Try making the value 1000 (1 second) and see if the usage goes down. If neither of these work, you might want to use a debugger & pin point what in specific is maxing out the CPU. |
|
#6
|
||||
|
||||
|
Re: Quick Question about Threads
Sorry, my last post was a bit confusing. What I was trying to say was that using thread.yield() caused the cpu usage to go to 100% but didn't cause any lag. The disadvantage was that it was unpredictable with the vision loop. What we used instead was thread.sleep. This does work for us because waiting 100ms doesn't increase the cpu usage very much. 6-10 fps seems like a good target frame rate for our camera. I don't really understand how the thread.sleep can be improved without making a much more complicated method of threading. I am aware that the sleep function tends to be off because of the way that thread scheduling works, but the difference is so small, that for us it won't really make a difference. We're not waiting for something to happen, we're just trying to reduce CPU usage. I'm trying to keep it simple, and since we only have 3 threads right now including the main thread, and they interact in such a way that they don't need to be synchronized with each other, I don't see why I'd have to do anything differently.
|
|
#7
|
||||
|
||||
|
Re: Quick Question about Threads
Thread.yield() tells the CPU to pause the current thread and allow other threads to run. See : http://stackoverflow.com/questions/4...sleep0-in-java
Unless that is what you are going for, I'm thinking that yield() doesn't find any other threads to run, so it just runs right away, making the loop incredibly fast (100% usage). |
|
#8
|
||||
|
||||
|
Re: Quick Question about Threads
Also, if you are feeling lazy, the wpilibj has a class called Timer that has a static method delay(double seconds). It just uses Thread.sleep(), but converts the double correctly and catches the exception.
|
|
#9
|
||||
|
||||
|
Re: Quick Question about Threads
I don't know whether this works on the robot, but this is how we plan to implement it on our driver's station this year. We may add an interrupt timer that will re-process a new image if the old image hasn't been processed, but we also don't expect the driver's station laptop to bog down enough that it can't keep up. This method doesn't depend on a sleep() or a timer, it simply processes images as they chronologically come in (even if they're asynchronous due to network lag).
The big issue with doing threading like this comes when you go to fold the results back into whatever other robot logic you have. You MUST make sure your data is thread-safe (i.e. use synchronized blocks on critical path items OR make sure that only one single thread can access/modify a specific set of critical data). With gui's, it's easy: SwingUtilities.invokeLater() will update data on a GUI using the EventDispatchThread. For your own internal robot stuff though, it isn't quite as clear-cut. Code:
/**
* IUpdate<T> is just a type-safe interface that I commonly use
* for event-driven items that only need 1 input parameter.
*
public interface IUpdate<T>
{
public void update(T pObject);
}
*
*/
public abstract class ImageProcessor implements IUpdate<BufferedImage>
{
private final Executor mExecutor = Executors.newSingleThreadExecutor();
public ImageProcessor(IImageProvider pProvider)
{
pProvider.addListener(this);
}
@Override public void update(final BufferedImage pObject)
{
mExecutor.execute(new Runnable()
{
@Override public void run()
{
processImpl(pObject);
}
});
}
protected abstract void processImpl(BufferedImage pImage);
}
Last edited by JesseK : 14-12-2012 at 09:13. Reason: Abstract method is much more extendable than a private inner class |
|
#10
|
||||
|
||||
|
Re: Quick Question about Threads
My idea, which is my attempt to keep things simple, was to have a thread that would process the image, store the coordinates of the image in a variable, then wait 100ms. This would keep the processor happy. If we wanted, we could time the processing stuff then subtract that time from 100ms to make sure that we got exactly 10fps. Then, our PID loop for targeting would look to the most recently calculated image coordinate by using a method in the vision class which gets the variables with the coordinates. I realize that the PID loop may be sometimes getting bad information, for instance, it may grab the same coordinates twice before the cRIO can process another image. We used labview to do the same thing on the cRIO, and it worked fine. If my logic is flawed, I think I could just call a method which processes the image in the PID loop, which is threaded. What is the easiest way to get the image stuff working in a thread?
|
|
#11
|
||||
|
||||
|
What are thread used for and do you have any resources for using them?
|
|
#12
|
||||
|
||||
|
Re: Quick Question about Threads
Quote:
General information on Java threads can be found with Google. FRC-specific information can be found using the handy "search" bar up at the top of the page... |
|
#13
|
||||
|
||||
|
Re: Quick Question about Threads
Quote:
What happens if your image processor take 10ms to process (for a total loop time of 110ms), but the images still come in at 10Hz (every 100ms)? Quote:
However, there is no free lunch: dedicating more threads than you have CPU cores will still CPU cause scheduling conflicts. For example, if I dedicate 8 threads to heavy processing and expect my 9th main critical thread to main responsive (in a quad-core HT system), I'm really just fooling myself. The system has 7 available threads for heavy (100% cpu) processing. Last edited by JesseK : 14-12-2012 at 09:22. |
|
#14
|
||||
|
||||
|
Re: Quick Question about Threads
A much simpler explanation of threading is this:
Being able to do more than 1 thing at a time. It basically lets you do two (or more) things simultaneously, without any expectations of one of them being done before the other. Keep in mind there are a lot of concurrency problems that you need to deal with if you use multiple threads. (see synchronized blocks, atomic variables and volatile variables) |
|
#15
|
||||
|
||||
|
Re: Quick Question about Threads
Well, we chose 100ms because it is what is used in LabVIEW for the vision loop wait time. Also, when we use the AxisCamera.getInstance.getImage() method it will get the most recent image. Since the images come in faster than 100 ms, there's no way for the loop to grab the same image twice. I'm not sure that this is the best way. I'd like to know if there is a better way to do this.
|
![]() |
| Thread Tools | |
| Display Modes | Rate This Thread |
|
|