원클릭으로
quaternions
Quaternion creation, component access, and Euler angle conversion in PyChrono
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Quaternion creation, component access, and Euler angle conversion in PyChrono
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
Entry point for FSI-coupled hybrid plans (plan_type=fsi_in_scene) — any scene combining SPH fluid (water tanks, dam-break, wave channels) with multi-body dynamics, optionally with a wheeled vehicle. Pick this over mbs_in_scene whenever the plan involves a fluid domain (scene_objects with domain_type starting "sph_") or an FSI body registration (scene_objects with fsi_registration set). Routes to fsi/sph (always), veh/wheeled_vehicle (when vehicle present), and enforces FSI-specific invariants distinct from generic mbs_in_scene rigid scenes.
Entry point for rigid-body hybrid plans (plan_type=mbs_in_scene) combining a robot or vehicle with scene assets — NO fluid coupling. Routes to the correct domain skills and defines only high-level invariants. Use core/fsi_in_scene instead when the plan involves SPH fluid or FSI body registration.
Entry point for pure multi-body simulation plans (plan_type=mbs). Routes the agent to the correct mechanics, system, and camera skills and defines only high-level invariants.
Entry point for static scene plans (plan_type=scene). Routes the agent to the correct scene, system, and camera skills and defines only high-level invariants.
Set up SPH-based Fluid-Structure Interaction (FSI): create ChFsiFluidSystemSPH and ChFsiSystemSPH, configure fluid and SPH parameters, seed fluid particles with hydrostatic initialization, add container BCE boundary markers, register floating rigid bodies, optionally couple with a wheeled vehicle, and advance with sysFSI.DoStepDynamics(dT).
Translate a `geometry_relations` entry from the plan into correct PyChrono coordinate code. Read this whenever the plan declares a relation_name you have not previously encoded, and especially BEFORE writing SetPos / camera placement for any body that participates in a multi-body geometric constraint. Each subsection below is one canonical pattern named exactly as it appears in `plan.geometry_relations[i].relation_name`.
| name | quaternions |
| description | Quaternion creation, component access, and Euler angle conversion in PyChrono |
| compatibility | pychrono >= 8.0 |
| metadata | {"domain":"mbs"} |
Access quaternion components, create quaternions from angles/axes, and convert to Euler angles in PyChrono.
When reading body orientation, converting to Euler angles, creating a rotation, or passing a quaternion to Initialize/SetRot.
PyChrono quaternions use scalar-first storage: e0 is the scalar (w) part.
q = body.GetRot() # ChQuaterniond
# Correct attribute access:
w = q.e0 # scalar (w) component
i = q.e1 # x component
j = q.e2 # y component
k = q.e3 # z component
Do NOT use any of these — they do not exist in PyChrono:
# WRONG — AttributeError:
q.w # does not exist
q.x # does not exist
q.y # does not exist
q.z # does not exist
q.GetW() # does not exist
q.GetX() # does not exist
q.GetY() # does not exist
q.GetZ() # does not exist
rot = body.GetRot() # ChQuaterniond
euler = rot.GetCardanAnglesXYZ() # returns ChVector3d
angle_x = euler.x # rotation about X-axis [rad]
angle_y = euler.y # rotation about Y-axis [rad]
angle_z = euler.z # rotation about Z-axis [rad]
# From angle and axis (free function — returns a new quaternion):
q = chrono.QuatFromAngleAxis(angle_rad, chrono.VECT_Z)
q = chrono.QuatFromAngleAxis(angle_rad, chrono.ChVector3d(0, 0, 1))
# From angle and axis (instance method — mutates existing quaternion in-place):
q = chrono.ChQuaterniond()
q.SetFromAngleAxis(angle_rad, chrono.ChVector3d(0, 1, 0))
# Identity (no rotation):
q = chrono.QUNIT
# From Euler angles XYZ:
q = chrono.QuatFromAngleX(ax) * chrono.QuatFromAngleY(ay) * chrono.QuatFromAngleZ(az)
chrono.QUNIT # identity quaternion (no rotation)
chrono.Q_ROTATE_Y_TO_Z # rotate so Y-axis maps to Z-axis
chrono.Q_ROTATE_Y_TO_X # rotate so Y-axis maps to X-axis
chrono.Q_ROTATE_Z_TO_X # rotate so Z-axis maps to X-axis
rot = body.GetRot() # ChQuaterniond
# Body-local → world frame (e.g., attachment point on body to world position)
world_vec = rot.RotateBack(local_vec)
# World → body-local frame
local_vec = rot.Rotate(world_vec)
Typical usage — compute world position of a body-local attachment point:
rotor_pos = rotor.GetPos()
rotor_rot = rotor.GetRot()
attach_local = chrono.ChVector3d(0.25, 0, 0) # point in body frame
attach_world = rotor_pos + rotor_rot.RotateBack(attach_local)
v = chrono.ChVector3d(x, y, z)
v.Length() # magnitude (scalar)
v.Cross(other_vec) # cross product → ChVector3d
v.Dot(other_vec) # dot product → scalar
# Vector arithmetic: +, -, * (scalar) work as expected
delta = pos2 - pos1 # difference vector
rot = body.GetRot()
euler = rot.GetCardanAnglesXYZ() # ChVector3d
angle_about_z = euler.z # [rad]
q = chrono.QuatFromAngleAxis(chrono.CH_PI / 4, chrono.VECT_Z)
body.SetRot(q)
norm = (q.e0**2 + q.e1**2 + q.e2**2 + q.e3**2) ** 0.5
# Should be ~1.0 for a valid rotation quaternion
rot = chrono.QuatFromAngleAxis(-chrono.CH_PI / 2, chrono.ChVector3d(0, 1, 0))
frame = chrono.ChFramed(chrono.ChVector3d(x, y, z), rot)
joint.Initialize(body1, body2, frame)
allowed_classes:
allowed_methods:
allowed_constants:
allowed_utils: