예제 #1
0
    def state_contraints(self, robot, U):

        constraintVar = c.MX(
            2 * (robot.nx - 1) * self.N,
            self.T)  #skipping orientation. 2* to include min and max
        U = c.reshape(U, robot.nu * self.N, self.T)
        X = c.MX(robot.nx * self.N, self.T + 1)
        X[:, 0] = np.reshape(self.X0, (robot.nx * self.N, ))

        for i in range(self.T):
            for n in range(self.N):
                X[robot.nx * n:robot.nx * (n + 1), i + 1] = robot.kinematics(
                    X[robot.nx * n:robot.nx * (n + 1), i], U[robot.nu * n, i],
                    U[robot.nu * n + 1, i], U[robot.nu * n + 2, i])
                constraintVar[2 * (robot.nx - 1) * n:2 * (robot.nx - 1) *
                              (n + 1), i] = c.blockcat(
                                  [[
                                      self.Xmax - X[robot.nx * n:robot.nx *
                                                    (n + 1) - 1, i + 1]
                                  ],
                                   [
                                       X[robot.nx * n:robot.nx *
                                         (n + 1) - 1, i + 1] - self.Xmin
                                   ]])

        constraintVar = c.reshape(constraintVar, 1,
                                  2 * (robot.nx - 1) * self.N * self.T)

        return constraintVar
예제 #2
0
    def formulateNLP(self, walker):
        Xk = ca.MX([-0.3, 0.7, 0.0, -0.5, -0.6, 0., 0., 0., 0., 0.])
        Xk = ca.reshape(Xk, 10, 1)
        self.g += [Xk]
        self.lbg += [-np.pi / 2] * 10
        self.ubg += [np.pi / 2] * 10

        for k in range(walker.N):
            if k == walker.N - 1:
                Xk = ca.MX([-0.6, -0.5, 0.0, 0.7, -0.3, 0., 0., 0., 0., 0.])
                Xk = ca.reshape(Xk, 10, 1)
                self.g += [Xk]
                self.lbg += [-np.pi / 2] * 10
                self.ubg += [np.pi / 2] * 10

            # New NLP variable for the control
            Uk = ca.MX.sym('U_' + str(k), 4, 1)
            # Uk = ca.MX([0.])
            self.w += [Uk]
            self.lbw += [-walker.tau_max] * 4
            self.ubw += [walker.tau_max] * 4
            self.w0 += [0.] * 4

            # Integrate till the end of the interval
            Fk = walker.F(x0=Xk, u=Uk)
            Xk = Fk['xf']
            self.J = self.J + Fk['j']
예제 #3
0
    def exitEquation(self, tree):
        logger.debug('exitEquation')

        if isinstance(tree.left, list):
            src_left = ca.vertcat(*[self.get_mx(c) for c in tree.left])
        else:
            src_left = self.get_mx(tree.left)

        if isinstance(tree.right, list):
            src_right = ca.vertcat(*[self.get_mx(c) for c in tree.right])
        else:
            src_right = self.get_mx(tree.right)

        src_left = ca.MX(src_left)
        src_right = ca.MX(src_right)

        # According to the Modelica spec,
        # "It is possible to omit left hand side component references and/or truncate the left hand side list in order to discard outputs from a function call."
        if isinstance(tree.right, ast.Expression) and tree.right.operator in self.root.classes:
            if src_left.size1() < src_right.size1():
                src_right = src_right[0:src_left.size1()]
        if isinstance(tree.left, ast.Expression) and tree.left.operator in self.root.classes:
            if src_left.size1() > src_right.size1():
                src_left = src_left[0:src_right.size1()]

        # If dimensions between the lhs and rhs do not match, but the dimensions of lhs
        # and transposed rhs do match, transpose the rhs.
        if src_left.shape != src_right.shape and src_left.shape == src_right.shape[::-1]:
            src_right = ca.transpose(src_right)

        self.src[tree] = src_left - src_right
예제 #4
0
    def __set_cost_function(self, costFunc, mean_ref_s, P_s):
        """ Define stage cost and terminal cost
        """

        mean_s = ca.MX.sym('mean', self.__Ny)
        covar_x_s = ca.MX.sym('covar_x', self.__Ny, self.__Ny)
        covar_u_s = ca.MX.sym('covar_u', self.__Nu, self.__Nu)
        u_s = ca.MX.sym('u', self.__Nu)
        delta_u_s = ca.MX.sym('delta_u', self.__Nu)
        Q = ca.MX(self.__Q)
        R = ca.MX(self.__R)
        S = ca.MX(self.__S)

        if costFunc is 'quad':
            self.__l_func = ca.Function(
                'l', [mean_s, covar_x_s, u_s, covar_u_s, delta_u_s], [
                    self.__cost_l(mean_s, mean_ref_s, covar_x_s, u_s,
                                  covar_u_s, delta_u_s, Q, R, S)
                ])
            self.__lf_func = ca.Function(
                'lf', [mean_s, covar_x_s, P_s],
                [self.__cost_lf(mean_s, mean_ref_s, covar_x_s, P_s)])
        elif costFunc is 'sat':
            self.__l_func = ca.Function(
                'l', [mean_s, covar_x_s, u_s, covar_u_s, delta_u_s], [
                    self.__cost_saturation_l(mean_s, mean_ref_s, covar_x_s,
                                             u_s, covar_u_s, delta_u_s, Q, R,
                                             S)
                ])
            self.__lf_func = ca.Function('lf', [mean_s, covar_x_s, P_s], [
                self.__cost_saturation_lf(mean_s, mean_ref_s, covar_x_s, P_s)
            ])
        else:
            raise NameError('No cost function called: ' + costFunc)
예제 #5
0
    def test_concatenations(self):
        y = np.linspace(0, 1, 10)[:, np.newaxis]
        a = pybamm.Vector(y)
        b = pybamm.Scalar(16)
        c = pybamm.Scalar(3)
        conc = pybamm.NumpyConcatenation(a, b, c)
        self.assert_casadi_equal(conc.to_casadi(),
                                 casadi.MX(conc.evaluate()),
                                 evalf=True)

        # Domain concatenation
        mesh = get_mesh_for_testing()
        a_dom = ["negative electrode"]
        b_dom = ["separator"]
        a = 2 * pybamm.Vector(np.ones_like(mesh[a_dom[0]].nodes), domain=a_dom)
        b = pybamm.Vector(np.ones_like(mesh[b_dom[0]].nodes), domain=b_dom)
        conc = pybamm.DomainConcatenation([b, a], mesh)
        self.assert_casadi_equal(conc.to_casadi(),
                                 casadi.MX(conc.evaluate()),
                                 evalf=True)

        # 2d
        disc = get_1p1d_discretisation_for_testing()
        a = pybamm.Variable("a", domain=a_dom)
        b = pybamm.Variable("b", domain=b_dom)
        conc = pybamm.Concatenation(a, b)
        disc.set_variable_slices([conc])
        expr = disc.process_symbol(conc)
        y = casadi.SX.sym("y", expr.size)
        x = expr.to_casadi(None, y)
        f = casadi.Function("f", [x], [x])
        y_eval = np.linspace(0, 1, expr.size)
        self.assert_casadi_equal(f(y_eval), casadi.SX(expr.evaluate(y=y_eval)))
예제 #6
0
    def move(self, u, t, delta_t, is_pred=False, prev_x=None, prev_v=None):
        norm = np.linalg.norm
        if prev_x is None:
            prev_x = self.x_log[-1]
        if prev_v is None:
            prev_v = self.v_log[-1]

        if is_pred:
            norm = casadi.norm_2
            prev_x = casadi.MX(prev_x)
            if self.mm_order == 2:
                prev_v = casadi.MX(prev_v)

        if self.mm_order == 1:
            x_new = prev_x + u * delta_t
            v_new = u
        elif self.mm_order == 2:
            x_new = prev_x + prev_v * delta_t + u * (delta_t**2) / 2
            v_new = prev_v + u * delta_t
            # if norm(v_new) > self.vmax:
            #     v_new = v_new/norm(v_new)*self.vmax
            # assert(norm(v_new) != 0)
            # NEW
            v_new = v_new / norm(v_new) * self.vmax
        else:
            return NotImplemented

        # if is_pred:
        #     return x_new
        # else:
        return x_new, v_new
예제 #7
0
 def test_special_functions(self):
     a = pybamm.Array(np.array([1, 2, 3, 4, 5]))
     self.assert_casadi_equal(pybamm.max(a).to_casadi(),
                              casadi.MX(5),
                              evalf=True)
     self.assert_casadi_equal(pybamm.min(a).to_casadi(),
                              casadi.MX(1),
                              evalf=True)
     b = pybamm.Array(np.array([-2]))
     c = pybamm.Array(np.array([3]))
     self.assert_casadi_equal(pybamm.Function(np.abs, b).to_casadi(),
                              casadi.MX(2),
                              evalf=True)
     self.assert_casadi_equal(pybamm.Function(np.abs, c).to_casadi(),
                              casadi.MX(3),
                              evalf=True)
     for np_fun in [
             np.sqrt,
             np.tanh,
             np.cosh,
             np.sinh,
             np.exp,
             np.log,
             np.sign,
             np.sin,
             np.cos,
             np.arccosh,
             np.arcsinh,
     ]:
         self.assert_casadi_equal(pybamm.Function(np_fun, c).to_casadi(),
                                  casadi.MX(np_fun(3)),
                                  evalf=True)
예제 #8
0
    def get_derivative(self, s):

        # Case 1: s is a constant, e.g. MX(5)
        if ca.MX(s).is_constant():
            return 0

        # Case 2: s is a symbol, e.g. MX(x)
        elif s.is_symbolic():
            if s.name() not in self.derivative:
                if len(self.for_loops
                       ) > 0 and s in self.for_loops[-1].indexed_symbols:
                    # Create a new indexed symbol, referencing to the for loop index inside the vector derivative symbol.
                    for_loop_symbol = self.for_loops[-1].indexed_symbols[s]
                    s_without_index = self.get_mx(
                        ast.ComponentRef(name=for_loop_symbol.tree.name))
                    der_s_without_index = self.get_derivative(s_without_index)
                    if ca.MX(der_s_without_index).is_symbolic():
                        return self.get_indexed_symbol(
                            ast.ComponentRef(
                                name=der_s_without_index.name(),
                                indices=for_loop_symbol.tree.indices),
                            der_s_without_index)
                    else:
                        return 0
                else:
                    der_s = _new_mx("der({})".format(s.name()), s.size())
                    self.derivative[s.name()] = der_s
                    self.nodes[self.current_class][der_s.name()] = der_s
                    return der_s
            else:
                return self.derivative[s.name()]

        # Case 3: s is an already indexed symbol, e.g. MX(x[1])
        elif s.is_op(ca.OP_GETNONZEROS) and s.dep().is_symbolic():
            slice_info = s.info()['slice']
            dep = s.dep()
            if dep.name() not in self.derivative:
                der_dep = _new_mx("der({})".format(dep.name()), dep.size())
                self.derivative[dep.name()] = der_dep
                return der_dep[
                    slice_info['start']:slice_info['stop']:slice_info['step']]
            else:
                return self.derivative[dep.name(
                )][slice_info['start']:slice_info['stop']:slice_info['step']]

        # Case 4: s is an expression that requires differentiation, e.g. MX(x2 * x2)
        # Need to do this sort of expansion: der(x1 * x2) = der(x1) * x2 + x1 * der(x2)
        else:
            # Differentiate expression using CasADi
            orig_deps = ca.symvar(s)
            deps = ca.vertcat(*orig_deps)
            J = ca.Function('J', [deps], [ca.jacobian(s, deps)])
            J_sparsity = J.sparsity_out(0)
            der_deps = [
                self.get_derivative(dep)
                if J_sparsity.has_nz(0, j) else ca.DM.zeros(dep.size())
                for j, dep in enumerate(orig_deps)
            ]
            return ca.mtimes(J(deps), ca.vertcat(*der_deps))
    def buildDynamicalSystem(self):
        # q1 is first link q2 is second link
        q1 = ca.MX.sym('q1')
        dq1 = ca.MX.sym('dq1')
        q2 = ca.MX.sym('q2')
        dq2 = ca.MX.sym('dq2')
        u = ca.MX.sym('u')

        theta = ca.MX.sym("theta", 7, 1)

        if self.trainMotor:
            Rm = ca.MX.sym("Rm")
            km = ca.MX.sym("km")
            params = ca.vertcat(ca.MX.sym("params", 7, 1), Rm, km)
        else:
            Rm = self.Rm
            km = self.km
            params = theta

        states = ca.vertcat(q1, q2, dq1, dq2)
        controls = u  # km * (u - km * dq1) / Rm;

        if self.hackOn:
            # convert actions which are given as torques to voltage to be consistent with the controller inputs of Lukas
            u = u * Rm / km

        controls_torque = km * (u - km * dq1) / Rm

        # build matrix for mass matrix
        phi_1_1 = ca.MX(2, 7)
        phi_1_1[0, 0] = ca.MX.ones(1)
        phi_1_1[0, 1] = ca.sin(q2) * ca.sin(q2)
        phi_1_1[1, 2] = ca.cos(q2)
        phi_1_2 = ca.MX(2, 7)
        phi_1_2[0, 2] = -ca.cos(q2)
        phi_1_2[1, 3] = ca.MX.ones(1)
        mass_matrix = ca.horzcat(ca.mtimes(phi_1_1, params),
                                 ca.mtimes(phi_1_2, params))

        phi_2 = ca.MX(2, 7)
        phi_2[0, 1] = ca.sin(2 * q2) * dq1 * dq2
        phi_2[0, 2] = ca.sin(q2) * dq2 * dq2
        phi_2[0, 5] = dq1
        phi_2[1, 1] = -1 / 2 * ca.sin(2 * q2) * dq1 * dq1
        phi_2[1, 4] = self.g * ca.sin(q2)
        phi_2[1, 6] = dq2

        forces = ca.mtimes(phi_2, params)

        actions = ca.vertcat(controls_torque, ca.MX.zeros(1))

        b = actions - forces
        states_dd = ca.solve(mass_matrix, b)

        states_d = ca.vertcat(dq1, dq2, states_dd[0], states_dd[1])

        return states, states_d, controls, params
예제 #10
0
    def variable_metadata_function(self):
        in_var = ca.veccat(*self._symbols(self.parameters))
        out = []
        is_affine = True
        zero, one = ca.MX(0), ca.MX(
            1)  # Recycle these common nodes as much as possible.
        for variable_list in [
                self.states, self.alg_states, self.inputs, self.parameters,
                self.constants
        ]:
            attribute_lists = [[] for i in range(len(ast.Symbol.ATTRIBUTES))]
            for variable in variable_list:
                for attribute_list_index, attribute in enumerate(
                        ast.Symbol.ATTRIBUTES):
                    value = ca.MX(getattr(variable, attribute))
                    if value.is_zero():
                        value = zero
                    elif value.is_one():
                        value = one
                    value = value if value.numel() != 1 else ca.repmat(
                        value, *variable.symbol.size())
                    attribute_lists[attribute_list_index].append(value)
            expr = ca.horzcat(*[
                ca.veccat(*attribute_list)
                for attribute_list in attribute_lists
            ])
            if len(self.parameters) > 0 and isinstance(expr, ca.MX):
                f = ca.Function('f', [in_var], [expr])
                contains_if_else = ca.OP_IF_ELSE_ZERO in [
                    f.instruction_id(k) for k in range(f.n_instructions())
                ]
                zero_hessian = ca.jacobian(ca.jacobian(expr, in_var),
                                           in_var).is_zero()
                if contains_if_else or not zero_hessian:
                    is_affine = False
            out.append(expr)
        if len(self.parameters) > 0 and is_affine:
            # Rebuild variable metadata as a single affine expression, if all
            # subexpressions are affine.
            in_var_ = ca.MX.sym('in_var', in_var.shape)
            out_ = []
            for o in out:
                Af = ca.Function('Af', [in_var], [ca.jacobian(o, in_var)])
                bf = ca.Function('bf', [in_var], [o])

                A = Af(0)
                A = ca.sparsify(A)

                b = bf(0)
                b = ca.sparsify(b)

                o_ = ca.reshape(ca.mtimes(A, in_var_), o.shape) + b
                out_.append(o_)
            out = out_
            in_var = in_var_
        return ca.Function('variable_metadata', [in_var], out)
예제 #11
0
    def w_dynamics(self):
        f_thrust = self.u * self.quad.max_thrust

        y_f = cs.MX(self.quad.y_f)
        x_f = cs.MX(self.quad.x_f)
        c_f = cs.MX(self.quad.z_l_tau)
        return cs.vertcat(
            (cs.mtimes(f_thrust.T, y_f) + (self.quad.J[1] - self.quad.J[2]) * self.r[1] * self.r[2]) / self.quad.J[0],
            (-cs.mtimes(f_thrust.T, x_f) + (self.quad.J[2] - self.quad.J[0]) * self.r[2] * self.r[0]) / self.quad.J[1],
            (cs.mtimes(f_thrust.T, c_f) + (self.quad.J[0] - self.quad.J[1]) * self.r[0] * self.r[1]) / self.quad.J[2])
예제 #12
0
    def __setCosts__(self):
        Q = ca.diag(ca.MX([1, 1, 1]))
        R = ca.diag(ca.MX([0.1, 0.1]))
        cost = 0
        for k in range(self.N):
            q, dq = self.states[k], self.dstates[k]
            u = self.actions[k]
            cost += dq.T @ Q @ dq + u.T @ R @ u

        self.opti.minimize(cost)
예제 #13
0
 def _substitute_delay_arguments(self, delay_arguments, symbols, values):
     exprs = ca.substitute(
         [ca.MX(argument.expr) for argument in delay_arguments], symbols,
         values)
     durations = ca.substitute(
         [ca.MX(argument.duration) for argument in delay_arguments],
         symbols, values)
     return [
         DelayArgument(expr, duration)
         for expr, duration in zip(exprs, durations)
     ]
예제 #14
0
    def test_convert_differentiated_function(self):
        a = pybamm.Scalar(0)
        b = pybamm.Scalar(1)

        def myfunction(x, y):
            return x + y**3

        f = pybamm.Function(myfunction, a, b).diff(a)
        self.assert_casadi_equal(f.to_casadi(), casadi.MX(1), evalf=True)
        f = pybamm.Function(myfunction, a, b).diff(b)
        self.assert_casadi_equal(f.to_casadi(), casadi.MX(3), evalf=True)
예제 #15
0
    def __init__(self, start_angles, start_angular_vel, start_pos):
        # set our parameters of optimization
        self.opti = ca.Opti()
        self.terrain_factor = 0.1
        self.N = 40
        self.T = 0.3
        self.step_max = 0.5
        self.tauMax = 20
        self.pi = np.pi
        self.length = ca.MX([0.5, 0.5, 0.5, 0.5, 0.5])
        self.mass = ca.MX([0.25, 0.25, 0.25, 0.25, 0.25])
        self.inertia = self.mass * (self.length**2) / 12
        self.gravity = 9.81
        self.h = self.T / self.N
        self.goal = [start_angles, start_angular_vel]
        self.ini_goal = self.goal[0].to_DM()
        self.fin_goal = ca.DM([
            self.ini_goal[4], self.ini_goal[3], self.ini_goal[2],
            self.ini_goal[1], self.ini_goal[0]
        ])
        self.p0 = ca.MX(start_pos)
        self.comh = self.length[0] * 0.5
        #set our optimization variables
        self.x = []
        self.xdot = []
        self.u = []
        self.left = []
        self.right = []

        for i in range(self.N):
            self.x.append(self.opti.variable(5))
            self.xdot.append(self.opti.variable(5))
            self.u.append(self.opti.variable(4))
            self.left.append(self.opti.variable(2))
            self.right.append(self.opti.variable(2))

        self.pos = []
        self.com = []
        self.ddq = []
        self.dpos = []

        for n in range(self.N):
            p, dp, ddp, c, dc, ddc = self.getKinematics(
                self.x[n], self.xdot[n])
            self.pos.append(p)
            self.dpos.append(dp)
            self.com.append(c)
            ddq = self.getDynamics(self.x[n], self.xdot[n], self.u[n], p, ddp,
                                   c, ddc)
            self.ddq.append(ddq)

            if n == self.N - 1:
                self.x_impact, self.xdot_impact = self.impactMap(
                    self.x[n], self.xdot[n], p, dp, c, dc)
예제 #16
0
    def bounds(self):
        # Call parent class first for default values.
        bounds = super().bounds()

        # Parameter values
        parameters = self.parameters(0)
        parameter_values = [
            parameters.get(param.name(), param)
            for param in self.__mx['parameters']
        ]

        # Load additional bounds from model
        for v in itertools.chain(self.__pymoca_model.states,
                                 self.__pymoca_model.alg_states,
                                 self.__pymoca_model.inputs):
            sym_name = v.symbol.name()

            try:
                (m, M) = bounds[sym_name]
            except KeyError:
                if self.__python_types.get(sym_name, float) == bool:
                    (m, M) = (0, 1)
                else:
                    (m, M) = (-np.inf, np.inf)

            m_ = ca.MX(v.min)
            if not m_.is_constant():
                [m_] = substitute_in_external([m_], self.__mx['parameters'],
                                              parameter_values)
                if not m_.is_constant():
                    raise Exception(
                        'Could not resolve lower bound for variable {}'.format(
                            sym_name))
            m_ = float(m_)

            M_ = ca.MX(v.max)
            if not M_.is_constant():
                [M_] = substitute_in_external([M_], self.__mx['parameters'],
                                              parameter_values)
                if not M_.is_constant():
                    raise Exception(
                        'Could not resolve upper bound for variable {}'.format(
                            sym_name))
            M_ = float(M_)

            # We take the intersection of all provided bounds
            m = max(m, m_)
            M = min(M, M_)

            bounds[sym_name] = (m, M)

        return bounds
예제 #17
0
    def variable_metadata_function(self):
        in_var = ca.veccat(*self._symbols(self.parameters))
        out = []
        is_affine = True
        zero, one = ca.MX(0), ca.MX(1) # Recycle these common nodes as much as possible.
        for variable_list in [self.states, self.alg_states, self.inputs, self.parameters, self.constants]:
            attribute_lists = [[] for i in range(len(CASADI_ATTRIBUTES))]
            for variable in variable_list:
                for attribute_list_index, attribute in enumerate(CASADI_ATTRIBUTES):
                    value = ca.MX(getattr(variable, attribute))
                    if value.is_zero():
                        value = zero
                    elif value.is_one():
                        value = one
                    value = value if value.numel() != 1 else ca.repmat(value, *variable.symbol.size())
                    attribute_lists[attribute_list_index].append(value)
            expr = ca.horzcat(*[ca.veccat(*attribute_list) for attribute_list in attribute_lists])
            if len(self.parameters) > 0 and isinstance(expr, ca.MX):
                f = ca.Function('f', [in_var], [expr])
                # NOTE: This is not a complete list of operations that can be
                # handled in an affine expression. That said, it should
                # capture the most common ways variable attributes are
                # expressed as a function of parameters.
                allowed_ops = {ca.OP_INPUT, ca.OP_OUTPUT, ca.OP_CONST,
                               ca.OP_SUB, ca.OP_ADD, ca.OP_SUB, ca.OP_MUL, ca.OP_DIV, ca.OP_NEG}
                f_ops = {f.instruction_id(k) for k in range(f.n_instructions())}
                contains_unallowed_ops = not f_ops.issubset(allowed_ops)
                zero_hessian = ca.jacobian(ca.jacobian(expr, in_var), in_var).is_zero()
                if contains_unallowed_ops or not zero_hessian:
                    is_affine = False
            out.append(expr)
        if len(self.parameters) > 0 and is_affine:
            # Rebuild variable metadata as a single affine expression, if all
            # subexpressions are affine.
            in_var_ = ca.MX.sym('in_var', in_var.shape)
            out_ = []
            for o in out:
                Af = ca.Function('Af', [in_var], [ca.jacobian(o, in_var)])
                bf = ca.Function('bf', [in_var], [o])

                A = Af(0)
                A = ca.sparsify(A)

                b = bf(0)
                b = ca.sparsify(b)

                o_ = ca.reshape(ca.mtimes(A, in_var_), o.shape) + b
                out_.append(o_)
            out = out_
            in_var = in_var_

        return self._expand_mx_func(ca.Function('variable_metadata', [in_var], out))
예제 #18
0
    def test_simplify_all(self):
        # Create model, cache it, and load the cache
        compiler_options = \
            {'expand_vectors': True,
             'replace_constant_values': True,
             'replace_constant_expressions': True,
             'replace_parameter_values': True,
             'replace_parameter_expressions': True,
             'eliminate_constant_assignments': True,
             'detect_aliases': True,
             'eliminable_variable_expression': r'_\w+',
             'reduce_affine_expression': True}

        casadi_model = transfer_model(TEST_DIR, 'Simplify', compiler_options)

        ref_model = Model()

        p3 = ca.MX.sym('p3')
        x = ca.MX.sym('x')
        der_x = ca.MX.sym('der(x)')
        y = ca.MX.sym('y')

        ref_model.states = list(map(Variable, [x]))
        ref_model.states[0].min = 1
        ref_model.states[0].max = 2
        ref_model.states[0].nominal = 10
        ref_model.der_states = list(map(Variable, [der_x]))
        ref_model.alg_states = list(map(Variable, [y]))
        ref_model.inputs = list(map(Variable, []))
        ref_model.outputs = list(map(Variable, []))
        ref_model.constants = list(map(Variable, []))
        constant_values = []
        for _cst, v in zip(ref_model.constants, constant_values):
            _cst.value = v
        ref_model.parameters = list(map(Variable, [p3]))
        parameter_values = [np.nan]
        for par, v in zip(ref_model.parameters, parameter_values):
            par.value = v

        A = ca.MX(2, 3)
        A[0, 0] = -1.0
        A[0, 1] = 1.0
        A[1, 0] = -1.1
        A[1, 2] = 1.0
        b = ca.MX(2, 1)
        b[0] = -6 - 3 * p3
        b[1] = -7
        x = ca.vertcat(x, der_x, y)
        ref_model.equations = [ca.mtimes(A, x) + b]

        # Compare
        self.assert_model_equivalent_numeric(casadi_model, ref_model)
예제 #19
0
def validate(X_test, Y_test, X, Y, invK, hyper, meanFunc, alpha=None):
    """ Validate GP model with new test data
    """
    N, Ny = Y_test.shape
    Nx = np.size(X, 1)
    z_s = ca.MX.sym('z', Nx)

    gp_func = ca.Function(
        'gp', [z_s],
        gp(invK,
           ca.MX(X),
           ca.MX(Y),
           ca.MX(hyper),
           z_s,
           meanFunc=meanFunc,
           alpha=alpha))
    loss = 0
    NLP = 0

    for i in range(N):
        mean, var = gp_func(X_test[i, :])
        loss += (Y_test[i, :] - mean)**2
        NLP += 0.5 * np.log(2 * np.pi *
                            (var)) + ((Y_test[i, :] - mean)**2) / (2 * var)
        print(NLP)
        print(var)
    loss = loss / N
    SMSE = loss / np.std(Y_test, 0)
    MNLP = NLP / N

    print('\n________________________________________')
    print('# Validation of GP model ')
    print('----------------------------------------')
    print('* Num training samples: ' + str(np.size(Y, 0)))
    print('* Num test samples: ' + str(N))
    print('----------------------------------------')
    print('* Mean squared error: ')
    for i in range(Ny):
        print('\t- State %d: %f' % (i + 1, loss[i]))
    print('----------------------------------------')
    print('* Standardized mean squared error:')
    for i in range(Ny):
        print('\t* State %d: %f' % (i + 1, SMSE[i]))
    print('----------------------------------------\n')
    print('* Mean Negative log Probability:')
    for i in range(Ny):
        print('\t* State %d: %f' % (i + 1, MNLP[i]))
    print('----------------------------------------\n')
    return SMSE, MNLP
예제 #20
0
def interpolate(ts, xs, t, equidistant, mode=0):
    if interp1d is not None:
        if mode == 0:
            mode_str = 'linear'
        elif mode == 1:
            mode_str = 'floor'
        else:
            mode_str = 'ceil'
        return interp1d(ts, xs, t, mode_str, equidistant)
    else:
        if mode == 1:
            xs = xs[:-1]  # block-forward
        else:
            xs = xs[1:]  # block-backward
        t = ca.MX(t)
        if t.size1() > 1:
            t_ = ca.MX.sym('t')
            xs_ = ca.MX.sym('xs', xs.size1())
            f = ca.Function('interpolant', [t_, xs_], [
                ca.mtimes(ca.transpose((t_ >= ts[:-1]) * (t_ < ts[1:])), xs_)
            ])
            f = f.map(t.size1(), 'serial')
            return ca.transpose(f(ca.transpose(t), ca.repmat(xs, 1,
                                                             t.size1())))
        else:
            return ca.mtimes(ca.transpose((t >= ts[:-1]) * (t < ts[1:])), xs)
예제 #21
0
    def getBounds(self, walker):
        c = []
        f = 30
        for i in range(walker.N):
            q = walker.x[i]
            dq = walker.xdot[i]
            u = walker.u[i]
            c.extend([
                walker.opti.bounded(ca.MX([-walker.pi / 2] * 5), q,
                                    ca.MX([walker.pi / 2] * 5)),
                # walker.opti.bounded(ca.MX([-f*walker.pi]*5),dq,ca.MX([f*walker.pi]*5)),
                walker.opti.bounded(ca.MX([-walker.tauMax] * 4), u,
                                    ca.MX([walker.tauMax] * 4)),
            ])

        return c
예제 #22
0
 def test_special_functions(self):
     a = pybamm.Array(np.array([1, 2, 3, 4, 5]))
     self.assert_casadi_equal(pybamm.max(a).to_casadi(),
                              casadi.MX(5),
                              evalf=True)
     self.assert_casadi_equal(pybamm.min(a).to_casadi(),
                              casadi.MX(1),
                              evalf=True)
     b = pybamm.Array(np.array([-2]))
     c = pybamm.Array(np.array([3]))
     self.assert_casadi_equal(pybamm.Function(np.abs, b).to_casadi(),
                              casadi.MX(2),
                              evalf=True)
     self.assert_casadi_equal(pybamm.Function(np.abs, c).to_casadi(),
                              casadi.MX(3),
                              evalf=True)
예제 #23
0
    def exitForEquation(self, tree):
        logger.debug('exitForEquation')

        f = self.for_loops.pop()
        if len(f.values) > 0:
            indexed_symbols = list(f.indexed_symbols.keys())
            args = [f.index_variable] + indexed_symbols
            expr = ca.vcat([ca.vec(self.get_mx(e)) for e in tree.equations])
            free_vars = ca.symvar(expr)

            arg_names = [arg.name() for arg in args]
            free_vars = [e for e in free_vars if e.name() not in arg_names]
            all_args = args + free_vars
            F = ca.Function('loop_body', all_args, [expr])

            indexed_symbols_full = []
            for k in indexed_symbols:
                s = f.indexed_symbols[k]
                orig_symbol = self.nodes[self.current_class][s.tree.name]
                indexed_symbol = orig_symbol[s.indices]
                if s.transpose:
                    indexed_symbol = ca.transpose(indexed_symbol)
                indexed_symbols_full.append(indexed_symbol)

            Fmap = F.map("map", self.map_mode, len(f.values),
                         list(range(len(args), len(all_args))), [])
            res = Fmap.call([f.values] + indexed_symbols_full + free_vars)

            self.src[tree] = res[0].T
        else:
            self.src[tree] = ca.MX()
예제 #24
0
    def linearized_quad_dynamics(self):
        """
        Jacobian J matrix of the linearized dynamics specified in the function quad_dynamics. J[i, j] corresponds to
        the partial derivative of f_i(x) wrt x(j).

        :return: a CasADi symbolic function that calculates the 13 x 13 Jacobian matrix of the linearized simplified
        quadrotor dynamics
        """

        jac = cs.MX(self.state_dim, self.state_dim)

        # Position derivatives
        jac[0:3, 7:10] = cs.diag(cs.MX.ones(3))

        # Angle derivatives
        jac[3:7, 3:7] = skew_symmetric(self.r) / 2
        jac[3, 10:] = 1 / 2 * cs.horzcat(-self.q[1], -self.q[2], -self.q[3])
        jac[4, 10:] = 1 / 2 * cs.horzcat(self.q[0], -self.q[3], self.q[2])
        jac[5, 10:] = 1 / 2 * cs.horzcat(self.q[3], self.q[0], -self.q[1])
        jac[6, 10:] = 1 / 2 * cs.horzcat(-self.q[2], self.q[1], self.q[0])

        # Velocity derivatives
        a_u = (self.u[0] + self.u[1] + self.u[2] + self.u[3]) * self.quad.max_thrust / self.quad.mass
        jac[7, 3:7] = 2 * cs.horzcat(a_u * self.q[2], a_u * self.q[3], a_u * self.q[0], a_u * self.q[1])
        jac[8, 3:7] = 2 * cs.horzcat(-a_u * self.q[1], -a_u * self.q[0], a_u * self.q[3], a_u * self.q[2])
        jac[9, 3:7] = 2 * cs.horzcat(0, -2 * a_u * self.q[1], -2 * a_u * self.q[1], 0)

        # Rate derivatives
        jac[10, 10:] = (self.quad.J[1] - self.quad.J[2]) / self.quad.J[0] * cs.horzcat(0, self.r[2], self.r[1])
        jac[11, 10:] = (self.quad.J[2] - self.quad.J[0]) / self.quad.J[1] * cs.horzcat(self.r[2], 0, self.r[0])
        jac[12, 10:] = (self.quad.J[0] - self.quad.J[1]) / self.quad.J[2] * cs.horzcat(self.r[1], self.r[0], 0)

        return cs.Function('J', [self.x, self.u], [jac])
예제 #25
0
    def cost_func_SSP(self, robot, U, X0):

        cost = 0

        U = c.reshape(U, robot.nu, self.T)

        X = c.MX(robot.nx, self.T + 1)
        X[:, 0] = X0

        for i in range(self.T):

            cost = (cost + c.mtimes(c.mtimes(U[:, i].T, self.R), U[:, i]) +
                    c.mtimes(c.mtimes((self.Xg - X[:, i]).T, self.Q),
                             (self.Xg - X[:, i])))

            X_temp = X[0:2, i]

            if params.OBSTACLES:

                obstacle_cost =  params.M*(c.exp(-(c.mtimes(c.mtimes((params.c_obs_1 - X_temp).T, params.E_obs_1),(params.c_obs_1 - X_temp))))+ \
                                        c.exp(-(c.mtimes(c.mtimes((params.c_obs_2 - X_temp).T, params.E_obs_2),(params.c_obs_2 - X_temp)))) + \
                                        c.exp(-(c.mtimes(c.mtimes((params.c_obs_3 - X_temp).T, params.E_obs_3),(params.c_obs_3 - X_temp)))) + \
                                        c.exp(-(c.mtimes(c.mtimes((params.c_obs_4 - X_temp).T, params.E_obs_4),(params.c_obs_4 - X_temp)))))

                cost = cost + obstacle_cost
            X[:, i + 1] = robot.kinematics(X[:, i], U[:, i])

        cost = cost + c.mtimes(c.mtimes((self.Xg - X[:, self.T]).T, self.Qf),
                               (self.Xg - X[:, self.T]))

        return cost
    def proc_model(self):

        # f = c.Function('f',[self.x,self.u],[self.x[0] + self.u[0]*c.cos(self.x[2])*self.dt,
        #                                         self.x[1] + self.u[0]*c.sin(self.x[2])*self.dt,
        #                                         self.x[2] + self.u[0]*c.tan(self.x[3])*self.dt/self.length,
        #                                         self.x[3] + self.u[1]*self.dt])

        g = c.MX(self.nx,self.nu)
        g[0,0] = c.cos(self.x[2]); g[0,1] = 0;
        g[1,0] = c.sin(self.x[2]); g[1,1] = 0;
        g[2,0] = c.tan(self.x[3])/self.length; g[2,1] = 0
        g[3,0] = 0; g[3,1] = 1;

        # f = c.Function('f',[self.x,self.u],[self.x[0] + self.u[0]*c.cos(self.x[2])*self.dt,
        #                                         self.x[1] + self.u[0]*c.sin(self.x[2])*self.dt,
        #                                         self.x[2] + self.u[0]*c.tan(self.x[3])*self.dt/self.length,
        #                                         self.x[3] + self.u[1]*self.dt])

        f =  c.Function('f',[self.x,self.u],[self.x + c.mtimes(g,self.u)*self.dt])

        # A = c.Function('A',[self.x,self.u],[c.jacobian(f(self.x,self.u)[0],self.x),
        #                                         c.jacobian(f(self.x,self.u)[1],self.x),
        #                                         c.jacobian(f(self.x,self.u)[2],self.x),
        #                                         c.jacobian(f(self.x,self.u)[3],self.x)]) #linearization

        # B = c.Function('B',[self.x,self.u],[c.jacobian(f(self.x,self.u)[0],self.u),
        #                                         c.jacobian(f(self.x,self.u)[1],self.u),
        #                                         c.jacobian(f(self.x,self.u)[2],self.u),
        #                                         c.jacobian(f(self.x,self.u)[3],self.u)])

        A = c.Function('A',[self.x,self.u],[c.jacobian(f(self.x,self.u),self.x)])

        B = c.Function('B',[self.x,self.u],[c.jacobian(f(self.x,self.u),self.u)])

        return f,A, B
예제 #27
0
    def move(self, u, t, delta_t, is_pred=False, prev_x=None, prev_v=None):
        # x'(t) = Ax(t) + Bu(t) assumes u(t) = u(t+delta_t)
        # x(t + delta_t) = x(t) +  delta_t*(Ax(t) + Bu(t))
        prev_x = self.x_log[-1]
        A = self.A
        B = self.B
        if is_pred:
            prev_x = casadi.MX(prev_x)
            A = casadi.MX(A)
            B = casadi.MX(B)
        else:
            u = np.array(u).reshape(self.m)

        x_new = prev_x + delta_t * (A @ prev_x + B @ u)

        return x_new
예제 #28
0
    def test_convert_array_symbols(self):
        # Arrays
        a = np.array([1, 2, 3, 4, 5])
        pybamm_a = pybamm.Array(a)
        self.assert_casadi_equal(pybamm_a.to_casadi(), casadi.MX(a))

        casadi_t = casadi.MX.sym("t")
        casadi_y = casadi.MX.sym("y", 10)
        casadi_y_dot = casadi.MX.sym("y_dot", 10)

        pybamm_t = pybamm.Time()
        pybamm_y = pybamm.StateVector(slice(0, 10))
        pybamm_y_dot = pybamm.StateVectorDot(slice(0, 10))

        # Time
        self.assertEqual(pybamm_t.to_casadi(casadi_t, casadi_y), casadi_t)

        # State Vector
        self.assert_casadi_equal(pybamm_y.to_casadi(casadi_t, casadi_y),
                                 casadi_y)

        # State Vector Dot
        self.assert_casadi_equal(
            pybamm_y_dot.to_casadi(casadi_t, casadi_y, casadi_y_dot),
            casadi_y_dot)
예제 #29
0
    def state_contraints(self, robot, U):

        constraintVar = c.MX(
            2 * 2, self.T
        )  #skipping orientation & steer angle. 2* to include min and max
        U = c.reshape(U, robot.nu, self.T)
        X = c.MX(robot.nx, self.T + 1)
        X[:, 0] = self.X0

        for i in range(self.T):
            X[:, i + 1] = robot.kinematics(X[:, i], U[:, i])
            constraintVar[:, i] = c.blockcat([[self.Xmax - X[0:2, i + 1]],
                                              [X[0:2, i + 1] - self.Xmin]])

        constraintVar = c.reshape(constraintVar, 1, 2 * 2 * self.T)

        return constraintVar
예제 #30
0
def reduce_matvec(e, v):
    """
    Reduces the MX graph e of linear operations on p into a matrix-vector product.

    This reduces the number of nodes required to represent the linear operations.
    """
    Af = ca.Function('Af', [ca.MX()], [ca.jacobian(e, v)])
    A = Af(ca.DM())
    return ca.reshape(ca.mtimes(A, v), e.shape)