scenario_simulator_v2 C++ API
raycaster.hpp
Go to the documentation of this file.
1 // Copyright 2015 TIER IV, Inc. All rights reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef SIMPLE_SENSOR_SIMULATOR__SENSOR_SIMULATION__LIDAR__RAYCASTER_HPP_
16 #define SIMPLE_SENSOR_SIMULATOR__SENSOR_SIMULATION__LIDAR__RAYCASTER_HPP_
17 
18 #include <embree4/rtcore.h>
19 #include <pcl_conversions/pcl_conversions.h>
20 
23 #include <geometry_msgs/msg/pose.hpp>
24 #include <geometry_msgs/msg/vector3.hpp>
25 #include <memory>
26 #include <random>
27 #include <sensor_msgs/msg/point_cloud2.hpp>
30 #include <string>
31 #include <unordered_map>
32 #include <utility>
33 #include <vector>
34 
36 {
37 class Raycaster
38 {
39 public:
40  Raycaster();
41  explicit Raycaster(std::string embree_config);
42  ~Raycaster();
43  template <typename T, typename... Ts>
44  void addPrimitive(std::string name, Ts &&... xs)
45  {
46  if (primitive_ptrs_.count(name) != 0) {
47  throw std::runtime_error("primitive " + name + " already exist.");
48  }
49  auto primitive_ptr = std::make_unique<T>(std::forward<Ts>(xs)...);
50  primitive_ptrs_.emplace(name, std::move(primitive_ptr));
51  }
52  const sensor_msgs::msg::PointCloud2 raycast(
53  const std::string & frame_id, const rclcpp::Time & stamp,
54  const geometry_msgs::msg::Pose & origin, double max_distance = 300, double min_distance = 0);
55  const std::vector<std::string> & getDetectedObject() const;
56  void setDirection(
57  const simulation_api_schema::LidarConfiguration & configuration,
58  double horizontal_angle_start = 0, double horizontal_angle_end = 2 * M_PI);
59 
60 private:
61  std::vector<geometry_msgs::msg::Quaternion> getDirections(
62  const std::vector<double> & vertical_angles, double horizontal_angle_start,
63  double horizontal_angle_end, double horizontal_resolution);
64  std::vector<geometry_msgs::msg::Quaternion> directions_;
65  double previous_horizontal_angle_start_;
66  double previous_horizontal_angle_end_;
67  double previous_horizontal_resolution_;
68  std::vector<double> previous_vertical_angles_;
69  std::unordered_map<std::string, std::unique_ptr<primitives::Primitive>> primitive_ptrs_;
70  RTCDevice device_;
71  RTCScene scene_;
72  std::random_device seed_gen_;
73  std::default_random_engine engine_;
74  std::vector<std::string> detected_objects_;
75  std::unordered_map<unsigned int, std::string> geometry_ids_;
76  std::vector<Eigen::Matrix3d> rotation_matrices_;
77 
78  static void intersect(
79  int thread_id, int thread_count, RTCScene scene,
80  pcl::PointCloud<pcl::PointXYZI>::Ptr thread_cloud, geometry_msgs::msg::Pose origin,
81  std::reference_wrapper<std::set<unsigned int>> ref_thread_detected_ids, double max_distance,
82  double min_distance,
83  std::reference_wrapper<const std::vector<Eigen::Matrix3d>> ref_rotation_matrices)
84  {
85  auto & rotation_matrices = ref_rotation_matrices.get();
86  auto & thread_detected_ids = ref_thread_detected_ids.get();
87  const auto orientation_matrix = math::geometry::getRotationMatrix(origin.orientation);
88  for (unsigned int i = thread_id; i < rotation_matrices.size(); i += thread_count) {
89  RTCRayHit rayhit = {};
90  rayhit.ray.org_x = origin.position.x;
91  rayhit.ray.org_y = origin.position.y;
92  rayhit.ray.org_z = origin.position.z;
93  // make raycast interact with all objects
94  rayhit.ray.mask = 0b11111111'11111111'11111111'11111111;
95  rayhit.ray.tfar = max_distance;
96  rayhit.ray.tnear = min_distance;
97  rayhit.ray.flags = false;
98 
99  const auto rotation_mat = orientation_matrix * rotation_matrices.at(i);
100  rayhit.ray.dir_x = rotation_mat(0);
101  rayhit.ray.dir_y = rotation_mat(1);
102  rayhit.ray.dir_z = rotation_mat(2);
103  rayhit.hit.geomID = RTC_INVALID_GEOMETRY_ID;
104  rtcIntersect1(scene, &rayhit);
105 
106  if (rayhit.hit.geomID != RTC_INVALID_GEOMETRY_ID) {
107  double distance = rayhit.ray.tfar;
108  pcl::PointXYZI p;
109  {
110  p.x = rotation_matrices.at(i)(0) * distance;
111  p.y = rotation_matrices.at(i)(1) * distance;
112  p.z = rotation_matrices.at(i)(2) * distance;
113  }
114  thread_cloud->emplace_back(p);
115  thread_detected_ids.insert(rayhit.hit.geomID);
116  }
117  }
118  }
119 };
120 } // namespace simple_sensor_simulator
121 
122 #endif // SIMPLE_SENSOR_SIMULATOR__SENSOR_SIMULATION__LIDAR__RAYCASTER_HPP_
Definition: raycaster.hpp:38
void addPrimitive(std::string name, Ts &&... xs)
Definition: raycaster.hpp:44
~Raycaster()
Definition: raycaster.cpp:42
const sensor_msgs::msg::PointCloud2 raycast(const std::string &frame_id, const rclcpp::Time &stamp, const geometry_msgs::msg::Pose &origin, double max_distance=300, double min_distance=0)
Definition: raycaster.cpp:99
Raycaster()
Definition: raycaster.cpp:26
void setDirection(const simulation_api_schema::LidarConfiguration &configuration, double horizontal_angle_start=0, double horizontal_angle_end=2 *M_PI)
Definition: raycaster.cpp:48
const std::vector< std::string > & getDetectedObject() const
Definition: raycaster.cpp:97
auto getRotationMatrix(T quat) -> Eigen::Matrix3d
Definition: get_rotation_matrix.hpp:33
Definition: constants.hpp:19
auto distance(const geometry_msgs::Pose &pose1, const geometry_msgs::Pose &pose2)
Definition: detection_sensor.cpp:36
Definition: junit5.hpp:25
std::string string
Definition: junit5.hpp:26