3
$\begingroup$

I'm hoping to 3D print a simple robot controlled by an Arduino microcontroller, but first I am prototyping the design in Blender — I'm experimenting with controls, movements, actions etc. How do I move/rotate part of the robot in Blender — let's say "Robot_Arm_Lower" — to a predefined position? It only needs to be a simple button somewhere that just executes a basic command along the lines of "on button press move 'Robot_Arm_Lower' by rotating xyz and moving to location xyz". I'm guessing I need a simple Python script but I'm not sure where to start.

Hope that makes sense? Thank you.

$\endgroup$
4
$\begingroup$

I put together a small addon for you:

bl_info = {
    "name": "Move & rotate",
    "blender": (2, 80, 0),
    "location": "VIEW_3D > Tools > Move and rotate"
    }

import bpy
from bpy.types import (Panel,Operator,AddonPreferences,PropertyGroup)

xyz_rot = (0,0,0)
xyz_loc = (1,1,1)

class MYADDON_OT_rotate_obj(bpy.types.Operator):
    """rotate the obj"""
    bl_idname = "myops.rotate_obj"
    bl_label = "rotate_obj"

    def execute(self, context):
        #convert degrees to radians
        x = xyz_rot[0]*pi/180
        y = xyz_rot[1]*pi/180
        z = xyz_rot[2]*pi/180
        xyz_rot = (x,y,z)

        #Rotates all the selected objects: if you know the name of the obj you want to rotate use
        #bpy.data.objects["Robot_Arm_Lower"].rotation_euler = xyz_rot
        for obj in bpy.context.selected_objects:
            obj.rotation_euler = xyz_rot
        return {'FINISHED'}

class MYADDON_OT_move_obj(bpy.types.Operator):
    """move the obj"""
    bl_idname = "myops.move_obj"
    bl_label = "move_obj"

    def execute(self, context):
        #moves all the selected objects: if you know the name of the obj you want to move use
        #bpy.data.objects["Robot_Arm_Lower"].location = xyz_loc
        for obj in bpy.context.selected_objects:
            obj.location = xyz_loc
        return {'FINISHED'}
#-------------------UI-----------------------------------------------------

class MYOPS_PT_move_obj(bpy.types.Panel):
    """Creates a Panel in the Tool tab"""
    bl_label = "Rotate & Move"
    bl_idname = "MYOPS_PT_move_obj_ui"
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'UI'
    bl_category = "Rotate & move"
    bl_context = "objectmode"

    @classmethod
    def poll(self,context):
        return True

    def draw(self, context):
        layout = self.layout
        scene = context.scene

        #Label
        layout.operator("myops.rotate_obj", text = "Rotate")
        layout.operator("myops.move_obj", text = "Move")

#-------------REGISTRATION--------------------
classes = (
    MYADDON_OT_rotate_obj,
    MYADDON_OT_move_obj,
    ROTATE_MOVE_PT_tool,
)

def register():
    from bpy.utils import register_class
    for cls in classes:
        register_class(cls)

def unregister():
    from bpy.utils import unregister_class
    for cls in reversed(classes):
        unregister_class(cls)

if __name__ == "__main__":
    register()
    #Sometimes i get some registration errors when debugging an addon. If you get the same error try uncommenting the following lines
    #unregister()
    #register()

you may want to modify it to fit your needs: for example you may want to create 2 sliders to control the xyz_rot and xyz_loc from the UI without having to re-run the addon (btw, you don't need to install it from the user preferences like normal addons, you can just use it like a script if you want).

the addon/script creates a panel in the tool tab, but feel free to move it where you want The custom panel is on the top right


EDIT

As you mention in the comment you are running Blender 2.79b and you don't know how to use python, so you could try to use the following script:

import bpy
from math import pi

#change your parameters here
move = True          #If "True" the objects move: write "False" to disable it
rotate = True        #If "True" the objects rotate: write "False" to disable it
xyz_rot = (0,0,0)    #What rotation you want your objects to have (in degrees)
xyz_loc = (1,1,1)    #What position you want your objects to have
objName = ""         #The name of the object you want to move/rotate, if you need to move one object only.
#                     If you leave it as "" the script will move/rotate all the selected objects. (Recommended)

# ------------- CODE ----------------
#Rotates all the selected objects (or the desired object if objName is not "")
if rotate:
    #convert degrees to radians
    x = xyz_rot[0]*pi/180
    y = xyz_rot[1]*pi/180
    z = xyz_rot[2]*pi/180
    xyz_rot = (x,y,z)

    if objName == "":
        for obj in bpy.context.selected_objects:
            obj.rotation_euler = xyz_rot
    else:
        bpy.data.objects[objName].rotation_euler = xyz_rot


#Moves all the selected objects (or the desired object if objName is not "")
if move:
    if objName == "":
        for obj in bpy.context.selected_objects:
            obj.location = xyz_loc
    else:
        bpy.data.objects[objName].location = xyz_loc

To run it, just paste it in the text editor, play with the parameters at the top and hit the "run script" button.

Every time you run it the selected objects (or the object you put in objName) will rotate and/or move based on the two flags ("move" and "rotate") and the two "xyz_loc" and "xyz_rot".

This should work both in 2.79 and 2.80, but you don't get the fancy panel and buttons of the precedent code

$\endgroup$
  • 2
    $\begingroup$ Please try to adhere to blender's class naming convention wiki.blender.org/wiki/Reference/Release_Notes/2.80/Python_API/… $\endgroup$ – batFINGER Aug 12 at 11:54
  • 2
    $\begingroup$ Oh sorry, I'm still new to that convenction ahah $\endgroup$ – Tareyes Aug 12 at 13:05
  • $\begingroup$ Wow, thank you @Tareyes for taking the time to write that code. Unfortunately I should've mentioned that I'm a complete noob to Python and Blender scripting so I'm not sure where to start. Do I just copy and paste that code into the Python script console? I tried that and nothing happened. I should point out that I'm using Blender 2.79b if that makes any difference? Maybe I'm trying to run before I can walk? I just assumed I could write some simple code and it would work — I'm fairly experienced with JavaScript coding so I suppose I naively thought it would be very similar. Thanks again $\endgroup$ – Ben Clarke Aug 13 at 2:45
  • 1
    $\begingroup$ @BenClarke I edited my answer with a second script that should work in your case. To run it you need to paste it in the text editor (not the python console: that allows you to insert only one line of code at the time) and press "run script" $\endgroup$ – Tareyes Aug 13 at 13:07
  • $\begingroup$ Thank you again @Tareyes. With the help of your code I managed to achieve what I was aiming for. See answer below. Couldn't have got there without your help! :) $\endgroup$ – Ben Clarke Aug 13 at 13:56
0
$\begingroup$

Okay, so thanks to the answers above I managed to do what I was aiming for (kind of). I've now got a custom panel in the Blender UI that performs specific movements/rotations when certain buttons are pressed. It is currently VERY basic but I am brand new to Python and Blender scripting so hopefully I will build upon this code during this project.

The current working version of the code is below (Blender 2.79b). Thanks for everyone's help that enabled me to get to this stage :)

bl_info = {
"name": "Robot Controls",
"blender": (2, 79, 0)
}

import bpy
from bpy.types import (Panel,Operator,PropertyGroup)

# Import math to convert radians to degrees
from math import pi

# This is just a simple object to hold some location/rotation variables
class ROBOT_ARM_L:
    Rx = 90*(pi/180)
    Ry = 0
    Rz = 0
    rotateTo = (Rx,Ry,Rz)    
    moveTo = (0.053666,-2.17661,0.706597)

# ------------------------------------------------------------------------
#    Rotate - This performs the rotation
# ------------------------------------------------------------------------

class ROBOT_ARM_L_OT_rotate_obj(bpy.types.Operator):
    bl_idname = "myops.rotate_obj"
    bl_label = "rotate_obj"

    def execute(self, context):
        obj = bpy.data.objects["Robot_Arm_Lower"]
        obj.rotation_euler = ROBOT_ARM_L.rotateTo
        return {'FINISHED'}

# ------------------------------------------------------------------------
#    Move - This performs the movement (location)
# ------------------------------------------------------------------------

class ROBOT_ARM_L_OT_move_obj(bpy.types.Operator):
    bl_idname = "myops.move_obj"
    bl_label = "move_obj"

    def execute(self, context):
        obj = bpy.data.objects["Robot_Arm_Lower"]
        obj.location = ROBOT_ARM_L.moveTo
        return {'FINISHED'}

# ----------------------------------------------------------------------------
#    Panel - This creates the custom panel/buttons in the UI 
# ----------------------------------------------------------------------------

class OBJECT_PT_CustomPanel(Panel):
    bl_idname = "object.custom_panel"
    bl_label = "Robot Controls"
    bl_space_type = "VIEW_3D"   
    bl_region_type = "TOOLS"    
    bl_category = "Tools"
    bl_context = "objectmode"   

    @classmethod
    def poll(self,context):
        return True

    def draw(self, context):
        layout = self.layout
        scene = context.scene

        #Label
        layout.operator("myops.rotate_obj", text = "Left Arm Rotate")
        layout.operator("myops.move_obj", text = "Left Arm Move")    

# ------------------------------------------------------------------------
#    Registration
# ------------------------------------------------------------------------

def register():
    bpy.utils.register_module(__name__)

def unregister():
    bpy.utils.unregister_module(__name__)
    del bpy.types.Scene.my_tool

if __name__ == "__main__":
    register()


The above code results in this custom panel:

enter image description here

$\endgroup$
  • $\begingroup$ Glad to help, and if I were you I would try Blender 2.8 $\endgroup$ – Tareyes Aug 14 at 15:09
  • $\begingroup$ Just to let you know, it's your decision... If you are accepting your own answer, you don't get any extra reputation. In case you accept the other answer (which isn't really different in comparison) Tareyes will gain a little bit of extra rep (15) for all the effort. $\endgroup$ – brockmann Aug 15 at 11:38
  • $\begingroup$ Sure, no problem. I'm not trying to increase my rep — I'm just here for knowledge! :) $\endgroup$ – Ben Clarke Aug 15 at 11:48
  • $\begingroup$ lol, thanks you guys ahah $\endgroup$ – Tareyes Aug 16 at 8:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.