For next year we are planning to use threads so the robot can multitask better. Do you think this is a good idea and if so how would you go about doing it thanks.
I know you have to create a thread and runnable (like the one below) but where do you put them?
Thread nameOfThread = new Thread();
Runnable trackingJob = new Runnable()
{
//Particle Analysis Report
public void run()
{
//Code here
}
};
The argument to the Thread constructor takes a Runnable. To start the Thread use the start() method, not run() (If you call run(), it won’t be threaded at all).
I usually write a separate class that implements Runnable, then creates and starts a thread in the constructor. Take this simple class for an example:
public class ThreadedHello implements Runnable{
public ThreadedHello(){
new Thread(this).start();
}
public void run(){
System.out.println("Hello World!");
}
}
Then, to use this class I would just do this in another class:
ThreadedHello hello = new ThreadedHello();
//if it were a real object I would do something else besides create it
Ok, that makes sense. Then would this (below) be how you would use threads with the simple robot template. Would you still need a while loop or once you start the thread it will keep running and call the Runnable. Thanks.
package edu.wpi.first.wpilibj.templates;
import edu.wpi.first.wpilibj.Joystick;
import edu.wpi.first.wpilibj.RobotDrive;
import edu.wpi.first.wpilibj.SimpleRobot;
public class RobotTemplate extends SimpleRobot
{
Joystick stickL = new Joystick(1);
Joystick stickR = new Joystick(2);
public void autonomous()
{
}
public void operatorControl()
{
Thread drive = new Thread(driveJob);
drive.start();
}
Runnable driveJob = new Runnable()
{
RobotDrive myDrive = new RobotDrive(1, 2, 3, 4);
public void run()
{
myDrive.tankDrive(-stickL.getAxis(Joystick.AxisType.kY), -stickR.getAxis(Joystick.AxisType.kY));
}
};
}
If you wanted to use it for something like driving the robot, it would probably be easiest to use the built-in Command classes, but if you have your heart set on using Thread or want to use it for something like socket communication (like I did with our robot), then you would need to have a while(true) loop inside your run method, otherwise it would only run once. If you would like an example of using the Command based model, I would be happy to post one, just let me know.
Does anyone know exactly where someone could find the threading guarantees we have with the WPILIB library? Can we set motors from separate threads? Can we call I/O functions(both networking and storage) concurrently? Are the constructors for the PWM-like classes free from contention? Etc.
Some of the newer programmers on my team want to look into multithreading next year and I am wondering whether we need to mutex the world in order for it to work well.
I haven’t seen it documented anywhere, but I have set motors within Commands, which is WPILib’s overly simplified (to a fault I think) system of threading, which I would assume uses the default Thread class. I can’t remember for sure whether I have controlled motors in a thread that I created myself, but I am pretty sure that there isn’t a problem with it.
I have definitely read files and sockets within a Thread and that works fine.
Ok so in each runnable just put while(true). Could you also put while(isTeleop())?
Runnable driveJob = new Runnable()
{
RobotDrive myDrive = new RobotDrive(1, 2, 3, 4);
public void run()
{
while(true)
{
myDrive.tankDrive(-stickL.getAxis(Joystick.AxisType.kY), -stickR.getAxis(Joystick.AxisType.kY));
}
}
};
If you are sending information from the laptop to the robot through udp, can you put a thread in and the robot won’t get caught somewhere. So you will still be able to drive and run conveyors and shoot the ball.
Watch out, that while loop has the potential to freeze the code because it never rests, you need to put some kind of Thread.sleep(…) in there.
Alternatively, you could try to figure out the Command System which is better for doing the kind of job you’ve written down (although for UDP stuff, you’ll have to use a thread).
Ok thanks. Does it matter how many milliseconds you put in for Thread.sleep(…). Could it be really small? Also would you mind posting an example of using the Command classes. Thanks.
Regarding UDP, I do not believe that it is supported on the cRIO in Java (as of last year at least). The classes exist for it, but when I tried to run my UDP code, it said that datagram sockets were not supported.
When the user’s code runs the Scheduler’s run() method, the scheduler iterates through a list of active commands and calls execute() on each one (sequentially, not parallel).
So there’s no issues with race conditions or anything complicated like that with the new command-based system, since there’s no threads. I thought commands were useful because we could easily make the robot perform actions by binding button presses to Commands. It also made it easy for our robot to sequentially fire balls during autonomous just by scheduling three of our “shoot ball” Commands to run using a CommandGroup.