ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange
Ask Your Question
1

Receiving Meshes via ROS in Python

asked 2019-08-06 09:40:05 -0500

Jägermeister gravatar image

updated 2019-08-07 03:58:01 -0500

I am using Voxblox_ros(https://github.com/ethz-asl/voxblox) which is a real-time mesh generator, and it saves a .ply file under a folder.

What I want to achieve is to read the mesh that is saved under that folder. I've looked it up and found that there is a message type called shape_msgs/Mesh, which sounded like something I could use. However, I am having question marks in my head about how exactly to fill in the data to this message.

I created a msg (MeshInfo.msg):

string mesh_id
shape_msgs/Mesh part_mesh

and a srv(MeshArray.srv):

---
MeshInfo[] mesh_array

which I refer in the code as:

self.mesh_srv = rospy.Service("voxblox_ros/generate_mesh", MeshArray, self.mesh_processor_srv) # get the mesh

I've come up with this kind of code which I have not tested yet, just wanted to illustrate what I have in mind:

 def mesh_processor_srv(self, req):
        # this service does not return anything by itself, it only saves the mesh to the designated folder
        # so, one must implement a mechanism here to import the mesh which is saved in that folder
        rospy.wait_for_service('voxblox_ros/generate_mesh')
        MeshArrayResponse = rospy.ServiceProxy('voxblox_ros/generate_mesh', MeshArray)

        # navigate to voxblox_ros package, under mesh_results, there should be mesh file stored as .ply
        files = os.listdir(home + "/ros_ws/src/voxblox/voxblox_ros/mesh_results/") # get the mesh files
        meshlist = [] # to keep the meshes in

        # loop over each mesh, import and create our mesh object
        for i in range(len(files)):
            mesh = MeshInfo()
            mesh.mesh_id = "mesh_" + os.path.splitext(os.path.basename(files[i]))[0]  # get the mesh name from the file
            mesh.part_mesh = PlyData.read(home + "/ros_ws/src/voxblox/voxblox_ros/mesh_results/" + files[i]) # get the mesh data
            meshlist.append(mesh)

        response = MeshArrayResponse()
        response.mesh_array = meshlist
        return response

which I am not sure of. Did someone have similar task and had somehow figured out how to crack?

edit retag flag offensive close merge delete

2 Answers

Sort by » oldest newest most voted
0

answered 2019-08-06 10:53:08 -0500

aPonza gravatar image

updated 2019-08-06 11:01:27 -0500

A solution using existing things could be to read the .ply into a pcl::PolygonMesh (see this or this) and then convert it like it's done here.

Another solution, since the message already exists, would be to copy the triangles into the shape_msgs::Mesh. Iirc a better idea, which I've used before, is assimp, not sure if it can load .ply meshes, but if it can, the package geometric_shapes comes to the rescue with its geometric_shapes::createMeshFromResource. Edit2: I was missing a piece in the explanation: shapes::constructMsgFromShape converts the Mesh* to a variant of shape_msgs::Mesh. The code would be almost the same as in q245995.

Edit1: ply seems supported as per this, it might be worth a try.

edit flag offensive delete link more

Comments

I need a Python solution, therefore I guess the PCL solution is out of option. PCL-Python is a very unstable release that is not working in many ways, and not supported properly. On another look, all these are C++ libraries/packages, or?

Jägermeister gravatar image Jägermeister  ( 2019-08-07 03:57:37 -0500 )edit
1

Everything is C++, you're correct. I didn't think python was a requirement, not sure then...

aPonza gravatar image aPonza  ( 2019-08-07 04:08:38 -0500 )edit

My mistake, included in the title now, thank you though, perhaps your answer can guide those who need a C++ solution to the same problem.

Jägermeister gravatar image Jägermeister  ( 2019-08-07 04:10:15 -0500 )edit
1

answered 2020-05-23 11:22:10 -0500

fvd gravatar image

pyassimp apparently reads 3D file formats like ply and stl, and there is a usage example in the MoveIt planning scene interface that is probably helpful:

 def makeMesh(self, name, pose, filename):
     if not use_pyassimp:
         rospy.logerr('pyassimp is broken on your platform, cannot load meshes')
         return
     scene = pyassimp.load(filename)
     if not scene.meshes:
         rospy.logerr('Unable to load mesh')
         return

     mesh = Mesh()
     for face in scene.meshes[0].faces:
         triangle = MeshTriangle()
         if len(face.indices) == 3:
             triangle.vertex_indices = [face.indices[0],
                                        face.indices[1],
                                        face.indices[2]]
         mesh.triangles.append(triangle)
     for vertex in scene.meshes[0].vertices:
         point = Point()
         point.x = vertex[0]
         point.y = vertex[1]
         point.z = vertex[2]
         mesh.vertices.append(point)
     pyassimp.release(scene)

     o = CollisionObject()
     o.header.stamp = rospy.Time.now()
     o.header.frame_id = self._fixed_frame
     o.id = name
     o.meshes.append(mesh)
     o.mesh_poses.append(pose)
     o.operation = o.ADD
     return o
edit flag offensive delete link more

Question Tools

2 followers

Stats

Asked: 2019-08-06 09:40:05 -0500

Seen: 833 times

Last updated: May 23 '20