예제 #1
0
    def distance_squared(self, u):
        # Function `distance` can be applied to CasADi symbols and
        # lists of numbers. However, if `u` is a symbol, we need to
        # use appropriate CasADi functions like cs.sign and cs.norm_2
        if fn.is_symbolic(u):
            # Case I: `u` is a CasADi SX symbol
            nu = u.size(1)
            v = u if self.__center is None else u - self.__center
        elif (isinstance(u, list) and all(isinstance(x, (int, float)) for x in u)) \
                or isinstance(u, np.ndarray):
            # Case II: `u` is an array of numbers or an np.ndarray
            nu = len(u)
            if self.__center is None:
                v = u
            else:
                # Note: self.__center is np.ndarray (`u` might be a list)
                z = self.__center.reshape(nu)
                u = np.array(u).reshape(nu)
                v = np.subtract(u, z)
        else:
            raise Exception("u is of invalid type")

        # Compute distance to Ball infinity:
        # dist^2(u) = norm(v)^2
        #            + SUM_i [
        #                         min{vi^2, r^2}
        #                       - 2*min{vi^2, r*|vi|}
        #                    ]
        # where v = u - xc

        squared_distance = fn.norm2(v)**2
        for i in range(nu):
            squared_distance += fn.fmin(v[i]**2, self.radius**2) \
                                - 2.0 * fn.fmin(v[i]**2, self.radius * fn.fabs(v[i]))
        return squared_distance
예제 #2
0
    def distance_squared(self, u):
        """Computes the squared distance between a given point `u` and this
           second-order cone

            :param u: given point; can be a list of float, a numpy
                n-dim array (`ndarray`) or a CasADi SX/MX symbol

            :return: distance from set as a float or a CasADi symbol
        """

        if isinstance(u, cs.SX):
            warnings.warn(
                "This function does not accept casadi.SX; use casadi.MX instead"
            )

        if fn.is_symbolic(u):
            nu = u.size(1)
        elif (isinstance(u, list) and all(isinstance(x, (int, float)) for x in u)) \
                or isinstance(u, np.ndarray):
            nu = len(u)
        else:
            raise Exception("Illegal Argument, `u`")

        # Partition `u = (x, r)`, where `r` is the last element of `u`
        a = self.__a
        x = u[0:nu - 1]
        r = u[nu - 1]

        eps = 1e-16

        norm_x = fn.norm2(x)  # norm of x
        sq_norm_x = cs.dot(x, x)  # squared norm of x
        gamma = (a * norm_x + r) / (a**2 + 1)

        fun1 = 0
        fun2 = sq_norm_x + r**2
        fun3 = sq_norm_x * (1 - gamma * a / norm_x)**2 + (r - gamma)**2

        condition0 = norm_x + cs.fabs(r) < eps
        condition1 = norm_x <= a * r
        condition2 = a * norm_x <= -r

        f = cs.if_else(
            condition0, 0,
            cs.if_else(condition1, fun1,
                       cs.if_else(condition2, fun2, fun3, True), True), True)

        return f
예제 #3
0
    def distance_squared(self, u):
        """Computes the squared distance between a given point `u` and this ball

            :param u: given point; can be a list of float, a numpy
                n-dim array (`ndarray`) or a CasADi SX/MX symbol

            :return: distance from set as a float or a CasADi symbol
        """
        if fn.is_symbolic(u):
            # Case I: `u` is a CasADi SX symbol
            v = u if self.__center is None else u - self.__center
        elif (isinstance(u, list) and all(isinstance(x, (int, float)) for x in u))\
                or isinstance(u, np.ndarray):
            # Case II: `u` is an array of numbers or an np.ndarray
            if self.__center is None:
                v = u
            else:
                # Note: self.__center is np.ndarray (`u` might be a list)
                z = self.__center.reshape(len(u))
                u = np.array(u).reshape(len(u))
                v = np.subtract(u, z)
        else:
            raise Exception("u is of invalid type")

        # Compute squared distance
        # Let B = B(xc, r) be a Euclidean ball centered at xc with radius r
        #
        # dist_B^2(u) = max(0, sign(t(u))*t(u)^2), where
        # t(u) = ||u - x_c|| - r
        #
        # Note: there is another way to take squared distances:
        # d_B^2(u) = ||u||^2 * (1 - 1 / max{r, ||u||})^2,
        # but this leads to slightly lengthier CasADi symbols for
        # the Jacobian of the squared distance, so this approach was
        # abandoned
        t = fn.norm2(v) - self.radius
        return fn.fmax(0.0, fn.sign(t) * t ** 2)