It is possible to deliver most software on time, but you need to be very clear about scope and unknowns and keep the units of work small.
The broad strokes of the design work need to be done before the estimate (i.e. gather requirements, identify constraints, decide on direction and tools).
If work is unknown or in large chunks, it needs to be broken up into smaller well-understood chunks before estimation.
When new ideas arise, they should usually be kept for future work.
When work is added, other work needs to be removed or the estimate revised.
If the work runs late, something should be removed from the scope to keep it on time, then done after delivery.
If work involves integration with other systems this is much harder unfortunately, but for some classes of software (much business software), it is not so hard to estimate.
The broad strokes of the design work need to be done before the estimate (i.e. gather requirements, identify constraints, decide on direction and tools).
If work is unknown or in large chunks, it needs to be broken up into smaller well-understood chunks before estimation.
When new ideas arise, they should usually be kept for future work.
When work is added, other work needs to be removed or the estimate revised.
If the work runs late, something should be removed from the scope to keep it on time, then done after delivery.
If work involves integration with other systems this is much harder unfortunately, but for some classes of software (much business software), it is not so hard to estimate.