1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215
|
import os
import sys
import pkgutil
import inspect
import subprocess
try:
import bpy # Blender
except ImportError:
print("Could not import bpy, run with Blender\n"
"blender -P components_exhibit.py")
sys.exit(-1)
from mathutils import Euler
def ext_exec(cmd, python=None):
if not python:
python = 'python%i.%i'%(sys.version_info.major, sys.version_info.minor)
return subprocess.getoutput('%s -c"%s"' % (python, cmd) )
def fix_python_path(python=None):
pythonpath = ext_exec("import os,sys;print(os.pathsep.join(sys.path))")
sys.path.extend(pythonpath.split(os.pathsep))
fix_python_path()
try:
import morse # MORSE
except ImportError:
raise ImportError("Could not import morse, set your PYTHONPATH\n"
'export PYTHONPATH="/usr/local/lib/python3.3/site-packages/:$PYTHONPATH"')
from morse.builder import *
#
# helpers
#
def get_classes_from_module(module_name):
__import__(module_name)
# Predicate to make sure the classes only come from the module in question
def predicate(member):
return inspect.isclass(member) and member.__module__.startswith(module_name)
# fetch all members of module name matching 'pred'
return inspect.getmembers(sys.modules[module_name], predicate)
def get_submodules(module_name):
""" Get a list of submodules from a module name.
Not recursive, don't return nor look in subpackages """
__import__(module_name)
module = sys.modules[module_name]
module_path = getattr(module, '__path__')
return [name for _, name, ispkg in pkgutil.iter_modules(module_path) if not ispkg]
def get_subclasses(module_name, skip_submodules=[]):
subclasses = []
submodules = get_submodules(module_name)
for submodule_name in submodules:
if submodule_name in skip_submodules:
pass
submodule = "%s.%s"%(module_name, submodule_name)
try:
submodule_classes = get_classes_from_module(submodule)
for _, klass in submodule_classes:
subclasses.append(klass)
except Exception:
# can not import some resources
pass
return subclasses
modules = [
"morse.builder.sensors",
"morse.builder.actuators",
"morse.builder.robots",
]
specific_camera_pose_per_component = {
# Robots
'BasePR2': (.36, -2.25, 1.77),
'Morsy': (3.84, -3.12, 2.12, 1.32, 0.0, 0.86),
'SegwayRMP400': (.36, -2.25, 1.77),
'ATRV': (.36, -2.25, 1.77),
'Human': (4, 0, 2.8), # 65°,0,90°
'Hummer': (.36, -2.25, 1.77),
'Jido': (.36, -2.25, 1.77),
'B21': (.36, -2.25, 1.77),
'RMax': (.36, -2.25, 1.77),
'Submarine': (.36, -2.25, 1.77),
'Vicitm': (.36, -2.25, 1.77),
'NavPR2': (.36, -2.25, 1.77),
'QUAD2012': (.36, -1.25, .77),
'Quadrotor': (.36, -1.25, .77),
'Pioneer3DX': (.36, -1.25, .77),
# Sensors
'Accelerometer': (.36, -1.25, .77),
'Battery': (.36, -1.25, .77),
'DepthCamera': (.36, -1.25, .77),
'GPS': (.36, -1.25, .77),
'Gyroscope': (.36, -1.25, .77),
'Hokuyo': (.36, -1.25, .77),
'IMU': (.36, -1.25, .77),
'Infrared': (.36, -1.25, .77),
'Kinect': (.36, -1.25, .77),
'Odometry': (.36, -1.25, .77),
'Pose': (.36, -1.25, .77),
'Proximity': (.36, -1.25, .77),
'SearchAndRescue': (.36, -1.25, .77),
'SemanticCamera': (.36, -1.25, .77),
'Sick': (.36, -1.25, .77),
'SickLDMRS': (.36, -1.25, .77),
'StereoUnit': (.36, -1.25, .77),
'Thermometer': (.36, -1.25, .77),
'VideoCamera': (.36, -1.25, .77),
'Velodyne': (.36, -1.25, .77),
# Actuators
'PTU': (.36, -1.25, .77),
'PA10': (.36, -2.25, 1.77),
'KukaLWR': (.36, -2.25, 1.77),
'Gripper': (.36, -1.25, .77),
}
def pose_camera(location = (.36, -1.25, .77), rotation = (1.1, 0, 0.25)):
if len(location) == 6:
rotation = location[3:]
location = location[:3]
scene = bpy.context.scene
scene.camera.rotation_euler = Euler(rotation, 'XYZ')
scene.camera.location = location
def setup_scene():
scene = bpy.context.scene
if 'Cube' in bpy.data.objects:
bpymorse.delete('Cube')
# Set the scene's camera
scene.camera = bpy.data.objects['Camera']
# Set the scene's output file format
scene.render.image_settings.file_format = 'PNG'
# RGBA, Images are saved with RGB and Alpha data (if supported).
scene.render.image_settings.color_mode = 'RGBA'
if bpy.app.version < (2, 66, 0):
# Premultiplied, Transparent RGB pixels are multiplied by the alpha channel.
scene.render.alpha_mode = 'PREMUL'
else:
# Transparent, World background is transparent with premultiplied alpha.
scene.render.alpha_mode = 'TRANSPARENT'
# Move the default Lamp
bpy.data.objects['Lamp'].location = (-2, 3, 6)
if len(bpy.data.lamps) < 3:
# Add new lamp point
bpy.ops.object.lamp_add(type='POINT', location=(5, 2, 1))
bpy.data.lamps[-1].energy = 0.6
bpy.ops.object.lamp_add(type='POINT', location=(-4, 3, 4))
bpy.data.lamps[-1].energy = 0.4
# Move the default Camera
pose_camera()
def render_component(klass, save_path):
scene = bpy.context.scene
class_name = klass.__name__
if class_name in specific_camera_pose_per_component:
pose_camera(specific_camera_pose_per_component[class_name])
else:
print("#### class not in dict: %s"%str(class_name))
pose_camera()
origin_objects = [obj.name for obj in bpy.data.objects]
try:
# load class
component = klass()
# Refresh the view
bpy.ops.wm.redraw_timer(type='DRAW_WIN_SWAP', iterations=1)
# Render the scene
scene.render.filepath = os.path.join(save_path, klass.__name__ + ".png")
bpy.ops.render.render(write_still=True)
except Exception as e:
print("[ERROR] Could not load %s.\nSet MORSE_ROOT to the prefix " \
"used to install MORSE.\n%s"% (str(klass), str(e) ) )
finally:
# Remove the inserted objects
bpymorse.delete([obj for obj in bpy.data.objects \
if obj.name not in origin_objects])
def main():
""" Generate "studio" image of MORSE components
HOWTO
export PYTHONPATH="/usr/local/lib/python3.3/site-packages/:$PYTHONPATH"
blender -P components_exhibit.py
Et voila!
"""
print ("==== PHOTO STUDIO FOR MORSE COMPONENTS ====\n\n")
save_path = "//morse_renders"
scene = bpy.context.scene
print('Using Scene[%s]'%scene.name)
setup_scene()
# browse morse components modules
for module in modules:
print("browse %s classes"%module)
for _, klass in get_classes_from_module(module):
print("process %s"%str(klass))
if issubclass(klass, AbstractComponent):
try:
render_component(klass, save_path)
except Exception as e:
print("[ERROR] Could not render %s : %s"%(str(klass), str(e)))
else:
print("[ERROR] Not a Component : %s"%str(klass))
print("\n\n")
print ("DONE!")
if __name__ == '__main__':
main()
|