/**
         * \brief Sends a goal to the ActionServer, and waits until the goal completes or a timeout is exceeded
         *
         * If the goal doesn't complete by the execute_timeout, then a preempt message is sent. This call
         * then waits up to the preempt_timeout for the goal to then finish.
         *
         * \param goal             The goal to be sent to the ActionServer
         * \param execute_timeout  Time to wait until a preempt is sent. 0 implies wait forever
         * \param preempt_timeout  Time to wait after a preempt is sent. 0 implies wait forever
         * \return The state of the goal when this call is completed
         */
        public SimpleClientGoalState sendGoalAndWait(AGoal goal, Duration execute_timeout, Duration preempt_timeout)
        {
            sendGoal(goal);

            // See if the goal finishes in time
            if (waitForResult(execute_timeout))
            {
                ROS.Debug("actionlib", "Goal finished within specified execute_timeout [%.2f]", execute_timeout.toSec());
                return(getState());
            }

            ROS.Debug("actionlib", "Goal didn't finish within specified execute_timeout [%.2f]", execute_timeout.toSec());

            // It didn't finish in time, so we need to preempt it
            cancelGoal();

            // Now wait again and see if it finishes
            if (waitForResult(preempt_timeout))
            {
                ROS.Debug("actionlib", "Preempt finished within specified preempt_timeout [%.2f]", preempt_timeout.toSec());
            }
            else
            {
                ROS.Debug("actionlib", "Preempt didn't finish specified preempt_timeout [%.2f]", preempt_timeout.toSec());
            }
            return(getState());
        }
        /**
         * \brief Sends a goal to the ActionServer, and also registers callbacks
         *
         * If a previous goal is already active when this is called. We simply forget
         * about that goal and start tracking the new goal. No cancel requests are made.
         * \param done_cb     Callback that gets called on transitions to Done
         * \param active_cb   Callback that gets called on transitions to Active
         * \param feedback_cb Callback that gets called whenever feedback for this goal is received
         */
        public void sendGoal(AGoal goal, SimpleDoneCallback done_cb = null, SimpleActiveCallback active_cb = null, SimpleFeedbackCallback feedback_cb = null)
        {
            // Reset the old GoalHandle, so that our callbacks won't get called anymore
            goalHandle.reset();

            // Store all the callbacks
            doneCallback     = done_cb;
            activeCallback   = active_cb;
            feedbackCallback = feedback_cb;

            goalState = new SimpleGoalState(SimpleGoalState.StateEnum.PENDING);

            // Send the goal to the ActionServer
            goalHandle = actionClient.sendGoal(goal, handleTransition, handleFeedback);
        }