00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #include <moveit/mesh_filter/mesh_filter_base.h>
00038 #include <moveit/mesh_filter/gl_mesh.h>
00039 #include <moveit/mesh_filter/filter_job.h>
00040
00041 #include <geometric_shapes/shapes.h>
00042 #include <geometric_shapes/shape_operations.h>
00043 #include <Eigen/Eigen>
00044 #include <stdexcept>
00045 #include <sstream>
00046 #include <sensor_msgs/image_encodings.h>
00047
00048 #include <ros/console.h>
00049
00050
00051 #ifdef HAVE_SSE_EXTENSIONS
00052 #include <xmmintrin.h>
00053 #endif
00054
00055 using std::string;
00056 using namespace Eigen;
00057 using shapes::Mesh;
00058 using boost::shared_ptr;
00059 using boost::unique_lock;
00060 using boost::mutex;
00061
00062 mesh_filter::MeshFilterBase::MeshFilterBase (const TransformCallback& transform_callback,
00063 const SensorModel::Parameters& sensor_parameters,
00064 const string& render_vertex_shader, const string& render_fragment_shader,
00065 const string& filter_vertex_shader, const string& filter_fragment_shader)
00066 : sensor_parameters_ (sensor_parameters.clone ())
00067 , next_handle_ (FirstLabel)
00068 , min_handle_ (FirstLabel)
00069 , stop_ (false)
00070 , transform_callback_ (transform_callback)
00071 , padding_scale_ (1.0)
00072 , padding_offset_ (0.01)
00073 , shadow_threshold_ (0.5)
00074 {
00075 using boost::thread;
00076 filter_thread_ = thread (boost::bind(&MeshFilterBase::run, this,
00077 render_vertex_shader, render_fragment_shader, filter_vertex_shader, filter_fragment_shader));
00078 }
00079
00080 void mesh_filter::MeshFilterBase::initialize (const string& render_vertex_shader, const string& render_fragment_shader,
00081 const string& filter_vertex_shader, const string& filter_fragment_shader)
00082 {
00083 mesh_renderer_.reset (new GLRenderer (sensor_parameters_->getWidth(), sensor_parameters_->getHeight(),
00084 sensor_parameters_->getNearClippingPlaneDistance (),
00085 sensor_parameters_->getFarClippingPlaneDistance ()));
00086 depth_filter_.reset (new GLRenderer (sensor_parameters_->getWidth(), sensor_parameters_->getHeight(),
00087 sensor_parameters_->getNearClippingPlaneDistance (),
00088 sensor_parameters_->getFarClippingPlaneDistance ()));
00089
00090 mesh_renderer_->setShadersFromString (render_vertex_shader, render_fragment_shader);
00091 depth_filter_->setShadersFromString (filter_vertex_shader, filter_fragment_shader);
00092
00093 depth_filter_->begin ();
00094
00095 glGenTextures (1, &sensor_depth_texture_);
00096
00097 glUniform1i (glGetUniformLocation (depth_filter_->getProgramID (), "sensor"), 0);
00098 glUniform1i (glGetUniformLocation (depth_filter_->getProgramID (), "depth"), 2);
00099 glUniform1i (glGetUniformLocation (depth_filter_->getProgramID (), "label"), 4);
00100
00101 shadow_threshold_location_ = glGetUniformLocation (depth_filter_->getProgramID (), "shadow_threshold");
00102
00103 depth_filter_->end ();
00104
00105 canvas_ = glGenLists (1);
00106 glNewList (canvas_, GL_COMPILE);
00107 glBegin (GL_QUADS);
00108
00109 glColor3f (1, 1, 1);
00110 glTexCoord2f (0, 0);
00111 glVertex3f (-1, -1, 1);
00112
00113 glTexCoord2f (1, 0);
00114 glVertex3f (1, -1, 1);
00115
00116 glTexCoord2f ( 1, 1);
00117 glVertex3f (1, 1, 1);
00118
00119 glTexCoord2f ( 0, 1);
00120 glVertex3f (-1, 1, 1);
00121
00122 glEnd ();
00123 glEndList ();
00124 }
00125
00126 mesh_filter::MeshFilterBase::~MeshFilterBase ()
00127 {
00128 {
00129 unique_lock<mutex> lock (jobs_mutex_);
00130 stop_ = true;
00131 while (!jobs_queue_.empty())
00132 {
00133 jobs_queue_.front ()->cancel ();
00134 jobs_queue_.pop();
00135 }
00136 }
00137 jobs_condition_.notify_one ();
00138 filter_thread_.join();
00139 }
00140
00141 void mesh_filter::MeshFilterBase::addJob (const boost::shared_ptr<Job> &job) const
00142 {
00143 {
00144 unique_lock<mutex> _(jobs_mutex_);
00145 jobs_queue_.push (job);
00146 }
00147 jobs_condition_.notify_one();
00148 }
00149
00150 void mesh_filter::MeshFilterBase::deInitialize ()
00151 {
00152 glDeleteLists (canvas_, 1);
00153 glDeleteTextures (1, &sensor_depth_texture_);
00154
00155 meshes_.clear ();
00156 mesh_renderer_.reset();
00157 depth_filter_.reset();
00158 }
00159
00160 void mesh_filter::MeshFilterBase::setSize (unsigned int width, unsigned int height)
00161 {
00162 mesh_renderer_->setBufferSize (width, height);
00163 mesh_renderer_->setCameraParameters (width, width, width >> 1, height >> 1);
00164
00165 depth_filter_->setBufferSize (width, height);
00166 depth_filter_->setCameraParameters (width, width, width >> 1, height >> 1);
00167 }
00168
00169 void mesh_filter::MeshFilterBase::setTransformCallback (const TransformCallback& transform_callback)
00170 {
00171 mutex::scoped_lock _(transform_callback_mutex_);
00172 transform_callback_ = transform_callback;
00173 }
00174
00175 mesh_filter::MeshHandle mesh_filter::MeshFilterBase::addMesh (const Mesh& mesh)
00176 {
00177 mutex::scoped_lock _(meshes_mutex_);
00178
00179 shared_ptr<Job> job (new FilterJob<void> (boost::bind (&MeshFilterBase::addMeshHelper, this, next_handle_, &mesh)));
00180 addJob(job);
00181 job->wait ();
00182 mesh_filter::MeshHandle ret = next_handle_;
00183 const std::size_t sz = min_handle_ + meshes_.size() + 1;
00184 for (std::size_t i = min_handle_ ; i < sz ; ++i)
00185 if (meshes_.find(i) == meshes_.end())
00186 {
00187 next_handle_ = i;
00188 break;
00189 }
00190 min_handle_ = next_handle_;
00191 return ret;
00192 }
00193
00194 void mesh_filter::MeshFilterBase::addMeshHelper (MeshHandle handle, const Mesh *cmesh)
00195 {
00196 meshes_[handle] = shared_ptr<GLMesh> (new GLMesh (*cmesh, handle));
00197 }
00198
00199 void mesh_filter::MeshFilterBase::removeMesh (MeshHandle handle)
00200 {
00201 mutex::scoped_lock _(meshes_mutex_);
00202 FilterJob<bool>* remover = new FilterJob<bool> (boost::bind (&MeshFilterBase::removeMeshHelper, this, handle));
00203 shared_ptr<Job> job (remover);
00204 addJob(job);
00205 job->wait ();
00206
00207 if (!remover->getResult ())
00208 throw std::runtime_error ("Could not remove mesh. Mesh not found!");
00209 min_handle_ = std::min(handle, min_handle_);
00210 }
00211
00212 bool mesh_filter::MeshFilterBase::removeMeshHelper (MeshHandle handle)
00213 {
00214 std::size_t erased = meshes_.erase (handle);
00215 return (erased != 0);
00216 }
00217
00218 void mesh_filter::MeshFilterBase::setShadowThreshold (float threshold)
00219 {
00220 shadow_threshold_ = threshold;
00221 }
00222
00223 void mesh_filter::MeshFilterBase::getModelLabels (LabelType* labels) const
00224 {
00225 shared_ptr<Job> job (new FilterJob<void> (boost::bind (&GLRenderer::getColorBuffer, mesh_renderer_.get(), (unsigned char*) labels)));
00226 addJob(job);
00227 job->wait ();
00228 }
00229
00230 void mesh_filter::MeshFilterBase::getModelDepth (float* depth) const
00231 {
00232 shared_ptr<Job> job1 (new FilterJob<void> (boost::bind (&GLRenderer::getDepthBuffer, mesh_renderer_.get(), depth)));
00233 shared_ptr<Job> job2 (new FilterJob<void> (boost::bind (&SensorModel::Parameters::transformModelDepthToMetricDepth, sensor_parameters_.get(), depth)));
00234 {
00235 unique_lock<mutex> lock (jobs_mutex_);
00236 jobs_queue_.push (job1);
00237 jobs_queue_.push (job2);
00238 }
00239 jobs_condition_.notify_one();
00240 job1->wait ();
00241 job2->wait ();
00242 }
00243
00244 void mesh_filter::MeshFilterBase::getFilteredDepth (float* depth) const
00245 {
00246 shared_ptr<Job> job1 (new FilterJob<void> (boost::bind (&GLRenderer::getDepthBuffer, depth_filter_.get(), depth)));
00247 shared_ptr<Job> job2 (new FilterJob<void> (boost::bind (&SensorModel::Parameters::transformFilteredDepthToMetricDepth, sensor_parameters_.get(), depth)));
00248 {
00249 unique_lock<mutex> lock (jobs_mutex_);
00250 jobs_queue_.push (job1);
00251 jobs_queue_.push (job2);
00252 }
00253 jobs_condition_.notify_one();
00254 job1->wait ();
00255 job2->wait ();
00256 }
00257
00258 void mesh_filter::MeshFilterBase::getFilteredLabels (LabelType* labels) const
00259 {
00260 shared_ptr<Job> job (new FilterJob<void> (boost::bind (&GLRenderer::getColorBuffer, depth_filter_.get(), (unsigned char*) labels)));
00261 addJob(job);
00262 job->wait ();
00263 }
00264
00265 void mesh_filter::MeshFilterBase::run (const string& render_vertex_shader, const string& render_fragment_shader,
00266 const string& filter_vertex_shader, const string& filter_fragment_shader)
00267 {
00268 initialize (render_vertex_shader, render_fragment_shader, filter_vertex_shader, filter_fragment_shader);
00269
00270 while (!stop_)
00271 {
00272
00273 unique_lock<mutex> lock (jobs_mutex_);
00274
00275 if (jobs_queue_.empty ())
00276 jobs_condition_.wait (lock);
00277
00278 if (!jobs_queue_.empty ())
00279 {
00280 shared_ptr<Job> job = jobs_queue_.front ();
00281 jobs_queue_.pop ();
00282 lock.unlock ();
00283 job->execute ();
00284 lock.lock ();
00285 }
00286 }
00287 deInitialize ();
00288 }
00289
00290 void mesh_filter::MeshFilterBase::filter (const void* sensor_data, GLushort type, bool wait) const
00291 {
00292 if (type != GL_FLOAT && type != GL_UNSIGNED_SHORT)
00293 {
00294 std::stringstream msg;
00295 msg << "unknown type \"" << type << "\". Allowed values are GL_FLOAT or GL_UNSIGNED_SHORT.";
00296 throw std::runtime_error (msg.str ());
00297 }
00298
00299 shared_ptr<Job> job (new FilterJob<void> (boost::bind (&MeshFilterBase::doFilter, this, sensor_data, type)));
00300 addJob(job);
00301 if (wait)
00302 job->wait ();
00303 }
00304
00305 void mesh_filter::MeshFilterBase::doFilter (const void* sensor_data, const int encoding) const
00306 {
00307 mutex::scoped_lock _(transform_callback_mutex_);
00308
00309 mesh_renderer_->begin ();
00310 sensor_parameters_->setRenderParameters (*mesh_renderer_);
00311
00312 glEnable (GL_TEXTURE_2D);
00313 glEnable (GL_DEPTH_TEST);
00314 glDepthFunc(GL_LESS);
00315 glEnable (GL_CULL_FACE);
00316 glCullFace (GL_FRONT);
00317 glDisable (GL_ALPHA_TEST);
00318 glDisable (GL_BLEND);
00319
00320 GLuint padding_coefficients_id = glGetUniformLocation (mesh_renderer_->getProgramID (), "padding_coefficients");
00321 Eigen::Vector3f padding_coefficients = sensor_parameters_->getPaddingCoefficients () * padding_scale_ + Eigen::Vector3f (0, 0, padding_offset_);
00322 glUniform3f (padding_coefficients_id, padding_coefficients [0], padding_coefficients [1], padding_coefficients [2]);
00323
00324 Affine3d transform;
00325 for (std::map<MeshHandle, shared_ptr<GLMesh> >::const_iterator meshIt = meshes_.begin (); meshIt != meshes_.end (); ++meshIt)
00326 if (transform_callback_ (meshIt->first, transform))
00327 meshIt->second->render (transform);
00328
00329 mesh_renderer_->end ();
00330
00331
00332
00333
00334 depth_filter_->begin ();
00335 sensor_parameters_->setFilterParameters (*depth_filter_);
00336 glEnable (GL_TEXTURE_2D);
00337 glEnable (GL_DEPTH_TEST);
00338 glDepthFunc(GL_ALWAYS);
00339 glDisable (GL_CULL_FACE);
00340 glDisable (GL_ALPHA_TEST);
00341 glDisable (GL_BLEND);
00342
00343
00344
00345 glUniform1f (shadow_threshold_location_, shadow_threshold_);
00346
00347 GLuint depth_texture = mesh_renderer_->getDepthTexture ();
00348 GLuint color_texture = mesh_renderer_->getColorTexture ();
00349
00350
00351 glActiveTexture (GL_TEXTURE0);
00352 glBindTexture ( GL_TEXTURE_2D, sensor_depth_texture_ );
00353
00354 float scale = 1.0 / (sensor_parameters_->getFarClippingPlaneDistance () - sensor_parameters_->getNearClippingPlaneDistance ());
00355
00356 if (encoding == GL_UNSIGNED_SHORT)
00357
00358
00359
00360
00361 glPixelTransferf (GL_DEPTH_SCALE, scale * 65.535);
00362 else
00363 glPixelTransferf (GL_DEPTH_SCALE, scale);
00364 glPixelTransferf (GL_DEPTH_BIAS, -scale * sensor_parameters_->getNearClippingPlaneDistance ());
00365
00366 glTexImage2D ( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, sensor_parameters_->getWidth (), sensor_parameters_->getHeight (), 0, GL_DEPTH_COMPONENT, encoding, sensor_data);
00367 glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
00368 glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
00369 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
00370 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
00371
00372
00373 glActiveTexture (GL_TEXTURE2);
00374 glBindTexture (GL_TEXTURE_2D, depth_texture);
00375
00376
00377 glActiveTexture (GL_TEXTURE4);
00378 glBindTexture (GL_TEXTURE_2D, color_texture);
00379 glCallList (canvas_);
00380 depth_filter_->end ();
00381 }
00382
00383 void mesh_filter::MeshFilterBase::setPaddingOffset (float offset)
00384 {
00385 padding_offset_ = offset;
00386 }
00387
00388 void mesh_filter::MeshFilterBase::setPaddingScale (float scale)
00389 {
00390 padding_scale_ = scale;
00391 }