def do_single_basic_pend_traj_opt(should_init):
    plant = PendulumPlant()
    context = plant.CreateDefaultContext()

    kNumTimeSamples = 15
    kMinimumTimeStep = 0.01
    kMaximumTimeStep = 0.2

    dircol = DirectCollocation(plant, context, kNumTimeSamples, kMinimumTimeStep, kMaximumTimeStep)

    dircol.AddEqualTimeIntervalsConstraints()

    kTorqueLimit = 3.0  # N*m.
    u = dircol.input()
    dircol.AddConstraintToAllKnotPoints(-kTorqueLimit <= u[0])
    dircol.AddConstraintToAllKnotPoints(u[0] <= kTorqueLimit)

    initial_state = PendulumState()
    initial_state.set_theta(0.0)
    initial_state.set_thetadot(0.0)
    dircol.AddBoundingBoxConstraint(initial_state.get_value(), initial_state.get_value(), dircol.initial_state())
    # dircol.AddLinearConstraint(dircol.initial_state() == initial_state.get_value())

    final_state = PendulumState()
    final_state.set_theta(math.pi)
    final_state.set_thetadot(0.0)
    dircol.AddBoundingBoxConstraint(final_state.get_value(), final_state.get_value(), dircol.final_state())
    # dircol.AddLinearConstraint(dircol.final_state() == final_state.get_value())

    R = 10  # Cost on input "effort".
    dircol.AddRunningCost(R*u[0]**2)

    if should_init:
        initial_x_trajectory = PiecewisePolynomial.FirstOrderHold([0., 4.], [initial_state.get_value(), final_state.get_value()])
        dircol.SetInitialTrajectory(PiecewisePolynomial(), initial_x_trajectory)

    def cb(decision_vars):
        global cb_counter
        cb_counter += 1
        if cb_counter % 10 != 1:
            return

        # Get the total cost
        all_costs = dircol.EvalBindings(dircol.GetAllCosts(), decision_vars)
        # :all_constraints = dircol.EvalBindings(dircol.GetAllConstraints(), decision_vars)

        # Get the total cost of the constraints.
        # Additionally, the number and extent of any constraint violations.
        violated_constraint_count = 0
        violated_constraint_cost  = 0
        constraint_cost           = 0
        for constraint in dircol.GetAllConstraints():
            val = dircol.EvalBinding(constraint, decision_vars)

            # TODO: switch to DoCheckSatisfied...
            nudge = 1e-1 # This much constraint violation is not considered bad...
            lb = constraint.evaluator().lower_bound()
            ub = constraint.evaluator().upper_bound()
            good_lb = np.all( np.less_equal(lb, val+nudge) )
            good_ub = np.all( np.greater_equal(ub, val-nudge) )
            if not good_lb or not good_ub:
                # print("val,lb,ub: ", val, lb, ub)
                violated_constraint_count += 1
                violated_constraint_cost += np.sum(val)
            constraint_cost += np.sum(val)
        print("total cost: {:.2f} | constraint {:.2f}, bad {}, {:.2f}".format(
            sum(all_costs), constraint_cost, violated_constraint_count, violated_constraint_cost))
#    dircol.AddVisualizationCallback(cb, np.array(dircol.decision_variables()))
    result = dircol.Solve()
    assert(result == SolutionResult.kSolutionFound)

    sol_costs = np.hstack([dircol.EvalBindingAtSolution(cost) for cost in dircol.GetAllCosts()])
    sol_constraints = np.hstack([dircol.EvalBindingAtSolution(constraint) for constraint in dircol.GetAllConstraints()])
Exemple #2
0
dircol.SetInitialTrajectory(PiecewisePolynomial(), initial_x_trajectory)

fig = plt.figure()
h, = plt.plot([], [], '.-')
plt.xlim((-2.5, 2.5))
plt.ylim((-3., 3.))


def draw_trajectory(t, x):
    h.set_xdata(x[0, :])
    h.set_ydata(x[1, :])
    fig.canvas.draw()
    if plt.get_backend() == u'MacOSX':
        plt.pause(1e-10)


dircol.AddStateTrajectoryCallback(draw_trajectory)

result = dircol.Solve()
assert(result == SolutionResult.kSolutionFound)

x_trajectory = dircol.ReconstructStateTrajectory()

x_knots = np.hstack([x_trajectory.value(t) for t in
                     np.linspace(x_trajectory.start_time(),
                                 x_trajectory.end_time(), 100)])
plt.plot(x_knots[0, :], x_knots[1, :])

plt.show()
Exemple #3
0
    def _solve_traj_opt(self, initial_state, constrain_final_state=True, duration_bounds=None, d=0.0, verbose=False):
        '''Finds a trajectory from an initial state, optionally to a final state.
        
        Args: 
            initial_state (tuple): the initial state
            final_state (tuple): the final state (default to None, final state unconstrained)
            duration (tuple): the min and max duration of the trajectory (default to None, 
                              no duration constraints)
            d (float): constant disturbance force
            verbose (bool): enables/disables verbose output

        Returns:
            pydrake.trajectories.PiecewisePolynomial: the planned trajectory
            float: the cost of the planned trajectory

        Raises:
            RuntimeError: raised if the optimization fails
        '''

        print("Initial state: {}\nFinal state: {}\nMin duration: {} s\nMax duration: {} s".format(
            initial_state, constrain_final_state, duration_bounds[0], duration_bounds[1]))

        traj_opt = DirectCollocation(self.plant, self.context, 
                                     self.opt_params['num_time_samples'],
                                     self.opt_params['minimum_timestep'],
                                     self.opt_params['maximum_timestep'])

        traj_opt.AddEqualTimeIntervalsConstraints()

        # Add bounds on the total duration of the trajectory
        if duration_bounds:
            traj_opt.AddDurationBounds(duration_bounds[0], duration_bounds[1])

        # TODO make input limits a paramter
        limits_low = [-15., -15.]
        limits_upp = [15., 15.]

        x = traj_opt.state()
        u = traj_opt.input()
        t = traj_opt.time()
        # TODO assuming disturbance is at the last index
        for i in range(len(u) - 1):
            traj_opt.AddConstraintToAllKnotPoints(limits_low[i] <= u[i])
            traj_opt.AddConstraintToAllKnotPoints(u[i] <= limits_upp[i])

        traj_opt.AddConstraintToAllKnotPoints(u[len(u) - 1] == d)

        for signed_dist_func in self.signed_dist_funcs:
            traj_opt.AddConstraintToAllKnotPoints(signed_dist_func(x) >= 0)

        traj_opt.AddRunningCost(traj_opt.timestep(0) * self.running_cost(x, u, t))

        traj_opt.AddFinalCost(self.final_cost(x, u, t))

        # Add initial and final state constraints
        traj_opt.AddBoundingBoxConstraint(initial_state, initial_state,
                                          traj_opt.initial_state())

        if self.final_state_constraint and constrain_final_state:
            traj_opt.AddConstraint(self.final_state_constraint(traj_opt.final_state()) == 0)

        # # TODO this is redundant with the final state equality constraint above
        # if final_state:
        #     traj_opt.AddBoundingBoxConstraint(final_state, final_state,
        #                                       traj_opt.final_state())

        #     initial_x_trajectory = PiecewisePolynomial.FirstOrderHold([0., 0.4 * 21],
        #                                                               np.column_stack((initial_state,
        #                                                                                final_state)))
        #     traj_opt.SetInitialTrajectory(PiecewisePolynomial(), initial_x_trajectory)
        # else:
        #     initial_x_trajectory = PiecewisePolynomial.FirstOrderHold([0., 0.4 * 21],
        #                                                               np.column_stack((initial_state,
        #                                                                                initial_state)))
        #     traj_opt.SetInitialTrajectory(PiecewisePolynomial(), initial_x_trajectory)

        initial_x_trajectory = PiecewisePolynomial.FirstOrderHold([0., 0.4 * 21],
                                                                  np.column_stack((initial_state,
                                                                                   initial_state)))
        traj_opt.SetInitialTrajectory(PiecewisePolynomial(), initial_x_trajectory)

        result = traj_opt.Solve()

        if result != SolutionResult.kSolutionFound:
            raise RuntimeError('Direct collocation failed from initial state {}!'.format(initial_state))

        state_samples = traj_opt.GetStateSamples()
        input_samples = traj_opt.GetInputSamples()
        time_samples = traj_opt.GetSampleTimes()

        # for debugging
        hs = [time_samples[i+1] - time_samples[i] for i in range(len(time_samples)) if i < len(time_samples) - 1]
        #print(hs)

        total_cost = 0.
        for k in range(state_samples.shape[1]):
            total_cost += (hs[0] * 
                           self.running_cost(state_samples[:, k], 
                                             input_samples[:, k], 
                                             time_samples[k]))
            if verbose:
                for i, phi in enumerate(self.signed_dist_funcs):
                    print("\tsigned dist {}: {}".format(i, signed_dist_func(state_samples[:, k])))

        if verbose:
            print("Total cost is {}".format(total_cost))

            u_traj = traj_opt.ReconstructInputTrajectory()
            times = np.linspace(u_traj.start_time(), u_traj.end_time(), 100)
            u_lookup = np.vectorize(lambda t: u_traj.value(t)[0])
            u_values = u_lookup(times)

            plt.figure()
            plt.plot(times, u_values)
            plt.xlabel('time (seconds)')
            plt.ylabel('force (Newtons)')

            plt.show()

        return traj_opt.ReconstructStateTrajectory(), total_cost