Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/388.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Java中实现多线程PID控制器?_Java_Multithreading_Asynchronous_Pid - Fatal编程技术网

如何在Java中实现多线程PID控制器?

如何在Java中实现多线程PID控制器?,java,multithreading,asynchronous,pid,Java,Multithreading,Asynchronous,Pid,我对Java有点陌生,所以还没有完全掌握多线程的概念。我想创建一个PIDController类,它允许我这样做: ControllerMethods methods = new ControllerMethods() { public long getError(long setpoint) {

我对Java有点陌生,所以还没有完全掌握多线程的概念。我想创建一个PIDController类,它允许我这样做:

ControllerMethods methods = new ControllerMethods()
                            {
                                public long getError(long setpoint)
                                {
                                    //get an input
                                }
                                public void setOutput(long value)
                                {
                                    //do something
                                }
                                public void isComplete(long setpoint)
                                {
                                    return getError() == 0;
                                }
                            };

PIDController motorPID = new PIDController(setpoint, kp, ki, kd, methods);

motorPID.run();
//runs the PID controller to completion (methods.isComplete() == true)

motorPID.run(false);
//starts the PID controller in a separate thread, allowing
//continual monitoring in the current thread

while(motorPID.isRunning())
{
    //do something else
    if(condition1)
        motorPID.pause();
        //pause the PID controller, preventing the integral from increasing
    else if(condition2)
        motorPID.stop();
}
我已经解决了如何计算标准PID参数,但我无法解决如何提供异步功能


有谁能告诉我如何实现类似的API吗?

您已经为
PIDController
实现了
run()
方法,因此您还应该实现
Runnable
接口:

class PIDController implements Runnable {
    ....
}
现在,您可以通过调用以下命令异步启动PID控制器:

pidControllerThread = new Thread( pidController );
pidControllerThread.start();

对于同步(如果需要),您应该看看sun。

您已经为
PIDController
实现了
run()
方法,因此您还应该实现
Runnable
接口:

class PIDController implements Runnable {
    ....
}
现在,您可以通过调用以下命令异步启动PID控制器:

pidControllerThread = new Thread( pidController );
pidControllerThread.start();

对于同步(如果需要的话),您应该看看sun。

到目前为止,将线程附加到任何对象的最佳机制是将执行工作的对象与作为线程的对象分开。Runnable接口很吸引人,因为它允许人们将对象传递给线程构造函数或执行器,然后运行它。但是,如果对象的生命周期管理要求超出了“从运行到完成”的范围,例如暂停,那么在大多数情况下,您会发现管理对象内的线程更合适,这样您就知道哪个线程正在运行(是的,您可以将实例对象设置为Thread.currentThread()在进入时运行,但

所以,我认为你有一个好的开始。您需要添加一些锁定来帮助自己管理pause()和其他线程控制

public class PIDController { private final Object myLock = new Object(); private final ControllerMethods ctrl; private volatile Thread thread; private volatile Runner runner; private int pidInterval = 700; private final double setPoint, kp, ki, kd; public PIDController( double setPoint, double kp, double ki, double kd, ControllerMethods inst ) { this.ctrl = inst; this.setPoint = setPoint; this.kp = kp; this.ki = ki; this.kd = kd; } public void pause() { synchronized( myLock ) { if( runner.paused ) { throw new IllegalOperationException(this+": already paused"); } runner.paused = true; } } public void resume() { synchronized( myLock ) { if( !runner.paused ) { throw new IllegalOperationException(this+": already resumed"); } runner.paused = false; } } public bool isRunning() { return running; } public void start() { if( thread != null ) { throw new IllegalOperationException( this+": already running"); } myThread = new Thread( runner = new Runner() ); myThread.start(); } public void stop() { if( runner == null ) { throw new IllegalOperationException( this+": PID is not running"); } runner.running = false; if( runner.paused ) resume(); runner = null; } // It is important, anytime that you implement a stoppable Runnable, that // you include the "running" flag as a member of an innner instance class like // this so that when you ask this instance to stop, you can immediately restart // another instance and not have the two threads observing the same "running" flag private class Runner implements Runnable { volatile bool running = false, bool paused; public void run() { running = true; while( running ) { // do this at the top of the loop so that a wake from // pause will check running, before recomputing. reComputePID(); // Use the double check idiom to if( paused ) { synchronized( myLock ) { while( paused ) { myLock.wait(); } } } Thread.sleep( pidInterval ); } } } public void reComputePID() { ... } } 公共类PID控制器{ 私有最终对象myLock=新对象(); 私人最终控制人方法ctrl; 私有易失性线程; 私人跑者; 私有时间间隔=700; 专用最终双设定点,kp,ki,kd; 公共PID控制器(双设定点、双kp、双ki、双kd、控制器方法仪表){ this.ctrl=inst; 此设定点=设定点; this.kp=kp; this.ki=ki; 这个.kd=kd; } 公共空间暂停(){ 已同步(myLock){ 如果(runner.paused){ 抛出新的非法操作异常(此+“:已暂停”); } runner.paused=true; } } 公众简历(){ 已同步(myLock){ 如果(!runner.paused){ 抛出新的非法操作异常(此+“:已恢复”); } runner.paused=false; } } 公共广播正在运行(){ 返回运行; } 公开作废开始(){ if(线程!=null){ 抛出新的非法操作异常(此+“:已在运行”); } myThread=新线程(runner=新runner()); myThread.start(); } 公共停车场(){ if(runner==null){ 抛出新的非法操作异常(此+“:PID未运行”); } runner.running=false; 如果(runner.paused) 恢复(); runner=null; } //重要的是,无论何时实现可停止的Runnable //您将“running”标志作为Inner实例类的成员,如 //这样,当您请求此实例停止时,可以立即重新启动 //另一个实例,并且两个线程没有观察到相同的“running”标志 私有类运行器实现可运行{ volatile bool running=false,bool暂停; 公开募捐{ 运行=真; (跑步时){ //在循环的顶部执行此操作,以便从 //暂停将在重新计算前检查正在运行。 重新计算epid(); //使用双重检查习惯用法 如果(暂停){ 已同步(myLock){ while(暂停){ myLock.wait(); } } } 睡眠时间间隔; } } } public void重新计算(){ ... } }
到目前为止,将线程附加到任何对象的最佳机制是将执行工作的对象与作为线程的对象分开。Runnable接口很吸引人,因为它允许人们将对象传递给线程构造函数或执行器,然后运行它。但是,如果对象的生命周期管理要求超出了“从运行到完成”的范围,例如暂停,那么在大多数情况下,您会发现管理对象内的线程更合适,这样您就知道哪个线程正在运行(是的,您可以将实例对象设置为Thread.currentThread()在进入时运行,但

所以,我认为你有一个好的开始。您需要添加一些锁定来帮助自己管理pause()和其他线程控制

public class PIDController { private final Object myLock = new Object(); private final ControllerMethods ctrl; private volatile Thread thread; private volatile Runner runner; private int pidInterval = 700; private final double setPoint, kp, ki, kd; public PIDController( double setPoint, double kp, double ki, double kd, ControllerMethods inst ) { this.ctrl = inst; this.setPoint = setPoint; this.kp = kp; this.ki = ki; this.kd = kd; } public void pause() { synchronized( myLock ) { if( runner.paused ) { throw new IllegalOperationException(this+": already paused"); } runner.paused = true; } } public void resume() { synchronized( myLock ) { if( !runner.paused ) { throw new IllegalOperationException(this+": already resumed"); } runner.paused = false; } } public bool isRunning() { return running; } public void start() { if( thread != null ) { throw new IllegalOperationException( this+": already running"); } myThread = new Thread( runner = new Runner() ); myThread.start(); } public void stop() { if( runner == null ) { throw new IllegalOperationException( this+": PID is not running"); } runner.running = false; if( runner.paused ) resume(); runner = null; } // It is important, anytime that you implement a stoppable Runnable, that // you include the "running" flag as a member of an innner instance class like // this so that when you ask this instance to stop, you can immediately restart // another instance and not have the two threads observing the same "running" flag private class Runner implements Runnable { volatile bool running = false, bool paused; public void run() { running = true; while( running ) { // do this at the top of the loop so that a wake from // pause will check running, before recomputing. reComputePID(); // Use the double check idiom to if( paused ) { synchronized( myLock ) { while( paused ) { myLock.wait(); } } } Thread.sleep( pidInterval ); } } } public void reComputePID() { ... } } 公共类PID控制器{ 私有最终对象myLock=新对象(); 私人最终控制人方法ctrl; 私有易失性线程; 私人跑者; 私有时间间隔=700; 专用最终双设定点,kp,ki,kd; 公共PID控制器(双设定点、双kp、双ki、双kd、控制器方法仪表){ this.ctrl=inst; 此设定点=s