Program Listing for File collision_object.h

Return to documentation for file (include/coal/collision_object.h)

/*
 * Software License Agreement (BSD License)
 *
 *  Copyright (c) 2011-2014, Willow Garage, Inc.
 *  Copyright (c) 2014-2015, Open Source Robotics Foundation
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   * Neither the name of Open Source Robotics Foundation nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef COAL_COLLISION_OBJECT_BASE_H
#define COAL_COLLISION_OBJECT_BASE_H

#include <limits>
#include <typeinfo>

#include "coal/deprecated.hh"
#include "coal/fwd.hh"
#include "coal/BV/AABB.h"
#include "coal/math/transform.h"

namespace coal {

enum OBJECT_TYPE {
  OT_UNKNOWN,
  OT_BVH,
  OT_GEOM,
  OT_OCTREE,
  OT_HFIELD,
  OT_COUNT
};

enum NODE_TYPE {
  BV_UNKNOWN,
  BV_AABB,
  BV_OBB,
  BV_RSS,
  BV_kIOS,
  BV_OBBRSS,
  BV_KDOP16,
  BV_KDOP18,
  BV_KDOP24,
  GEOM_BOX,
  GEOM_SPHERE,
  GEOM_CAPSULE,
  GEOM_CONE,
  GEOM_CYLINDER,
  GEOM_CONVEX,
  GEOM_PLANE,
  GEOM_HALFSPACE,
  GEOM_TRIANGLE,
  GEOM_OCTREE,
  GEOM_ELLIPSOID,
  HF_AABB,
  HF_OBBRSS,
  NODE_COUNT
};


class COAL_DLLAPI CollisionGeometry {
 public:
  CollisionGeometry()
      : aabb_center(Vec3s::Constant((std::numeric_limits<CoalScalar>::max)())),
        aabb_radius(-1),
        cost_density(1),
        threshold_occupied(1),
        threshold_free(0) {}

  CollisionGeometry(const CollisionGeometry& other) = default;

  virtual ~CollisionGeometry() {}

  virtual CollisionGeometry* clone() const = 0;

  bool operator==(const CollisionGeometry& other) const {
    return cost_density == other.cost_density &&
           threshold_occupied == other.threshold_occupied &&
           threshold_free == other.threshold_free &&
           aabb_center == other.aabb_center &&
           aabb_radius == other.aabb_radius && aabb_local == other.aabb_local &&
           isEqual(other);
  }

  bool operator!=(const CollisionGeometry& other) const {
    return isNotEqual(other);
  }

  virtual OBJECT_TYPE getObjectType() const { return OT_UNKNOWN; }

  virtual NODE_TYPE getNodeType() const { return BV_UNKNOWN; }

  virtual void computeLocalAABB() = 0;

  void* getUserData() const { return user_data; }

  void setUserData(void* data) { user_data = data; }

  inline bool isOccupied() const { return cost_density >= threshold_occupied; }

  inline bool isFree() const { return cost_density <= threshold_free; }

  bool isUncertain() const;

  Vec3s aabb_center;

  CoalScalar aabb_radius;

  AABB aabb_local;

  void* user_data;

  CoalScalar cost_density;

  CoalScalar threshold_occupied;

  CoalScalar threshold_free;

  virtual Vec3s computeCOM() const { return Vec3s::Zero(); }

  virtual Matrix3s computeMomentofInertia() const {
    return Matrix3s::Constant(NAN);
  }

  virtual CoalScalar computeVolume() const { return 0; }

  virtual Matrix3s computeMomentofInertiaRelatedToCOM() const {
    Matrix3s C = computeMomentofInertia();
    Vec3s com = computeCOM();
    CoalScalar V = computeVolume();

    return (Matrix3s() << C(0, 0) - V * (com[1] * com[1] + com[2] * com[2]),
            C(0, 1) + V * com[0] * com[1], C(0, 2) + V * com[0] * com[2],
            C(1, 0) + V * com[1] * com[0],
            C(1, 1) - V * (com[0] * com[0] + com[2] * com[2]),
            C(1, 2) + V * com[1] * com[2], C(2, 0) + V * com[2] * com[0],
            C(2, 1) + V * com[2] * com[1],
            C(2, 2) - V * (com[0] * com[0] + com[1] * com[1]))
        .finished();
  }

 private:
  virtual bool isEqual(const CollisionGeometry& other) const = 0;

  virtual bool isNotEqual(const CollisionGeometry& other) const {
    return !(*this == other);
  }

 public:
  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
};

class COAL_DLLAPI CollisionObject {
 public:
  CollisionObject(const shared_ptr<CollisionGeometry>& cgeom_,
                  bool compute_local_aabb = true)
      : cgeom(cgeom_), user_data(nullptr) {
    init(compute_local_aabb);
  }

  CollisionObject(const shared_ptr<CollisionGeometry>& cgeom_,
                  const Transform3s& tf, bool compute_local_aabb = true)
      : cgeom(cgeom_), t(tf), user_data(nullptr) {
    init(compute_local_aabb);
  }

  CollisionObject(const shared_ptr<CollisionGeometry>& cgeom_,
                  const Matrix3s& R, const Vec3s& T,
                  bool compute_local_aabb = true)
      : cgeom(cgeom_), t(R, T), user_data(nullptr) {
    init(compute_local_aabb);
  }

  bool operator==(const CollisionObject& other) const {
    return cgeom == other.cgeom && t == other.t && user_data == other.user_data;
  }

  bool operator!=(const CollisionObject& other) const {
    return !(*this == other);
  }

  ~CollisionObject() {}

  OBJECT_TYPE getObjectType() const { return cgeom->getObjectType(); }

  NODE_TYPE getNodeType() const { return cgeom->getNodeType(); }

  const AABB& getAABB() const { return aabb; }

  AABB& getAABB() { return aabb; }

  void computeAABB() {
    if (t.getRotation().isIdentity()) {
      aabb = translate(cgeom->aabb_local, t.getTranslation());
    } else {
      aabb.min_ = aabb.max_ = t.getTranslation();

      Vec3s min_world, max_world;
      for (int k = 0; k < 3; ++k) {
        min_world.array() = t.getRotation().row(k).array() *
                            cgeom->aabb_local.min_.transpose().array();
        max_world.array() = t.getRotation().row(k).array() *
                            cgeom->aabb_local.max_.transpose().array();

        aabb.min_[k] += (min_world.array().min)(max_world.array()).sum();
        aabb.max_[k] += (min_world.array().max)(max_world.array()).sum();
      }
    }
  }

  void* getUserData() const { return user_data; }

  void setUserData(void* data) { user_data = data; }

  inline const Vec3s& getTranslation() const { return t.getTranslation(); }

  inline const Matrix3s& getRotation() const { return t.getRotation(); }

  inline const Transform3s& getTransform() const { return t; }

  void setRotation(const Matrix3s& R) { t.setRotation(R); }

  void setTranslation(const Vec3s& T) { t.setTranslation(T); }

  void setTransform(const Matrix3s& R, const Vec3s& T) { t.setTransform(R, T); }

  void setTransform(const Transform3s& tf) { t = tf; }

  bool isIdentityTransform() const { return t.isIdentity(); }

  void setIdentityTransform() { t.setIdentity(); }

  const shared_ptr<const CollisionGeometry> collisionGeometry() const {
    return cgeom;
  }

  const shared_ptr<CollisionGeometry>& collisionGeometry() { return cgeom; }

  const CollisionGeometry* collisionGeometryPtr() const { return cgeom.get(); }

  CollisionGeometry* collisionGeometryPtr() { return cgeom.get(); }

  void setCollisionGeometry(
      const shared_ptr<CollisionGeometry>& collision_geometry,
      bool compute_local_aabb = true) {
    if (collision_geometry.get() != cgeom.get()) {
      cgeom = collision_geometry;
      init(compute_local_aabb);
    }
  }

 protected:
  void init(bool compute_local_aabb = true) {
    if (cgeom) {
      if (compute_local_aabb) cgeom->computeLocalAABB();
      computeAABB();
    }
  }

  shared_ptr<CollisionGeometry> cgeom;

  Transform3s t;

  mutable AABB aabb;

  void* user_data;
};

}  // namespace coal

#endif