Panda3D
obstacleAvoidance.cxx
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file obstacleAvoidance.cxx
10  * @author Deepak, John, Navin
11  * @date 2009-11-10
12  */
13 
14 #include "obstacleAvoidance.h"
15 
16 ObstacleAvoidance::
17 ObstacleAvoidance(AICharacter *ai_char, float feeler_length) {
18  _ai_char = ai_char;
19  _feeler = feeler_length;
20 }
21 
22 ObstacleAvoidance::
23 ~ObstacleAvoidance() {
24 }
25 
26 /**
27  * This function checks if an obstacle is near to the AICharacter and if an
28  * obstacle is detected returns true
29  */
32  // Calculate the volume of the AICharacter with respect to render
33  PT(BoundingVolume) np_bounds = _ai_char->get_node_path().get_bounds();
34  CPT(BoundingSphere) np_sphere = np_bounds->as_bounding_sphere();
35  LVecBase3 avoidance(0.0, 0.0, 0.0);
36  double distance = 0x7fff ;
37  double expanded_radius = 0;
38  LVecBase3 to_obstacle;
39  for(unsigned int i = 0; i < _ai_char->_world->_obstacles.size(); ++i) {
40  PT(BoundingVolume) bounds = _ai_char->_world->_obstacles[i].get_bounds();
41  CPT(BoundingSphere) bsphere = bounds->as_bounding_sphere();
42  LVecBase3 near_obstacle = _ai_char->_world->_obstacles[i].get_pos() - _ai_char->get_node_path().get_pos();
43  // Check if it's the nearest obstacle, If so initialize as the nearest
44  // obstacle
45  if((near_obstacle.length() < distance) && (_ai_char->_world->_obstacles[i].get_pos() != _ai_char->get_node_path().get_pos())) {
46  _nearest_obstacle = _ai_char->_world->_obstacles[i];
47  distance = near_obstacle.length();
48  expanded_radius = bsphere->get_radius() + np_sphere->get_radius();
49  }
50  }
51 
52  LVecBase3 feeler = _feeler * _ai_char->get_char_render().get_relative_vector(_ai_char->get_node_path(), LVector3::forward());
53  feeler.normalize();
54  feeler *= (expanded_radius + np_sphere->get_radius()) ;
55  to_obstacle = _nearest_obstacle.get_pos() - _ai_char->get_node_path().get_pos();
56  LVector3 line_vector = _ai_char->get_char_render().get_relative_vector(_ai_char->get_node_path(), LVector3::forward());
57  LVecBase3 project = (to_obstacle.dot(line_vector) * line_vector) / line_vector.length_squared();
58  LVecBase3 perp = project - to_obstacle;
59 
60  // If the nearest obstacle will collide with our AICharacter then send
61  // obstacle detection as true
62  if (_nearest_obstacle && (perp.length() < expanded_radius - np_sphere->get_radius()) && (project.length() < feeler.length())) {
63  return true;
64  }
65  return false;
66 }
67 
68 /**
69  * This function activates obstacle_avoidance if a obstacle is detected
70  */
73  if (obstacle_detection()) {
74  _ai_char->_steering->turn_off("obstacle_avoidance_activate");
75  _ai_char->_steering->turn_on("obstacle_avoidance");
76  }
77 }
78 
79 /**
80  * This function returns the force necessary by the AICharacter to avoid the
81  * nearest obstacle detected by obstacle_detection function NOTE : This
82  * assumes the obstacles are spherical
83  */
84 LVecBase3 ObstacleAvoidance::
86  LVecBase3 offset = _ai_char->get_node_path().get_pos() - _nearest_obstacle.get_pos();
87  PT(BoundingVolume) bounds =_nearest_obstacle.get_bounds();
88  CPT(BoundingSphere) bsphere = bounds->as_bounding_sphere();
89  PT(BoundingVolume) np_bounds = _ai_char->get_node_path().get_bounds();
90  CPT(BoundingSphere) np_sphere = np_bounds->as_bounding_sphere();
91 
92  if (obstacle_detection()) {
93  LVecBase3 direction = _ai_char->get_char_render().get_relative_vector(_ai_char->get_node_path(), LVector3::forward());
94  direction.normalize();
95  float forward_component = offset.dot(direction);
96  LVecBase3 projection = forward_component * direction;
97  LVecBase3 perpendicular_component = offset - projection;
98  double p = perpendicular_component.length();
99  perpendicular_component.normalize();
100  LVecBase3 avoidance = perpendicular_component;
101  // The more closer the obstacle, the more force it generates
102  avoidance = (avoidance * _ai_char->get_max_force() * _ai_char->_movt_force) / (p + 0.01);
103  return avoidance;
104  }
105  _ai_char->_steering->turn_on("obstacle_avoidance_activate");
106  _ai_char->_steering->turn_off("obstacle_avoidance");
107  return LVecBase3(0, 0, 0);
108 }
LVector3 get_relative_vector(const NodePath &other, const LVecBase3 &vec) const
Given that the indicated vector is in the coordinate system of the other node, returns the same vecto...
Definition: nodePath.cxx:1903
This defines a bounding sphere, consisting of a center and a radius.
void turn_on(std::string ai_type)
This function turns on any aiBehavior which is passed as a string.
bool obstacle_detection()
This function checks if an obstacle is near to the AICharacter and if an obstacle is detected returns...
void turn_off(std::string ai_type)
This function turns off any aiBehavior which is passed as a string.
This is an abstract class for any volume in any sense which can be said to define the locality of ref...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
LPoint3 get_pos() const
Retrieves the translation component of the transform.
Definition: nodePath.cxx:992
void obstacle_avoidance_activate()
This function activates obstacle_avoidance if a obstacle is detected.
LVecBase3 do_obstacle_avoidance()
This function returns the force necessary by the AICharacter to avoid the nearest obstacle detected b...