This is a very related resource: Algorithm for centering an object that is changing speed.
The PID controller is a viable choice. The two channels (tilt and pan) are independent and so are the two PID controllers you need to implement, which will each act on one single channel.
When I tried to track a static object, the PID controller worked fine resulting in a null steady-state error.
This is somehow expected as a moving object will add its own unknown dynamics to the game, making the controller's life harder.
- How to choose kP, kI, kD values during tuning.
The key here is to use a PI controller. As suggested in the related resource, start off with tuning a simple P controller, in order to get closer to centering the target in the image plane. You will certainly end up with a residual error that, in turn, you can compensate for by slowly increasing the integral gain I.
The P has to make most of the job. A simple P is not enough though. Imagine a situation where the object moves at a constant velocity and you've already got it in the center of the image. The error is 0 and so is the controller's effort $K_p \cdot 0 = 0$; hence, you don't move the camera. This tells us that the integral is strictly required since it can deliver nonnull effort for null input error.
The derivative part D serves as a prediction that would help us catch up with where the object will most likely be in the next few controller's time instants. Thereby, the derivative contribution can reduce overshoots and make the controller more reactive. However, predictions work in practice only for objects that move, well, predictably; otherwise, derivative can harm the system performance. For this reason, try your best without D, tuning up a PI.
- Whether the below code snippet is suitable for my application.
The snippet looks overall good, although it implements a quite simplistic PID. The only point I'd like to stress is that you ought to stick to a fixed controller's sample time $T_s$. Don't try to adjust for the elapsed time with
deltaTime. The latter variable needs to be a constant
deltaTime = Ts. To this end, you have to call the snippet with the said periodicity by means of an interrupt service routine or by relying on OS-specific threads, for example.
- Should I wait some time after calculating the PID output? Or, can I update the PID immediately?
The PID output needs to be applied to the system with the periodicity of $T_s$. As discussed right above, you should resort to interrupts or threads, which will guarantee some sort of robust timing. All modern languages offer threading through their libraries.
$T_s$ is usually in the range of milliseconds, but really depends on the system at hand.
- Should I control the speed of the PTZ camera?
Nope. You close the loop around the pixels error and this is sufficient.
Anyway, the output of the PID is typically a voltage to be applied to an electrical motor. In this context, setting the voltage amounts to controlling the velocity of the motor shafts (up to a certain extent), and thus of the camera's channels.
More generally, there are configurations where nested control loops are employed. See for example Inner current controller benefits.
A final note on the Z part of the PTZ camera. You may need to have different sets of PID gains for different zoom configurations.