notes
Robotics

STEP から URDF への変換 (FreeCAD スクリプト)

freecadcmd で STEP を読み、リンク単位で STL を書き出し、軸受位置から関節軸を復元して URDF を書く手順

要点#

STEP に拘束情報は無いが、軸受・減速機のパーツ位置から関節軸を復元できる。FreeCAD をヘッドレス (freecadcmd) でスクリプト実行すれば、STEP → リンク別 STL + URDF の変換がローカルで完結する。

手順#

  1. 構造把握: STEP をテキストとして grep -o "PRODUCT('[^']*'" するとパーツ名一覧が API 無しで得られる
  2. 階層とグローバル座標の取得: freecadcmd で Python スクリプトを実行
import FreeCAD, Import
doc = FreeCAD.newDocument("r")
Import.insert("robot.stp", "r")
# App::Part コンテナは .Group で子を辿る
# Part::Feature のグローバル配置:
gp = feat.getGlobalPlacement()
sh = feat.Shape.copy()
sh.Placement = gp.multiply(feat.Placement.inverse()).multiply(sh.Placement)
  1. 関節軸の特定: 軸受 (型番名で入っていることが多い) や減速機の CenterOfGravity を出力し、同軸に並ぶ位置 = 関節。リンク長が丸い数字 (例: 400.0 mm) になれば推定が正しい傍証になる
  2. リンク単位で STL 書き出し:
import Part, MeshPart
comp = Part.makeCompound(shapes)  # グローバル座標に変換済みの shape 群
mesh = MeshPart.meshFromShape(Shape=comp, LinearDeflection=0.8, AngularDeflection=0.6)
mesh.write("link_arm1.stl")
  1. URDF 記述。座標の扱いは次節
  2. 検証: check_urdf robot.urdf

URDF の座標処理#

メッシュを CAD グローバル座標のまま書き出した場合:

  • リンク frame の原点を関節ピボット位置 (グローバル) に置く
  • joint の <origin> = (親 frame からの差分)
  • visual/collision の <origin> = (メッシュをリンク frame に引き戻す)
  • 全 joint の回転をゼロにすれば、ゼロ姿勢 = CAD の姿勢になる
  • mm の STL は <mesh scale="0.001 0.001 0.001"/> で m に変換
  • CAD が Y-up の場合、root に fixed joint rpy="1.5708 0 0" を挟んで Z-up に立てる

制約#

  • 閉ループは表現できない: 平行リンク機構 (パレタイジングロボット等) は URDF の木構造に入らない。平行なバーは同角度で回る性質を使い、平行先のアームに fixed で付けるとゼロ姿勢では正しく、関節を動かすと位置が数十 mm ずれる (回転中心が違うため)。正確に扱うなら SDF や MuJoCo の equality constraint を使う
  • 慣性はメッシュ体積 × 仮定密度 + bounding box 近似で概算。真面目なシミュレーションでは CAD 側の質量特性から取り直す
  • 軸受が STEP に含まれていない (簡略化済み) モデルでは関節軸の復元根拠が減る

他手法との比較#

  • Assembly と mate を作り直せる状況なら Onshape 経由 や Fusion 360 経由 の方が再現性がある
  • この方法は「STEP しか手元に無い」「変換ツールに上げたくない」「1 回きり」の場合に速い。ジョイント再定義を GUI でやらずに済む

関連#

最終更新:

On this page