Frage

Ich bin ein bisschen neu in Java habe so noch nicht vollständig das Konzept der multithreading.I begriffen möchte eine PID-Regler-Klasse erstellen, die mir, dies zu tun erlaubt:

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();
}

Ich habe gearbeitet, wie der Standard-PID-argorithms zu berechnen, aber ich kann nicht herausfinden, wie die asynchrone Funktionalität bereitzustellen.

Kann mir jemand sagen, wie ich eine ähnliche API erreichen kann?

War es hilfreich?

Lösung

Sie implementiert bereits eine run() Methode für PIDController, so dass Sie auch die Runnable Schnittstelle implementieren sollten:

class PIDController implements Runnable {
    ....
}

Jetzt können Sie Ihre PID-Regler asynchronen beginnen, durch den Aufruf:

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

Für die Synchronisation (falls erforderlich), sollten Sie einen Blick auf die Sonne haben

Andere Tipps

Bei weitem der beste Mechanismus für Threads etwas Anbringen ist das Objekt zu trennen, die die Arbeit von dem Objekt tut, was der Thread ist. Die Runnable-Schnittstelle kann attraktiv sein, weil es Menschen passieren, das Objekt zu einem Thema Konstruktor oder Executor und laufen zu lassen. Wenn Sie jedoch Lifecycle-Management-Anforderungen für Ihr Objekt haben, die aus der Seite von „läuft bis zur Fertigstellung“ sind, wie Pause, dann werden Sie feststellen, es sinnvoller in den meisten Fällen das Thema in Ihrem Objekt zu verwalten, so dass Sie wissen, was Faden läuft (ja Sie eine Instanz Objekt Thread.currentThread () auf Eintrag festlegen zu laufen, aber ...).

Also, ich glaube, was Sie haben ist ein guter Anfang. Sie benötigen die Verwendung einiger Verriegelung hinzufügen, um sich selbst zu verwalten Pause zu helfen () und andere Fadenkontrolle.

    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() {
            ...
        }
    }

scroll top