2 "name":
"ROS Gazebo Exporter",
3 "author":
"Dave Niewinski",
6 "location":
"File > Import-Export",
7 "description":
"Export Gazebo",
8 "category":
"Import-Export" 14 from bpy_extras.io_utils
import ExportHelper
15 from bpy.props
import StringProperty
16 import xml.etree.ElementTree
as ET
23 return ET.fromstring(self.
text)
28 <param name="$NAME$_description" command="$(find xacro)/xacro --inorder '$(find $PACKAGE$)/urdf/$NAME$.urdf.xacro'" /> 30 <node name="spawn_$NAME$" pkg="gazebo_ros" type="spawn_model" args="-param $NAME$_description -urdf -model $NAME$" respawn="false"/> 36 self.
text =
'''<?xml version="1.0"?> 37 <robot name="robot" xmlns:xacro="http://www.ros.org/wiki/xacro"> 38 <link name="$NAME$_link"> 40 <origin xyz="0 0 0" rpy="0 0 0"/> 42 <inertia ixx="1" ixy="0" ixz="0" iyy="1" iyz="0" izz="1"/> 45 <origin xyz="0 0 0" rpy="0 0 0"/> 47 <mesh filename="package://$PACKAGE$/meshes/$VISUAL$"/> 51 <origin xyz="0 0 0" rpy="0 0 0"/> 53 <mesh filename="package://$PACKAGE$/meshes/$COLLISION$"/> 58 <gazebo> <static>true</static></gazebo> 65 <arg name="use_sim_time" default="true" /> 66 <arg name="gui" default="true" /> 67 <arg name="headless" default="false" /> 68 <arg name="world_name" default="$(find blender_gazebo)/worlds/actually_empty_world.world" /> 70 <include file="$(find gazebo_ros)/launch/empty_world.launch"> 71 <arg name="debug" value="0" /> 72 <arg name="gui" value="$(arg gui)" /> 73 <arg name="use_sim_time" value="$(arg use_sim_time)" /> 74 <arg name="headless" value="$(arg headless)" /> 75 <arg name="world_name" value="$(arg world_name)" /> 81 bl_idname =
"object.exportgazebo";
82 bl_label =
"Export Gazebo";
83 bl_options = {
'REGISTER',
'UNDO'};
85 filename_ext =
".launch" 86 filter_glob: StringProperty(default=
"*.launch", options={
'HIDDEN'})
92 if not os.path.exists(dir):
96 (dirname, filename) = os.path.split(launch_file)
97 (shortname, extension) = os.path.splitext(filename)
98 root_dir = os.path.abspath(os.path.join(dirname,
".."))
99 mesh_dir = os.path.join(root_dir,
"meshes/")
100 urdf_dir = os.path.join(root_dir,
"urdf/")
101 launch_dir = os.path.join(root_dir,
"launch/")
102 package_name = root_dir.split(
"/")
103 package_name = package_name[-1]
110 return root_dir, mesh_dir, urdf_dir, launch_dir, package_name, shortname
112 def writeURDF(self, name, package_name, visual, collision, urdf_dir):
115 for c
in body_urdf.findall(
".//mesh"):
116 for k
in c.attrib.keys():
117 c.set(k, c.attrib[k].replace(
"$PACKAGE$", package_name).replace(
"$VISUAL$", visual).replace(
"$COLLISION$", collision))
118 for c
in body_urdf.findall(
"link"):
119 for k
in c.attrib.keys():
120 c.set(k, c.attrib[k].replace(
"$NAME$", name))
122 outFile = open(urdf_dir + name +
".urdf.xacro",
'wb')
123 outFile.write(ET.tostring(body_urdf))
129 for c
in body_launch.findall(
"*"):
130 for k
in c.attrib.keys():
131 c.set(k, c.attrib[k].replace(
"$NAME$", name).replace(
"$PACKAGE$", package_name))
133 outFile = open(launch_dir +
"spawn_" + name +
".launch",
'wb')
134 outFile.write(ET.tostring(body_launch))
138 bpy.ops.object.select_all(action=
'DESELECT')
140 bpy.ops.export_mesh.stl(filepath= dir + name, use_selection=
True, use_mesh_modifiers=
True)
143 bpy.ops.object.select_all(action=
'DESELECT')
145 bpy.ops.wm.collada_export(filepath= dir + name, apply_modifiers=
True, selected=
True)
148 root_dir, mesh_dir, urdf_dir, launch_dir, package_name, prefix = self.
getPackagePaths(self.filepath)
151 for ob
in bpy.data.objects:
152 if ob.type ==
'MESH':
154 print(
"Working on " + ob.name)
155 body_name = prefix +
"_" + ob.name
156 visual_name = body_name +
".dae" 157 self.
exportDAE(ob, visual_name, mesh_dir)
161 collision_file = bpy.data.objects[collision_name]
162 print(
"Found custom collision mesh")
164 self.
exportSTL(collision_file, collision_name, mesh_dir)
166 collision_name = visual_name
168 self.
writeURDF(body_name, package_name, visual_name, collision_name, urdf_dir)
169 self.
writeLaunch(body_name, package_name, launch_dir)
170 world_launch.append(ET.Element(
"include", attrib={
"file":
"$(find " + package_name +
")/launch/spawn_" + body_name +
".launch"}))
172 outFile = open(launch_dir +
"/" + prefix +
".launch",
'wb')
173 outFile.write(ET.tostring(world_launch))
179 self.layout.operator(GazeboExport.bl_idname, text=
"Gazebo Launch (.launch)");
182 bpy.utils.register_class(GazeboExport)
183 bpy.types.TOPBAR_MT_file_export.append(menu_func)
186 bpy.utils.unregister_class(GazeboExport)
187 bpy.types.TOPBAR_MT_file_export.remove(menu_func);
189 if __name__ ==
"__main__" :
def exportDAE(self, ob, name, dir)
def execute(self, context)
def exportSTL(self, ob, name, dir)
def menu_func(self, context)
def writeLaunch(self, name, package_name, launch_dir)
def getPackagePaths(self, launch_file, make_dirs=True)
def writeURDF(self, name, package_name, visual, collision, urdf_dir)