Skip to content
Snippets Groups Projects
Commit 63d8dee3 authored by Henrik Lindgren's avatar Henrik Lindgren
Browse files

initial commit

parents
Branches
No related tags found
No related merge requests found
# Robotarm Simulator
Blender scene and export script for creating animations for the Dofbot robotic arm.
## Todo
- [ ] Add/subtract correct offsets to angles to match with Dofbot angles
- [ ] Add constraints to angles
- [ ] Fix mirrored part of claw
File added
import math
import json
import bpy
from bpy_extras.io_utils import ExportHelper
from bpy.props import StringProperty
from bpy.types import Operator
def print(data):
for window in bpy.context.window_manager.windows:
screen = window.screen
for area in screen.areas:
if area.type == 'CONSOLE':
override = {'window': window, 'screen': screen, 'area': area}
bpy.ops.console.scrollback_append(override, text=str(data), type="OUTPUT")
# Alternative way to get animation data
# Takes the keyframes instead of going through frame by frame
def get_animaiton_data(servo_object):
for fcurve in servo_object.animation_data.action.fcurves:
for keyframe_point in fcurve.keyframe_points:
yield keyframe_point.co
SERVO_NAMES = ['bottom_rotation', 'joint_1', 'joint_2', 'joint_3', 'claw_grip', 'claw_rotation']
def get_servo_objects():
return [bpy.data.objects[servo_name] for servo_name in SERVO_NAMES]
def get_moving_angle(servo_name, rot_deg):
if servo_name == 'bottom_rotation':
return rot_deg.z
if servo_name == 'joint_1':
return rot_deg.y
if servo_name == 'joint_2':
return rot_deg.y
if servo_name == 'joint_3':
return rot_deg.y
if servo_name == 'claw_rotation':
return rot_deg.z
if servo_name == 'claw_grip':
return rot_deg.x
def frame2time(frame):
fps = bpy.context.scene.render.fps
return int(frame/fps*1000)
class RotationDegrees:
def __init__(self, euler_rot):
self.x = round(math.degrees(euler_rot.x))
self.y = round(math.degrees(euler_rot.y))
self.z = round(math.degrees(euler_rot.z))
# This method of stepping through frame by frame and looking at the objects matrix_world
# was taken from the below export script by @astronotter
# https://gist.github.com/astronotter/faec735fc5e270df57741705052096ac
def get_servo_data():
frame_range = range(bpy.context.scene.frame_start, bpy.context.scene.frame_end + 1)
for obj in get_servo_objects():
previous_angle = None
for frame in frame_range:
bpy.context.scene.frame_set(frame)
matrix = obj.matrix_world.copy()
# posx, posy, posz = matrix.to_translation()[:]
# scalex, scaley, scalez = matrix.to_scale()[:]
rot_deg = RotationDegrees(matrix.to_euler())
angle = get_moving_angle(obj.name, rot_deg)
if previous_angle == angle:
continue
previous_angle = angle
yield (obj.name, [frame2time(frame), angle])
def calc_servo_data():
servos = {
'bottom_rotation': [],
'joint_1': [],
'joint_2': [],
'joint_3': [],
'claw_rotation': [],
'claw_grip': []
}
for servo_name, servo_data_point in get_servo_data():
servos[servo_name].append(servo_data_point)
return servos
class ExportDofbotAnimation(Operator, ExportHelper):
"""Exports Dofbot animation as json"""
bl_idname = "export_dofbot.json_animation" # important since its how bpy.ops.import_test.some_data is constructed
bl_label = "Export Dofbot Json Animation"
# ExportHelper mixin class uses this
filename_ext = ".json"
filter_glob: StringProperty(
default="*.json",
options={'HIDDEN'},
maxlen=255, # Max internal buffer length, longer would be clamped.
)
def execute(self, context):
servo_data = calc_servo_data()
with open(self.filepath, 'w') as f:
f.write(json.dumps(servo_data))
return {'FINISHED'}
# Only needed if you want to add into a dynamic menu
def menu_func_export(self, context):
self.layout.operator(ExportDofbotAnimation.bl_idname, text="Dofbot Animation Export")
# Register and add to the "file selector" menu (required to use F3 search "Text Export Operator" for quick access).
def register():
bpy.utils.register_class(ExportDofbotAnimation)
bpy.types.TOPBAR_MT_file_export.append(menu_func_export)
def unregister():
bpy.utils.unregister_class(ExportDofbotAnimation)
bpy.types.TOPBAR_MT_file_export.remove(menu_func_export)
if __name__ == "__main__":
register()
# test call
bpy.ops.export_dofbot.json_animation('INVOKE_DEFAULT')
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment