예전에 저는 스크립트로 CAD를 하는 OpenSCAD를 잠시 봤던 적이 있습니다.[바로가기] 아무래도 기계 엔지니어가 아니다 보니 멋드러진 툴로 현란하게 그리지 못하고 저렇게 코드를 이용한 CAD가 더 흥미롭더라구요^^. 뭐 그리고 한 동안 잊고 있었는데... 최근 파이썬 로보틱스라는 책[바로가기]을 읽다가 블렌더(Blender) 이야기가 나오더라구요. 그리고 기억했죠.. 저도 블렌더를 소개한 적이 있었더라구요^^[바로가기] 뭐 그때는 리눅스에 정말 초..초 간단히 설치하는게 내용이었지만요^^ 이 블렌더에는 Python 스크립트로 CAD 작업을 가능하게 했더라구요... 아~ 그래서 역시 저 답게 또 따라하기를 했죠... 도대체 전 언제쯤 이거 안하고 정말 멋진 내용을 올릴까요?ㅠㅠ.
뭐 아무튼~... Blender의 실행화면입니다.
저 부분을 바꿔서...
Scripting으로 바꾸면 Python 코드를 입력할 수 있는 창이 나타납니다.
그리고 교재에서 제공하는 코드를 붙여넣었죠^^
import bpy #This function will draw base plate def Draw_Base_Plate(): #Added two cubes for cutting sides of base plate bpy.ops.mesh.primitive_cube_add(radius=0.05, location=(0.175,0,0.09)) bpy.ops.mesh.primitive_cube_add(radius=0.05, location=(-0.175,0,0.09)) #Adding base plate bpy.ops.mesh.primitive_cylinder_add(radius=0.15,depth=0.005, location=(0,0,0.09)) #Adding booleab difference modifier from first cube bpy.ops.object.modifier_add(type='BOOLEAN') bpy.context.object.modifiers["Boolean"].operation = 'DIFFERENCE' bpy.context.object.modifiers["Boolean"].object = bpy.data.objects["Cube"] bpy.ops.object.modifier_apply(modifier="Boolean") #Adding booleab difference modifier from second cube bpy.ops.object.modifier_add(type='BOOLEAN') bpy.context.object.modifiers["Boolean"].operation = 'DIFFERENCE' bpy.context.object.modifiers["Boolean"].object = bpy.data.objects["Cube.001"] bpy.ops.object.modifier_apply(modifier="Boolean") #Deselect cylinder and delete cubes bpy.ops.object.select_pattern(pattern="Cube") bpy.ops.object.select_pattern(pattern="Cube.001") bpy.data.objects['Cylinder'].select = False bpy.ops.object.delete(use_global=False) #This function will draw motors and wheels def Draw_Motors_Wheels(): #Create first Wheel bpy.ops.mesh.primitive_cylinder_add(radius=0.045,depth=0.01, location=(0,0,0.07)) #Rotate bpy.context.object.rotation_euler[1] = 1.5708 #Transalation bpy.context.object.location[0] = 0.135 #Create second wheel bpy.ops.mesh.primitive_cylinder_add(radius=0.045,depth=0.01, location=(0,0,0.07)) #Rotate bpy.context.object.rotation_euler[1] = 1.5708 #Transalation bpy.context.object.location[0] = -0.135 #Adding motors bpy.ops.mesh.primitive_cylinder_add(radius=0.018,depth=0.06, location=(0.075,0,0.075)) bpy.context.object.rotation_euler[1] = 1.5708 bpy.ops.mesh.primitive_cylinder_add(radius=0.018,depth=0.06, location=(-0.075,0,0.075)) bpy.context.object.rotation_euler[1] = 1.5708 #Adding motor shaft bpy.ops.mesh.primitive_cylinder_add(radius=0.006,depth=0.04, location=(0.12,0,0.075)) bpy.context.object.rotation_euler[1] = 1.5708 bpy.ops.mesh.primitive_cylinder_add(radius=0.006,depth=0.04, location=(-0.12,0,0.075)) bpy.context.object.rotation_euler[1] = 1.5708 #Addubg Caster Wheel bpy.ops.mesh.primitive_cylinder_add(radius=0.015,depth=0.05, location=(0,0.125,0.065)) bpy.ops.mesh.primitive_cylinder_add(radius=0.015,depth=0.05, location=(0,-0.125,0.065)) #Adding Kinect bpy.ops.mesh.primitive_cube_add(radius=0.04, location=(0,0,0.26)) #Draw middle plate def Draw_Middle_Plate(): bpy.ops.mesh.primitive_cylinder_add(radius=0.15,depth=0.005, location=(0,0,0.22)) #Adding top plate def Draw_Top_Plate(): bpy.ops.mesh.primitive_cylinder_add(radius=0.15,depth=0.005, location=(0,0,0.37)) #Adding support tubes def Draw_Support_Tubes(): #Cylinders bpy.ops.mesh.primitive_cylinder_add(radius=0.007,depth=0.30, location=(0.09,0.09,0.23)) bpy.ops.mesh.primitive_cylinder_add(radius=0.007,depth=0.30, location=(-0.09,0.09,0.23)) bpy.ops.mesh.primitive_cylinder_add(radius=0.007,depth=0.30, location=(-0.09,-0.09,0.23)) bpy.ops.mesh.primitive_cylinder_add(radius=0.007,depth=0.30, location=(0.09,-0.09,0.23)) #Main code if __name__ == "__main__": Draw_Base_Plate() Draw_Motors_Wheels() Draw_Middle_Plate() Draw_Top_Plate() Draw_Support_Tubes()
그리고 Run Script를 해주면~~~
저렇게 .. 뭔가 멋진 모양이 나타납니다. 우와~~~~ 일단 감탄 5초 한다음에.. 그래도 튜토리얼인데 살짝 들여다 볼까요^^ 아 그전에 블렌더의 Python API에 대한 문서[바로가기]를 가보시면 뭐 다있는 내용입니다.
#Draw middle plate def Draw_Middle_Plate(): bpy.ops.mesh.primitive_cylinder_add(radius=0.15,depth=0.005, location=(0,0,0.22)) #Adding top plate def Draw_Top_Plate(): bpy.ops.mesh.primitive_cylinder_add(radius=0.15,depth=0.005, location=(0,0,0.37))
심플합니다. 중간과 윗판을 그린것인데... 딱 봐도 뭔지 알 정도로 cylinder로 구현되어 있습니다. 반지름(radius)과 길이(depth)를 지정하고 위치를 잡아주면 됩니다.^^.
#Adding support tubes def Draw_Support_Tubes(): #Cylinders bpy.ops.mesh.primitive_cylinder_add(radius=0.007,depth=0.30, location=(0.09,0.09,0.23)) bpy.ops.mesh.primitive_cylinder_add(radius=0.007,depth=0.30, location=(-0.09,0.09,0.23)) bpy.ops.mesh.primitive_cylinder_add(radius=0.007,depth=0.30, location=(-0.09,-0.09,0.23)) bpy.ops.mesh.primitive_cylinder_add(radius=0.007,depth=0.30, location=(0.09,-0.09,0.23))
저건 기둥들을 잡아 준 것인데 역시 cylinder로 그렸습니다.^^.
아~~ 저부분만 따로 그린 코드는
#This function will draw motors and wheels def Draw_Motors_Wheels(): #Create first Wheel bpy.ops.mesh.primitive_cylinder_add(radius=0.045,depth=0.01, location=(0,0,0.07)) #Rotate bpy.context.object.rotation_euler[1] = 1.5708 #Transalation bpy.context.object.location[0] = 0.135 #Create second wheel bpy.ops.mesh.primitive_cylinder_add(radius=0.045,depth=0.01, location=(0,0,0.07)) #Rotate bpy.context.object.rotation_euler[1] = 1.5708 #Transalation bpy.context.object.location[0] = -0.135 #Adding motors bpy.ops.mesh.primitive_cylinder_add(radius=0.018,depth=0.06, location=(0.075,0,0.075)) bpy.context.object.rotation_euler[1] = 1.5708 bpy.ops.mesh.primitive_cylinder_add(radius=0.018,depth=0.06, location=(-0.075,0,0.075)) bpy.context.object.rotation_euler[1] = 1.5708 #Adding motor shaft bpy.ops.mesh.primitive_cylinder_add(radius=0.006,depth=0.04, location=(0.12,0,0.075)) bpy.context.object.rotation_euler[1] = 1.5708 bpy.ops.mesh.primitive_cylinder_add(radius=0.006,depth=0.04, location=(-0.12,0,0.075)) bpy.context.object.rotation_euler[1] = 1.5708 #Addubg Caster Wheel bpy.ops.mesh.primitive_cylinder_add(radius=0.015,depth=0.05, location=(0,0.125,0.065)) bpy.ops.mesh.primitive_cylinder_add(radius=0.015,depth=0.05, location=(0,-0.125,0.065)) #Adding Kinect bpy.ops.mesh.primitive_cube_add(radius=0.04, location=(0,0,0.26))
좀 길긴 하지만, 두 바퀴는 cylinder로 그린다음 y축 중심으로 90도 회전하고, 위치를 다시 잡아준 것입니다. 그리고, 모터와 앞 뒤 바퀴용인 캐스터를 그려넣은 것이죠^^
이제 base판인데요.. 이 판은 꽤 재미있게 그립니다. 먼저 저런 cube를 놓고...
원판을 cylinder로 그린다음... 원판에서 cube를 빼버린 겁니다.^^
#This function will draw base plate def Draw_Base_Plate(): #Added two cubes for cutting sides of base plate bpy.ops.mesh.primitive_cube_add(radius=0.05, location=(0.175,0,0.09)) bpy.ops.mesh.primitive_cube_add(radius=0.05, location=(-0.175,0,0.09)) #Adding base plate bpy.ops.mesh.primitive_cylinder_add(radius=0.15,depth=0.005, location=(0,0,0.09)) #Adding booleab difference modifier from first cube bpy.ops.object.modifier_add(type='BOOLEAN') bpy.context.object.modifiers["Boolean"].operation = 'DIFFERENCE' bpy.context.object.modifiers["Boolean"].object = bpy.data.objects["Cube"] bpy.ops.object.modifier_apply(modifier="Boolean") #Adding booleab difference modifier from second cube bpy.ops.object.modifier_add(type='BOOLEAN') bpy.context.object.modifiers["Boolean"].operation = 'DIFFERENCE' bpy.context.object.modifiers["Boolean"].object = bpy.data.objects["Cube.001"] bpy.ops.object.modifier_apply(modifier="Boolean") #Deselect cylinder and delete cubes bpy.ops.object.select_pattern(pattern="Cube") bpy.ops.object.select_pattern(pattern="Cube.001") bpy.data.objects['Cylinder'].select = False bpy.ops.object.delete(use_global=False)
그러면...
이 그림이 되는 거죠^^
이제 다 그렸네요^^
이걸 STL파일로 export 시키면 저렇게 이쁘당한 모양을 얻을 수 있습니다. 아 3D 데이터를 바로 확인하기에는 별도로 Mesh Lab[바로가기]도 괜찮다고 하네요
괜찮네요~~~ 이제 도면 작업도 간단한 거라면 좀 더 편하게 할 수 있을듯 하네요^^
'Robot > Robot Program - ROS' 카테고리의 다른 글
ROS 가제보(Gazebo) 연습하기 - Pan/Tilt (25) | 2017.03.29 |
---|---|
ROS URDF의 기초예제 Pan/Tilt 시스템 (24) | 2017.03.20 |
ARDUnity 개발자가 말하는 ARDUnity (4) | 2016.07.29 |
유니티에 실제 서보모터 3D 모델을 import해서 서보모터 구동해 보기 (2) | 2016.07.06 |
푸쉬 버튼으로 유니티 Directional Light의 Intensity 조절하기 (6) | 2016.06.29 |
ROS Moveit으로 turtlebot_arm 프로젝트 설치 후 구동해 보기 (4) | 2016.06.24 |
유니티(Unity) UI의 Toggle Button과 아두이노의 Push Button 연동하기 (4) | 2016.06.22 |