ed
view_model.cpp
Go to the documentation of this file.
2 #include <ed/world_model.h>
3 #include <ed/update_request.h>
4 #include <ed/entity.h>
5 #include <ed/rendering.h>
6 
7 #include <fstream>
8 
10 #include <geolib/Shape.h>
11 #include <geolib/Box.h>
12 
13 #include <opencv2/highgui/highgui.hpp>
14 
15 #include <tue/config/reader.h>
17 #include "tue/config/loaders/sdf.h"
18 #include "tue/config/loaders/xml.h"
20 
21 #include <tue/filesystem/path.h>
22 
23 #include <math.h>
24 
25 constexpr double CANVAS_WIDTH = 800;
26 constexpr double CANVAS_HEIGHT = 600;
27 
29 
32 cv::Point LAST_MOUSE_POS;
33 bool do_rotate = true;
35 
36 bool do_flyto = false;
38 
39 bool render_required = true;
40 
41 cv::Mat depth_image;
42 cv::Mat image;
43 
44 // ----------------------------------------------------------------------------------------------------
45 
46 void usage()
47 {
48  std::cout << "Usage: ed_view_model [ --file | --model ] FILE-OR-MODEL-NAME" << std::endl;
49 }
50 
51 // ----------------------------------------------------------------------------------------------------
52 
53 void CallBackFunc(int event, int x, int y, int flags, void* /*userdata*/)
54 {
55  if (event == cv::EVENT_LBUTTONDBLCLK)
56  {
57  float d = depth_image.at<float>(y, x);
58  if (d > 0)
59  {
61  do_flyto = true;
62  }
63  }
64  else if (event == cv::EVENT_LBUTTONDOWN)
65  {
66  LAST_MOUSE_POS = cv::Point(x, y);
67  do_rotate = false;
68  }
69  else if (event == cv::EVENT_RBUTTONDOWN)
70  {
71  LAST_MOUSE_POS = cv::Point(x, y);
72  do_rotate = false;
73  }
74  else if (event == cv::EVENT_MBUTTONDOWN)
75  {
76  LAST_MOUSE_POS = cv::Point(x, y);
77  do_rotate = false;
78  }
79  else if (event == cv::EVENT_MOUSEMOVE)
80  {
81  double dx = x - LAST_MOUSE_POS.x;
82  double dy = y - LAST_MOUSE_POS.y;
83 
84  if (flags & cv::EVENT_FLAG_LBUTTON)
85  {
86  cam_yaw -= dx * 0.003;
87  cam_pitch += dy * 0.003;
88 
89  if (cam_pitch > 1.57)
90  cam_pitch = 1.57;
91  else if (cam_pitch < -1.57)
92  cam_pitch = -1.57;
93  }
94  else if (flags & cv::EVENT_FLAG_MBUTTON)
95  {
96  cam_dist += cam_dist * dy * 0.003;
97  }
98  else if (flags & cv::EVENT_FLAG_RBUTTON)
99  {
100  cam_lookat += cam_pose.R * (geo::Vector3(-dx, dy, 0) * 0.001 * cam_dist);
101  }
102 
103  LAST_MOUSE_POS = cv::Point(x, y);
104  }
105 }
106 
107 // ----------------------------------------------------------------------------------------------------
108 
109 int main(int argc, char **argv)
110 {
111  if (argc != 3)
112  {
113  usage();
114  return 1;
115  }
116 
117  std::string load_type_str = argv[1];
118  ed::models::LoadType load_type;
119  if (load_type_str == "--model")
120  load_type = ed::models::LoadType::MODEL;
121  else if (load_type_str == "--file")
122  load_type = ed::models::LoadType::FILE;
123  else
124  {
125  std::cerr << "Load type should either be --model or --file" << std::endl;
126  usage();
127  return 1;
128  }
129  std::string source = argv[2];
130 
131  ed::UpdateRequest req;
132  if (!ed::models::loadModel(load_type, source, req))
133  return 1;
134 
135  // Create world
136  ed::WorldModel world_model;
137  world_model.update(req);
138 
139  // Set camera specs
141  0.87 * CANVAS_WIDTH, 0.87 * CANVAS_WIDTH,
142  CANVAS_WIDTH / 2 + 0.5, CANVAS_HEIGHT / 2 + 0.5,
143  0, 0);
144 
145  // Determine min and max coordinates of model
146  geo::Vector3 p_min(1e9, 1e9, 1e9);
147  geo::Vector3 p_max(-1e9, -1e9, -1e9);
148 
149  int n_vertices = 0;
150  int n_triangles = 0;
151 
152  for(ed::WorldModel::const_iterator it = world_model.begin(); it != world_model.end(); ++it)
153  {
154  const ed::EntityConstPtr& e = *it;
155 
156  if (e->visual())
157  {
158  const std::string& id = e->id().str();
159  if (id.size() < 5 || id.substr(id.size() - 5) != "floor") // Filter ground plane
160  {
161  const std::vector<geo::Vector3>& vertices = e->visual()->getMesh().getPoints();
162  for(unsigned int i = 0; i < vertices.size(); ++i)
163  {
164  const geo::Vector3& p = e->pose() * vertices[i];
165  p_min.x = std::min(p.x, p_min.x);
166  p_min.y = std::min(p.y, p_min.y);
167  p_min.z = std::min(p.z, p_min.z);
168 
169  p_max.x = std::max(p.x, p_max.x);
170  p_max.y = std::max(p.y, p_max.y);
171  p_max.z = std::max(p.z, p_max.z);
172  }
173  }
174 
175  n_vertices += e->visual()->getMesh().getPoints().size();
176  n_triangles += e->visual()->getMesh().getTriangleIs().size();
177  }
178  }
179 
180  double dist = 2 * std::max(p_max.z - p_min.z, std::max(p_max.x - p_min.x, p_max.y - p_min.y));
181 
182  std::stringstream info_msg;
183  info_msg << "Model loaded successfully:" << std::endl;
184  info_msg << " " << n_vertices << " vertices" << std::endl;
185  info_msg << " " << n_triangles << " triangles" << std::endl;
186  info_msg << " " << "x: [" << p_min.x << " - " << p_max.x << "]" << std::endl;
187  info_msg << " " << "y: [" << p_min.y << " - " << p_max.y << "]" << std::endl;
188  info_msg << " " << "z: [" << p_min.z << " - " << p_max.z << "]" << std::endl;
189 
190  info_msg << std::endl;
191  info_msg << "Mouse:" << std::endl;
192  info_msg << " left - orbit" << std::endl;
193  info_msg << " middle - zoom" << std::endl;
194  info_msg << " right - pan" << std::endl;
195  info_msg << " double click - fly to" << std::endl;
196 
197  info_msg << std::endl;
198  info_msg << "Keys:" << std::endl;
199  info_msg << " r - reload model" << std::endl;
200  info_msg << " v - hide all volumes, show model volumes, show room volumes" << std::endl;
201  info_msg << " c - circle rotate" << std::endl;
202  info_msg << " p - snap pitch" << std::endl;
203  info_msg << " q - quit" << std::endl;
204 
205  std::cout << info_msg.str();
206 
207  ed::ShowVolumes show_volumes = ed::ModelVolumes;
208 
209  cam_dist = dist;
210  cam_lookat = (p_min + p_max) / 2;
211  cam_yaw = 0;
212  cam_pitch = 0.7;
213 
214  //Create a window
215  cv::namedWindow("visualization", 1);
216 
217  //set the callback function for any mouse event
218  cv::setMouseCallback("visualization", CallBackFunc, NULL);
219 
220  while (true)
221  {
222  const geo::Pose3D old_cam_pose = cam_pose;
223  cam_pose.t = geo::Vector3(cos(cam_yaw), sin(cam_yaw), 0) * cos(cam_pitch) * cam_dist;
224  cam_pose.t.z = sin(cam_pitch) * cam_dist;
225  cam_pose.t += cam_lookat;
226 
227  geo::Vector3 rz = -(cam_lookat - cam_pose.t).normalized();
228  geo::Vector3 rx = geo::Vector3(0, 0, 1).cross(rz).normalized();
229  geo::Vector3 ry = rz.cross(rx).normalized();
230 
231  cam_pose.R = geo::Matrix3(rx, ry, rz);
232 
233  if (!render_required && old_cam_pose != cam_pose)
234  {
235  render_required = true;
236  }
237 
238  if (render_required)
239  {
240  depth_image = cv::Mat(CANVAS_HEIGHT, CANVAS_WIDTH, CV_32FC1, 0.0);
241  image = cv::Mat(depth_image.rows, depth_image.cols, CV_8UC3, cv::Scalar(20, 20, 20)); // Not completely black
242  ed::renderWorldModel(world_model, show_volumes, cam, cam_pose.inverse(), depth_image, image);
243  render_required = false;
244  }
245 
246  cv::imshow("visualization", image);
247  char key = cv::waitKey(10);
248 
249  if (key == 'r')
250  {
251  ed::UpdateRequest req;
252  if (ed::models::loadModel(load_type, source, req))
253  {
254  world_model = ed::WorldModel();
255  world_model.update(req);
256  }
257  render_required = true;
258  }
259  else if (key == 'v')
260  {
261  show_volumes = ed::ShowVolumes((show_volumes + 1) % 3);
262  render_required = true;
263  }
264  else if (key == 'q')
265  {
266  break;
267  }
268  else if (key == 'c')
269  {
270  do_rotate = !do_rotate;
271  }
272  else if (key == 'p')
273  {
274  // Snap pitch to 90 degrees
275  if (cam_pitch < M_PI_2)
276  cam_pitch = std::round(cam_pitch / M_PI_2 + 0.51) * M_PI_2;
277  else
278  cam_pitch = std::round(cam_pitch / M_PI_2 - 0.51) * M_PI_2;
279 
280  render_required = true;
281  }
282 
283  if (do_rotate)
284  {
285  cam_yaw += 0.03;
286  render_required = true;
287  }
288 
289  if (do_flyto)
290  {
292  double dist = diff.length();
293 
294  double max_dist = std::max(0.001 * cam_dist, dist * 0.1);
295  if (dist < max_dist)
296  {
298  do_flyto = false;
299  }
300  else
301  {
302  cam_lookat += (diff / dist) * max_dist;
303  }
304  }
305  }
306 
307  return 0;
308 }
geo::Vector3::y
const real & y() const
geo::Vector3
Vec3 Vector3
ed::WorldModel
Definition: world_model.h:21
ed::UpdateRequest
Definition: update_request.h:24
fstream
std::string
DepthCamera.h
cam_yaw
double cam_yaw
Definition: view_model.cpp:31
entity.h
std::vector< geo::Vector3 >
std::vector::size
T size(T... args)
cam
geo::DepthCamera cam
Definition: view_model.cpp:28
Shape.h
std::stringstream
main
int main(int argc, char **argv)
Definition: view_model.cpp:109
ed::renderWorldModel
bool renderWorldModel(const ed::WorldModel &world_model, const enum ShowVolumes show_volumes, const geo::DepthCamera &cam, const geo::Pose3D &cam_pose_inv, cv::Mat &depth_image, cv::Mat &image, bool flatten=false)
renderWorldModel renders a world model on a depth image and a colored (3D) image
Definition: rendering.cpp:128
reader.h
CallBackFunc
void CallBackFunc(int event, int x, int y, int flags, void *)
Definition: view_model.cpp:53
std::cerr
geo::Transform3T
CANVAS_WIDTH
constexpr double CANVAS_WIDTH
Definition: view_model.cpp:25
usage
void usage()
Definition: view_model.cpp:46
do_rotate
bool do_rotate
Definition: view_model.cpp:33
rendering.h
ed::ShowVolumes
ShowVolumes
The ShowVolumes enum indicates which volumes to render.
Definition: rendering.h:23
ed::WorldModel::update
void update(const UpdateRequest &req)
Definition: world_model.cpp:23
ed::WorldModel::begin
const_iterator begin() const
Definition: world_model.h:68
ed::EntityConstPtr
shared_ptr< const Entity > EntityConstPtr
Definition: types.h:37
ed::WorldModel::end
const_iterator end() const
Definition: world_model.h:70
image
cv::Mat image
Definition: view_model.cpp:42
std::cout
geo::Transform3T::inverse
Transform3T inverse() const
update_request.h
do_flyto
bool do_flyto
Definition: view_model.cpp:36
sdf.h
reader_writer.h
ed::models::LoadType
LoadType
The LoadType enum indicates whether to load directly from a file or from a model that is part of the ...
Definition: model_loader.h:148
render_required
bool render_required
Definition: view_model.cpp:39
geo::Transform3T::t
Vec3T< T > t
geo::Vec3T::cross
Vec3T cross(const Vec3T &v) const
geo::Vector3
cam_pose
geo::Pose3D cam_pose
Definition: view_model.cpp:34
yaml.h
geo::DepthCamera::project2Dto3D
geo::Vec3T< T > project2Dto3D(int x, int y) const
ed::WorldModel::EntityIterator
Definition: world_model.h:26
cam_dist
double cam_dist
Definition: view_model.cpp:31
geo::Vector3::z
const real & z() const
CANVAS_HEIGHT
constexpr double CANVAS_HEIGHT
Definition: view_model.cpp:26
std::min
T min(T... args)
std::round
T round(T... args)
path.h
std::endl
T endl(T... args)
diff
IMETHOD Twist diff(const Frame &F_a_b1, const Frame &F_a_b2, double dt=1)
geo::Vec3T::normalized
Vec3T normalized() const
geo::Transform3T::R
Mat3T< T > R
cam_lookat_flyto
geo::Vector3 cam_lookat_flyto
Definition: view_model.cpp:37
geo::Vector3::x
const real & x() const
ed::models::MODEL
@ MODEL
Definition: shape_loader_private.h:27
geo::Vec3T::z
T z
geo::DepthCamera
std::stringstream::str
T str(T... args)
Box.h
cam_lookat
geo::Vector3 cam_lookat
Definition: view_model.cpp:30
ed::models::FILE
@ FILE
Definition: shape_loader_private.h:28
ed::ModelVolumes
@ ModelVolumes
Definition: rendering.h:26
cam_pitch
double cam_pitch
Definition: view_model.cpp:31
std::max
T max(T... args)
geo::Matrix3
Mat3 Matrix3
ed::models::loadModel
bool loadModel(const LoadType load_type, const std::string &source, ed::UpdateRequest &req)
loadModel loads an ED model from file
Definition: load_model.cpp:21
LAST_MOUSE_POS
cv::Point LAST_MOUSE_POS
Definition: view_model.cpp:32
xml.h
depth_image
cv::Mat depth_image
Definition: view_model.cpp:41
model_loader.h
world_model.h