10 #include "mf_sensors_simulator/CameraOutput.h" 11 #include <tf2_geometry_msgs/tf2_geometry_msgs.h> 12 #include <eigen3/Eigen/Dense> 37 rp3d::CollisionBody *body)
43 rp3d::Transform transform = body->getTransform();
44 rp3d::CollisionBody* new_body =
parent_->
ray_world_.createCollisionBody(transform);
51 new_body->addCollisionShape(
parent_->
ray_shapes_.back().get(), rp3d::Transform::identity());
60 const rp3d::RaycastInfo& info)
65 hit_pt_ = tf2::Vector3(info.worldPoint.x, info.worldPoint.y,
72 return rp3d::decimal(0.0);
77 rp3d::CollisionBody* body, std::unique_ptr<rp3d::BoxShape> &shape, ros::Time stamp)
80 geometry_msgs::TransformStamped fixed_camera_tf;
82 if (stamp != ros::Time(0)) {
86 catch (tf2::TransformException &ex) {
87 NODELET_WARN(
"[camera_nodelet] %s", ex.what());
103 rp3d::Transform transform(pos, orient);
104 body->setTransform(transform);
107 unsigned int nbr_poses = poses.size();
108 std::vector<box_shape_ptr> shapes(nbr_poses);
116 for (
unsigned int k = 0; k < nbr_poses; k++) {
117 shapes[k] = unique_ptr<rp3d::BoxShape>(
new rp3d::BoxShape(half_extents));
119 rp3d::Vector3 fov_pos(poses[k].position.x, poses[k].position.y, poses[k].position.z +
fov_distance_/2);
120 rp3d::Quaternion fov_orient(poses[k].orientation.x, poses[k].orientation.y, poses[k].orientation.y, poses[k].orientation.z);
121 rp3d::Transform fov_transform(fov_pos, fov_orient);
122 body->addCollisionShape(shapes[k].
get(), fov_transform);
126 rp3d::AABB merged_shape = body->getAABB();
128 for (
unsigned int k = 0; k < nbr_poses; k++) {
129 body->removeCollisionShape(body->getProxyShapesList());
132 pos = merged_shape.getCenter();
133 orient = rp3d::Quaternion(0, 0, 0, 1);
134 transform = rp3d::Transform(pos, orient);
135 body->setTransform(transform);
137 half_extents = merged_shape.getExtent();
138 shape = unique_ptr<rp3d::BoxShape>(
new rp3d::BoxShape(half_extents));
139 body->addCollisionShape(shape.get(), rp3d::Transform::identity());
155 rp3d::Transform transform(pos, orient);
164 for (
unsigned int k = 0; k <
n; k++) {
175 std::vector<float> &w_algae, std::vector<float> &h_algae,
176 std::vector<float> &inc_y3, std::vector<float> &inc_z3,
177 std::vector<geometry_msgs::TransformStamped> &tf_algae)
179 unsigned int n = w_algae.size();
183 for (
int k = 0; k <
n; k++) {
186 rp3d::Vector3 pos = inverse_tf.getPosition();
187 rp3d::Quaternion quati = inverse_tf.getOrientation();
188 tf_algae[k].transform.translation.x = pos.x;
189 tf_algae[k].transform.translation.y = pos.y;
190 tf_algae[k].transform.translation.z = pos.z;
191 tf_algae[k].transform.rotation.x = quati.x;
192 tf_algae[k].transform.rotation.y = quati.y;
193 tf_algae[k].transform.rotation.z = quati.z;
194 tf_algae[k].transform.rotation.w = quati.w;
200 inc_y3[k] = w_algae[k] / (n_width);
201 inc_z3[k] = h_algae[k] / (n_height);
208 if (n_pixel_h <= 0 || n_pixel_w <= 0) {
213 tf2::Vector3 a(
sensor_width_*(-1./2 +
float(pxl_w)/(n_pixel_w-1)),
216 tf2::Vector3 origin(0, 0, 0);
217 tf2::Vector3 aim_pt =
fov_distance_ / tf2::tf2Distance(a, origin) * a;
224 const vector<geometry_msgs::TransformStamped> &transforms)
229 for (
int k = 0; k < transforms.size(); k++) {
230 tf2::Vector3 trans(transforms[k].transform.translation.x,
231 transforms[k].transform.translation.y,
232 transforms[k].transform.translation.z);
233 tf2::Quaternion orient(transforms[k].transform.rotation.x,
234 transforms[k].transform.rotation.y,
235 transforms[k].transform.rotation.z,
236 transforms[k].transform.rotation.w);
238 tf *= tf2::Transform(orient, trans);
241 tf2::Vector3 trans = tf.getOrigin();
242 tf2::Quaternion orient = tf.getRotation();
244 geometry_msgs::TransformStamped ret;
245 ret.transform.translation.x = trans.getX();
246 ret.transform.translation.y = trans.getY();
247 ret.transform.translation.z = trans.getZ();
248 ret.transform.rotation.x = orient.getX();
249 ret.transform.rotation.y = orient.getY();
250 ret.transform.rotation.z = orient.getZ();
251 ret.transform.rotation.w = orient.getW();
258 const geometry_msgs::TransformStamped &transform)
260 geometry_msgs::Pose pose;
261 tf2::toMsg(in_vector, pose.position);
262 pose.orientation.w = 1;
264 geometry_msgs::Pose transf_pose;
265 tf2::doTransform(pose, transf_pose, transform);
267 return tf2::Vector3(transf_pose.position.x, transf_pose.position.y, transf_pose.position.z);
272 const tf2::Vector3 &aim_pt,
273 tf2::Vector3 &hit_pt,
275 const geometry_msgs::TransformStamped &fixed_camera_tf,
276 const tf2::Vector3 &origin)
301 const tf2::Vector3 &aim_pt,
303 const geometry_msgs::TransformStamped &fixed_camera_tf,
304 const tf2::Vector3 &origin)
309 bool alga_hit =
raycast_alga(aim_pt, hit_pt, alga_idx, fixed_camera_tf, origin);
313 distance = tf2::tf2Distance(hit_pt,
apply_transform(origin, fixed_camera_tf));
322 const geometry_msgs::Pose &vp_pose,
323 int n_pxl_h,
int n_pxl_w,
324 mf_sensors_simulator::CameraOutput &pxl_output,
328 int n_pixels = n_pxl_h * n_pxl_w;
329 pxl_output.x.reserve(n_pixels);
330 pxl_output.y.reserve(n_pixels);
331 pxl_output.z.reserve(n_pixels);
334 geometry_msgs::TransformStamped camera_fixed_tf, fixed_camera_tf;
336 if (stamp != ros::Time(0)) {
341 catch (tf2::TransformException &ex) {
342 NODELET_WARN(
"[camera_nodelet] Bonjour %s", ex.what());
351 int x_corner[4] = {0, n_pxl_h-1, n_pxl_h-1, 0};
352 int y_corner[4] = {0, 0, n_pxl_w-1, n_pxl_w-1};
353 bool hit_all_corners =
true;
354 tf2::Vector3 origin(vp_pose.position.x, vp_pose.position.y, vp_pose.position.z);
355 geometry_msgs::TransformStamped camera_vp_tf =
pose_to_tf(vp_pose);
357 for (
int l = 0; l < 4; l++) {
359 tf2::Vector3 aim_pt1 =
get_aim_pt(x_corner[l], y_corner[l], n_pxl_h, n_pxl_w);
365 bool alga_hit =
raycast_alga(aim_pt, hit_pt, alga_idx, fixed_camera_tf, origin);
370 pxl_output.x.emplace_back(out_pt.getX());
371 pxl_output.y.emplace_back(out_pt.getY());
372 pxl_output.z.emplace_back(out_pt.getZ());
374 hit_all_corners =
false;
379 if (hit_all_corners) {
380 tf2::Vector3 p1(pxl_output.x[0], pxl_output.y[0], pxl_output.z[0]);
381 tf2::Vector3 p2(pxl_output.x[1], pxl_output.y[1], pxl_output.z[1]);
382 tf2::Vector3 p3(pxl_output.x[2], pxl_output.y[2], pxl_output.z[2]);
383 tf2::Vector3 p4(pxl_output.x[3], pxl_output.y[3], pxl_output.z[3]);
387 pxl_output.x, pxl_output.y, pxl_output.z
393 for (
int i = 0; i < n_pxl_h; i++) {
394 for (
int j = 0; j < n_pxl_w; j++) {
395 if ((i != 0 && i != n_pxl_h-1) || (j != 0 && j != n_pxl_w-1)) {
397 tf2::Vector3 aim_pt1 =
get_aim_pt(i, j, n_pxl_h, n_pxl_w);
403 bool alga_hit =
raycast_alga(aim_pt, hit_pt, alga_idx, fixed_camera_tf, origin);
408 pxl_output.x.emplace_back(out_pt.getX());
409 pxl_output.y.emplace_back(out_pt.getY());
410 pxl_output.z.emplace_back(out_pt.getZ());
418 int n = pxl_output.x.size();
419 pxl_output.distance.resize(n);
420 pxl_output.value.resize(n);
422 for (
int k = 0; k <
n; k++) {
423 tf2::Vector3 pt(pxl_output.x[k], pxl_output.y[k], pxl_output.z[k]);
424 pxl_output.distance[k] = tf2::tf2Distance(pt, origin);
426 pxl_output.value[k] = 0;
434 const tf2::Vector3 &p1,
const tf2::Vector3 &p2,
const tf2::Vector3 &p3,
const tf2::Vector3 &p4,
436 vector<float> &x_list, vector<float> &y_list, vector<float> &z_list
439 Eigen::Vector4d X(p1.getX(), p2.getX(), p3.getX(), p4.getX());
440 Eigen::Vector4d Y(p1.getY(), p2.getY(), p3.getY(), p4.getY());
441 Eigen::Vector4d Z(p1.getZ(), p2.getZ(), p3.getZ(), p4.getZ());
448 Eigen::Matrix4d A_inv = A.inverse();
450 Eigen::Vector4d alpha = A_inv * X;
451 Eigen::Vector4d beta = A_inv * Y;
452 Eigen::Vector4d gamma = A_inv * Z;
454 for (
int i = 0; i < n_h; i++) {
455 for (
int j = 0; j < n_w; j++) {
456 if ((i != 0 && i != n_h-1) || (j != 0 && j != n_w-1)) {
457 float u = -1 + 2.0*i/(n_h-1);
458 float v = -1 + 2.0*j/(n_w-1);
459 float x = alpha[0] + alpha[1]*u + alpha[2]*v + alpha[3]*u*v;
460 float y = beta[0] + beta[1]*u + beta[2]*v + beta[3]*u*v;
461 float z = gamma[0] + gamma[1]*u + gamma[2]*v + gamma[3]*u*v;
463 x_list.emplace_back(x);
464 y_list.emplace_back(y);
465 z_list.emplace_back(z);
void get_ray_algae_carac(std::vector< float > &w_algae, std::vector< float > &h_algae, std::vector< float > &inc_y3, std::vector< float > &inc_z3, std::vector< geometry_msgs::TransformStamped > &tf_algae)
Gets position, dimension and axes of the algae for raycasting.
std::vector< int > corr_algae_
Correspondance between the algae used for raytracing and all the others.
float focal_length_
Focal length of the camera.
virtual rp3d::decimal notifyRaycastHit(const rp3d::RaycastInfo &info)
int n_pxl_width_
Nbr of pixels along sensor width.
rp3d::CollisionWorld ray_world_
World with algae colliding with FOV.
void overlap_fov(rp3d::CollisionBody *body)
Selects algae that are in field of view of the camera.
rp3d::CollisionWorld coll_world_
World with all algae and camera FOV.
std::vector< std::vector< std::vector< float > > > heatmaps_
Disease heatmatps for all the algae.
tf2::Vector3 apply_transform(const tf2::Vector3 &in_vector, const geometry_msgs::TransformStamped &transform)
Applies a transform to a vector.
tf2::Vector3 hit_pt_
Hit point.
geometry_msgs::TransformStamped fixed_camera_tf_
Transform from fixed frame to camera.
std::vector< box_shape_ptr > ray_shapes_
Collision shapes of algae for raycasting.
CameraNodelet * parent_
Parent CameraNodelet instance.
bool raycast_wall(const geometry_msgs::Pose &vp_pose, int n_pxl_h, int n_pxl_w, mf_sensors_simulator::CameraOutput &pxl_output, ros::Time stamp=ros::Time(0))
geometry_msgs::TransformStamped pose_to_tf(const geometry_msgs::Pose &pose)
Converts a pose to a transform.
virtual void notifyOverlap(rp3d::CollisionBody *body)
tf2_ros::Buffer tf_buffer_
std::unique_ptr< rp3d::BoxShape > box_shape_ptr
float distance(const geometry_msgs::Point &p1, const geometry_msgs::Point &p2)
Computes the the euclidean distance between two positions.
float fov_distance_
Maximum distance detected by the camera.
rp3d::Vector3 tf2_to_rp3d(const tf2::Vector3 vect)
Converts a tf2 vector to a rp3d vector.
geometry_msgs::TransformStamped inverse_tf(const geometry_msgs::TransformStamped &transform)
Inverse a transform.
void interpolate_quadri(const tf2::Vector3 &p1, const tf2::Vector3 &p2, const tf2::Vector3 &p3, const tf2::Vector3 &p4, int n_h, int n_w, std::vector< float > &x_list, std::vector< float > &y_list, std::vector< float > &z_list)
Interpolates a 3D quadrilateral lying on a plane.
float sensor_height_
Height of the camera sensor.
bool raycast_alga(const tf2::Vector3 &aim_pt, tf2::Vector3 &hit_pt, int &alga_idx, const geometry_msgs::TransformStamped &fixed_camera_tf, const tf2::Vector3 &origin=tf2::Vector3(0, 0, 0))
Casts a ray on algae and gets hit point.
Callback class for raycasting.
std::string fixed_frame_
Frame in which the pose is expressed.
Callback class for overlap detection.
RaycastCallback(CameraNodelet *parent)
void update_fov_pose()
Updates pose of field of view body.
std::vector< rp3d::CollisionBody * > ray_bodies_
Collision bodies for raycasting.
geometry_msgs::TransformStamped combine_transforms(const std::vector< geometry_msgs::TransformStamped > &transforms)
Combine transforms sequentially.
RaycastCallback raycast_cb_
Callback instance for raycasting.
OverlapCallback overlap_cb_
int alga_idx_
Index of the hit alga in the ray_bodies_ vector.
std::string camera_frame_
Frame of the camera.
std::vector< rp3d::CollisionBody * > algae_bodies_
Collision bodies of the algae.
int n_pxl_height_
Nbr of pixels along sensor height.
tf2::Vector3 get_aim_pt(int pxl_h, int pxl_w, int n_pixel_h=-1, int n_pixel_w=-1)
Gets an aim point from pixel coordinates for raycasting.
geometry_msgs::TransformStamped camera_fixed_tf_
Transform from camera to fixed frame.
bool alga_hit_
Whether an alga has been hit.
float sensor_width_
Width of the camera sensor.
CameraNodelet * parent_
Parent CameraNodelet instance.
Nodelet for a simulated camera.
std::vector< box_shape_ptr > algae_shapes_
Collision shapes of the algae bodies.
bool multi_fov_body(const std::vector< geometry_msgs::Pose > &poses, rp3d::CollisionBody *body, std::unique_ptr< rp3d::BoxShape > &shape, ros::Time stamp=ros::Time(0))
Fill a collision body for multi-pose FOV overlap.
Declaration of a nodelet simulating a camera.
rp3d::CollisionBody * fov_body_
Collision body of the camera FOV.