file struktur
This commit is contained in:
123
pipeline/precheck/check_constraints.py
Normal file
123
pipeline/precheck/check_constraints.py
Normal file
@@ -0,0 +1,123 @@
|
||||
import json
|
||||
import math
|
||||
|
||||
# Load robot.json
|
||||
with open(r'../../data/robot/robot.json') as f:
|
||||
robot = json.load(f)
|
||||
|
||||
# Extract markers by link
|
||||
markers_by_link = {}
|
||||
for link_name, link_data in robot['links'].items():
|
||||
markers = link_data.get('markers', [])
|
||||
if markers:
|
||||
markers_by_link[link_name] = markers
|
||||
|
||||
print("=" * 70)
|
||||
print("MARKER DISTRIBUTION BY LINK")
|
||||
print("=" * 70)
|
||||
for link, markers in markers_by_link.items():
|
||||
print(f"\n{link}: {len(markers)} markers")
|
||||
for m in markers:
|
||||
pos = m['position']
|
||||
print(f" ID {m['id']:3d}: pos={pos}")
|
||||
|
||||
# Check rigid body constraints: distances within each link
|
||||
print("\n" + "=" * 70)
|
||||
print("RIGID BODY CONSTRAINT CHECK (Arm1, Ellbow, Arm2)")
|
||||
print("=" * 70)
|
||||
|
||||
for link_name in ['Arm1', 'Ellbow', 'Arm2']:
|
||||
if link_name not in markers_by_link:
|
||||
continue
|
||||
|
||||
markers = markers_by_link[link_name]
|
||||
positions = [(m['position'][0], m['position'][1], m['position'][2]) for m in markers]
|
||||
|
||||
print(f"\n{link_name}:")
|
||||
if len(positions) > 1:
|
||||
for i in range(len(positions)):
|
||||
for j in range(i+1, len(positions)):
|
||||
dx = positions[i][0] - positions[j][0]
|
||||
dy = positions[i][1] - positions[j][1]
|
||||
dz = positions[i][2] - positions[j][2]
|
||||
dist = math.sqrt(dx*dx + dy*dy + dz*dz)
|
||||
print(f" Marker {markers[i]['id']:3d} <-> {markers[j]['id']:3d}: {dist:7.2f} mm")
|
||||
else:
|
||||
print(f" Only {len(positions)} marker(s)")
|
||||
|
||||
# Check X-distances between links
|
||||
print("\n" + "=" * 70)
|
||||
print("X-POSITION CONSTRAINT CHECK (Link relationships)")
|
||||
print("=" * 70)
|
||||
|
||||
# Get marker positions per link
|
||||
link_x_positions = {}
|
||||
for link_name in ['Board', 'Base', 'Arm1', 'Ellbow', 'Arm2']:
|
||||
if link_name in markers_by_link:
|
||||
x_vals = [m['position'][0] for m in markers_by_link[link_name]]
|
||||
link_x_positions[link_name] = {
|
||||
'min_x': min(x_vals),
|
||||
'max_x': max(x_vals),
|
||||
'count': len(x_vals)
|
||||
}
|
||||
|
||||
print("\nX-position ranges by link (local coords):")
|
||||
for link, data in link_x_positions.items():
|
||||
print(f" {link:10s}: x in [{data['min_x']:7.2f}, {data['max_x']:7.2f}] mm ({data['count']} markers)")
|
||||
|
||||
# Check X-distance between Arm1 and Ellbow
|
||||
print("\nKey constraint analysis:")
|
||||
arm1_x = [m['position'][0] for m in markers_by_link['Arm1']]
|
||||
ellbow_x = [m['position'][0] for m in markers_by_link['Ellbow']]
|
||||
print(f" Arm1 local X: {arm1_x}")
|
||||
print(f" Ellbow local X: {ellbow_x}")
|
||||
print(f" => BOTH rotate around X-axis, so X-spread within each link is FIXED")
|
||||
print(f" => X-distance between links is FIXED in world (different local X values)")
|
||||
|
||||
# Check Arm2 structure
|
||||
print("\n" + "=" * 70)
|
||||
print("ARM2 KINEMATIC CHECK (sin(a) dependency)")
|
||||
print("=" * 70)
|
||||
|
||||
arm2_markers = markers_by_link['Arm2']
|
||||
print(f"\nArm2 has {len(arm2_markers)} markers")
|
||||
print("Arm2 marker positions (local coords, before 'a' rotation around Y):")
|
||||
for m in arm2_markers:
|
||||
pos = m['position']
|
||||
print(f" ID {m['id']:3d}: x={pos[0]:8.2f}, y={pos[1]:8.2f}, z={pos[2]:8.2f}")
|
||||
|
||||
print("\nWhen Arm2 rotates around Y-axis (variable 'a'):")
|
||||
print(" Rotation matrix Ry(a) acts on [x_local, y_local, z_local]:")
|
||||
print(" X_world = 90 + x_local * cos(a) - z_local * sin(a)")
|
||||
print(" Y_world = y_local (unchanged)")
|
||||
print(" Z_world = x_local * sin(a) + z_local * cos(a)")
|
||||
print("\n=> X_world DEPENDS on sin(a) and z_local values!")
|
||||
|
||||
# Verify: X differences between Arm2 markers
|
||||
arm2_x_vals = [m['position'][0] for m in arm2_markers]
|
||||
arm2_z_vals = [m['position'][2] for m in arm2_markers]
|
||||
print(f"\nArm2 local X values: {sorted(set(arm2_x_vals))}")
|
||||
print(f"Arm2 local Z values: {sorted(set(arm2_z_vals))}")
|
||||
if len(set(arm2_z_vals)) > 1:
|
||||
print(f"=> Multiple Z values present: X_world will differ by sin(a) contributions")
|
||||
|
||||
print("\n" + "=" * 70)
|
||||
print("SUMMARY: WHICH CONSTRAINTS MAKE SENSE?")
|
||||
print("=" * 70)
|
||||
print("""
|
||||
1. RIGID BODY DISTANCES within Arm1/Ellbow/Arm2:
|
||||
✓ VALID - Fixed distances between markers on same rigid link
|
||||
✓ HELPS with: Preventing deformation, reducing degrees of freedom
|
||||
|
||||
2. X-DISTANCES between links (Arm1, Ellbow, Base):
|
||||
✓ VALID - Both rotate around X-axis, so relative X is fixed
|
||||
✓ HELPS with: Preventing sliding along links
|
||||
|
||||
3. X-POSITION of Arm2 dependent on sin(a):
|
||||
⚠ PARTIALLY VALID - Different markers have different dependencies
|
||||
✓ HELPS with: Constraining the a variable from Z-spread observation
|
||||
|
||||
IMPLEMENTATION RECOMMENDATION:
|
||||
- Start with constraints 1 & 2 (rigid body + inter-link X)
|
||||
- Use constraint 3 as a sanity check on 'a' estimation
|
||||
""")
|
||||
246
pipeline/precheck/json_to_urdf.py
Normal file
246
pipeline/precheck/json_to_urdf.py
Normal file
@@ -0,0 +1,246 @@
|
||||
# json_to_urdf.py
|
||||
import json
|
||||
import math
|
||||
import xml.etree.ElementTree as ET
|
||||
from pathlib import Path
|
||||
from xml.dom import minidom
|
||||
|
||||
# ============================================================
|
||||
# CONFIG
|
||||
# ============================================================
|
||||
|
||||
ROBOT_JSON = "../../data/robot/robot.json"
|
||||
OUTPUT_URDF = "robot.urdf"
|
||||
|
||||
# ============================================================
|
||||
# HELPERS
|
||||
# ============================================================
|
||||
|
||||
|
||||
def mm_to_m(v):
|
||||
return float(v) / 1000.0
|
||||
|
||||
|
||||
def vec_mm_to_m(v):
|
||||
return [mm_to_m(x) for x in v]
|
||||
|
||||
|
||||
def deg_to_rad(v):
|
||||
return math.radians(float(v))
|
||||
|
||||
|
||||
def vec_deg_to_rad(v):
|
||||
return [deg_to_rad(x) for x in v]
|
||||
|
||||
|
||||
def xyz_str(v):
|
||||
return f"{v[0]:.6f} {v[1]:.6f} {v[2]:.6f}"
|
||||
|
||||
|
||||
# ============================================================
|
||||
# LOAD JSON
|
||||
# ============================================================
|
||||
|
||||
with open(ROBOT_JSON, "r", encoding="utf-8") as f:
|
||||
robot_json = json.load(f)
|
||||
|
||||
links = robot_json.get("links", {})
|
||||
|
||||
# ============================================================
|
||||
# ROOT
|
||||
# ============================================================
|
||||
|
||||
robot_name = Path(ROBOT_JSON).stem
|
||||
robot = ET.Element("robot")
|
||||
robot.set("name", robot_name)
|
||||
|
||||
# ============================================================
|
||||
# CREATE LINKS
|
||||
# ============================================================
|
||||
|
||||
for link_name, link_info in links.items():
|
||||
|
||||
urdf_link = ET.SubElement(robot, "link")
|
||||
urdf_link.set("name", link_name)
|
||||
|
||||
# --------------------------------------------------------
|
||||
# VISUALS
|
||||
# --------------------------------------------------------
|
||||
|
||||
models = link_info.get("model", [])
|
||||
|
||||
for model in models:
|
||||
|
||||
stl_file = model.get("stlFile")
|
||||
if not stl_file:
|
||||
continue
|
||||
|
||||
visual = ET.SubElement(urdf_link, "visual")
|
||||
|
||||
origin = ET.SubElement(visual, "origin")
|
||||
|
||||
xyz = vec_mm_to_m(model.get("originOfModel", [0, 0, 0]))
|
||||
rpy = vec_deg_to_rad(model.get("rotationOfModelDegree", [0, 0, 0]))
|
||||
|
||||
origin.set("xyz", xyz_str(xyz))
|
||||
origin.set("rpy", xyz_str(rpy))
|
||||
|
||||
geometry = ET.SubElement(visual, "geometry")
|
||||
|
||||
mesh = ET.SubElement(geometry, "mesh")
|
||||
mesh.set("filename", stl_file)
|
||||
mesh.set("scale", "0.001 0.001 0.001")
|
||||
|
||||
# --------------------------------------------------------
|
||||
# SIMPLE COLLISION FROM SKELETON
|
||||
# --------------------------------------------------------
|
||||
|
||||
skeleton = link_info.get("skeleton")
|
||||
|
||||
if isinstance(skeleton, dict):
|
||||
|
||||
p1 = skeleton.get("from", [0, 0, 0])
|
||||
p2 = skeleton.get("to", [0, 0, 0])
|
||||
|
||||
dx = p2[0] - p1[0]
|
||||
dy = p2[1] - p1[1]
|
||||
dz = p2[2] - p1[2]
|
||||
|
||||
length_mm = math.sqrt(dx * dx + dy * dy + dz * dz)
|
||||
length_m = mm_to_m(length_mm)
|
||||
|
||||
radius_mm = skeleton.get("radius", 4)
|
||||
radius_m = mm_to_m(radius_mm)
|
||||
|
||||
cx = (p1[0] + p2[0]) * 0.5
|
||||
cy = (p1[1] + p2[1]) * 0.5
|
||||
cz = (p1[2] + p2[2]) * 0.5
|
||||
|
||||
collision = ET.SubElement(urdf_link, "collision")
|
||||
|
||||
collision_origin = ET.SubElement(collision, "origin")
|
||||
collision_origin.set(
|
||||
"xyz",
|
||||
xyz_str(vec_mm_to_m([cx, cy, cz]))
|
||||
)
|
||||
|
||||
# ----------------------------------------------------
|
||||
# CYLINDER ORIENTATION
|
||||
# URDF cylinder points along Z
|
||||
# ----------------------------------------------------
|
||||
|
||||
roll = 0.0
|
||||
pitch = 0.0
|
||||
yaw = 0.0
|
||||
|
||||
if abs(dx) >= abs(dy) and abs(dx) >= abs(dz):
|
||||
pitch = math.radians(90)
|
||||
yaw = 0.0
|
||||
|
||||
elif abs(dy) >= abs(dx) and abs(dy) >= abs(dz):
|
||||
pitch = math.radians(90)
|
||||
yaw = math.radians(90)
|
||||
|
||||
collision_origin.set(
|
||||
"rpy",
|
||||
xyz_str([roll, pitch, yaw])
|
||||
)
|
||||
|
||||
geometry = ET.SubElement(collision, "geometry")
|
||||
|
||||
cylinder = ET.SubElement(geometry, "cylinder")
|
||||
cylinder.set("radius", f"{radius_m:.6f}")
|
||||
cylinder.set("length", f"{length_m:.6f}")
|
||||
|
||||
# ============================================================
|
||||
# CREATE JOINTS
|
||||
# ============================================================
|
||||
|
||||
for link_name, link_info in links.items():
|
||||
|
||||
parent_name = link_info.get("parent")
|
||||
|
||||
if parent_name is None:
|
||||
continue
|
||||
|
||||
joint_info = link_info.get("jointToParent", {})
|
||||
|
||||
joint_name = joint_info.get("name", f"joint_{parent_name}_{link_name}")
|
||||
joint_type = joint_info.get("type", "fixed")
|
||||
|
||||
if joint_type == "linear":
|
||||
urdf_joint_type = "prismatic"
|
||||
elif joint_type == "revolute":
|
||||
urdf_joint_type = "revolute"
|
||||
else:
|
||||
urdf_joint_type = "fixed"
|
||||
|
||||
joint = ET.SubElement(robot, "joint")
|
||||
joint.set("name", joint_name)
|
||||
joint.set("type", urdf_joint_type)
|
||||
|
||||
# --------------------------------------------------------
|
||||
# PARENT / CHILD
|
||||
# --------------------------------------------------------
|
||||
|
||||
parent = ET.SubElement(joint, "parent")
|
||||
parent.set("link", parent_name)
|
||||
|
||||
child = ET.SubElement(joint, "child")
|
||||
child.set("link", link_name)
|
||||
|
||||
# --------------------------------------------------------
|
||||
# ORIGIN
|
||||
# --------------------------------------------------------
|
||||
|
||||
origin_xyz = joint_info.get("origin", [0, 0, 0])
|
||||
origin_rpy = joint_info.get("rotation", [0, 0, 0])
|
||||
|
||||
origin = ET.SubElement(joint, "origin")
|
||||
origin.set(
|
||||
"xyz",
|
||||
xyz_str(vec_mm_to_m(origin_xyz))
|
||||
)
|
||||
origin.set(
|
||||
"rpy",
|
||||
xyz_str(vec_deg_to_rad(origin_rpy))
|
||||
)
|
||||
|
||||
# --------------------------------------------------------
|
||||
# AXIS
|
||||
# --------------------------------------------------------
|
||||
|
||||
axis = joint_info.get("axis", [1, 0, 0])
|
||||
|
||||
axis_tag = ET.SubElement(joint, "axis")
|
||||
axis_tag.set("xyz", xyz_str(axis))
|
||||
|
||||
# --------------------------------------------------------
|
||||
# DEFAULT LIMITS
|
||||
# --------------------------------------------------------
|
||||
|
||||
if urdf_joint_type in ["revolute", "prismatic"]:
|
||||
|
||||
limit = ET.SubElement(joint, "limit")
|
||||
|
||||
if urdf_joint_type == "revolute":
|
||||
limit.set("lower", f"{-math.pi:.6f}")
|
||||
limit.set("upper", f"{math.pi:.6f}")
|
||||
else:
|
||||
limit.set("lower", "-1.0")
|
||||
limit.set("upper", "1.0")
|
||||
|
||||
limit.set("effort", "100")
|
||||
limit.set("velocity", "10")
|
||||
|
||||
# ============================================================
|
||||
# PRETTY XML
|
||||
# ============================================================
|
||||
|
||||
xml_string = ET.tostring(robot, encoding="utf-8")
|
||||
pretty = minidom.parseString(xml_string).toprettyxml(indent=" ")
|
||||
|
||||
with open(OUTPUT_URDF, "w", encoding="utf-8") as f:
|
||||
f.write(pretty)
|
||||
|
||||
print("URDF written:", OUTPUT_URDF)
|
||||
179
pipeline/precheck/robot.urdf
Normal file
179
pipeline/precheck/robot.urdf
Normal file
@@ -0,0 +1,179 @@
|
||||
<?xml version="1.0" ?>
|
||||
<robot name="robot">
|
||||
<link name="Board">
|
||||
<visual>
|
||||
<origin xyz="0.000000 0.000000 0.000000" rpy="0.000000 0.000000 -1.570796"/>
|
||||
<geometry>
|
||||
<mesh filename="surfaces/Board.stl" scale="0.001 0.001 0.001"/>
|
||||
</geometry>
|
||||
</visual>
|
||||
<visual>
|
||||
<origin xyz="0.000000 0.000000 0.000000" rpy="0.000000 0.000000 -1.570796"/>
|
||||
<geometry>
|
||||
<mesh filename="surfaces/BoardRail.stl" scale="0.001 0.001 0.001"/>
|
||||
</geometry>
|
||||
</visual>
|
||||
<collision>
|
||||
<origin xyz="0.500000 0.000000 0.016000" rpy="0.000000 1.570796 0.000000"/>
|
||||
<geometry>
|
||||
<cylinder radius="0.004000" length="1.000000"/>
|
||||
</geometry>
|
||||
</collision>
|
||||
</link>
|
||||
<link name="Base">
|
||||
<visual>
|
||||
<origin xyz="-0.030000 0.000000 -0.035000" rpy="0.000000 0.000000 0.000000"/>
|
||||
<geometry>
|
||||
<mesh filename="surfaces/Base.stl" scale="0.001 0.001 0.001"/>
|
||||
</geometry>
|
||||
</visual>
|
||||
<collision>
|
||||
<origin xyz="0.055000 0.108000 0.045000" rpy="0.000000 1.570796 0.000000"/>
|
||||
<geometry>
|
||||
<cylinder radius="0.004000" length="0.110000"/>
|
||||
</geometry>
|
||||
</collision>
|
||||
</link>
|
||||
<link name="Arm1">
|
||||
<visual>
|
||||
<origin xyz="-0.029000 0.025000 0.028500" rpy="3.141593 0.000000 -1.570796"/>
|
||||
<geometry>
|
||||
<mesh filename="surfaces/Holm.stl" scale="0.001 0.001 0.001"/>
|
||||
</geometry>
|
||||
</visual>
|
||||
<collision>
|
||||
<origin xyz="0.000000 -0.125000 0.000000" rpy="0.000000 1.570796 1.570796"/>
|
||||
<geometry>
|
||||
<cylinder radius="0.004000" length="0.250000"/>
|
||||
</geometry>
|
||||
</collision>
|
||||
</link>
|
||||
<link name="Ellbow">
|
||||
<visual>
|
||||
<origin xyz="0.090000 0.000000 0.000000" rpy="0.000000 -1.570796 -1.570796"/>
|
||||
<geometry>
|
||||
<mesh filename="surfaces/Ellebogen.stl" scale="0.001 0.001 0.001"/>
|
||||
</geometry>
|
||||
</visual>
|
||||
<collision>
|
||||
<origin xyz="0.045000 0.000000 0.000000" rpy="0.000000 1.570796 0.000000"/>
|
||||
<geometry>
|
||||
<cylinder radius="0.004000" length="0.090000"/>
|
||||
</geometry>
|
||||
</collision>
|
||||
</link>
|
||||
<link name="Arm2">
|
||||
<visual>
|
||||
<origin xyz="0.000000 -0.250000 0.000000" rpy="3.141593 0.000000 -1.570796"/>
|
||||
<geometry>
|
||||
<mesh filename="surfaces/Unterarm.stl" scale="0.001 0.001 0.001"/>
|
||||
</geometry>
|
||||
</visual>
|
||||
<collision>
|
||||
<origin xyz="0.000000 -0.125000 0.000000" rpy="0.000000 1.570796 1.570796"/>
|
||||
<geometry>
|
||||
<cylinder radius="0.004000" length="0.250000"/>
|
||||
</geometry>
|
||||
</collision>
|
||||
</link>
|
||||
<link name="Hand">
|
||||
<collision>
|
||||
<origin xyz="0.000000 -0.017500 0.000000" rpy="0.000000 1.570796 1.570796"/>
|
||||
<geometry>
|
||||
<cylinder radius="0.004000" length="0.035000"/>
|
||||
</geometry>
|
||||
</collision>
|
||||
</link>
|
||||
<link name="Palm">
|
||||
<collision>
|
||||
<origin xyz="0.000000 -0.035000 0.000000" rpy="0.000000 1.570796 0.000000"/>
|
||||
<geometry>
|
||||
<cylinder radius="0.007000" length="0.100000"/>
|
||||
</geometry>
|
||||
</collision>
|
||||
</link>
|
||||
<link name="FingerA">
|
||||
<visual>
|
||||
<origin xyz="0.024000 0.000000 -0.009100" rpy="1.570796 -1.570796 0.000000"/>
|
||||
<geometry>
|
||||
<mesh filename="surfaces/Finger.stl" scale="0.001 0.001 0.001"/>
|
||||
</geometry>
|
||||
</visual>
|
||||
<collision>
|
||||
<origin xyz="0.000000 -0.030000 0.000000" rpy="0.000000 1.570796 1.570796"/>
|
||||
<geometry>
|
||||
<cylinder radius="0.004000" length="0.060000"/>
|
||||
</geometry>
|
||||
</collision>
|
||||
</link>
|
||||
<link name="FingerB">
|
||||
<visual>
|
||||
<origin xyz="-0.024000 0.000000 0.009100" rpy="1.570796 1.570796 0.000000"/>
|
||||
<geometry>
|
||||
<mesh filename="surfaces/Finger.stl" scale="0.001 0.001 0.001"/>
|
||||
</geometry>
|
||||
</visual>
|
||||
<collision>
|
||||
<origin xyz="0.000000 -0.030000 0.000000" rpy="0.000000 1.570796 1.570796"/>
|
||||
<geometry>
|
||||
<cylinder radius="0.004000" length="0.060000"/>
|
||||
</geometry>
|
||||
</collision>
|
||||
</link>
|
||||
<joint name="Slider" type="prismatic">
|
||||
<parent link="Board"/>
|
||||
<child link="Base"/>
|
||||
<origin xyz="0.000000 0.000000 0.016000" rpy="0.000000 0.000000 0.000000"/>
|
||||
<axis xyz="1.000000 0.000000 0.000000"/>
|
||||
<limit lower="-1.0" upper="1.0" effort="100" velocity="10"/>
|
||||
</joint>
|
||||
<joint name="Joint1" type="revolute">
|
||||
<parent link="Base"/>
|
||||
<child link="Arm1"/>
|
||||
<origin xyz="0.110000 0.108000 0.045000" rpy="0.000000 0.000000 0.000000"/>
|
||||
<axis xyz="-1.000000 0.000000 0.000000"/>
|
||||
<limit lower="-3.141593" upper="3.141593" effort="100" velocity="10"/>
|
||||
</joint>
|
||||
<joint name="Joint2" type="revolute">
|
||||
<parent link="Arm1"/>
|
||||
<child link="Ellbow"/>
|
||||
<origin xyz="0.000000 -0.250000 0.000000" rpy="0.000000 0.000000 0.000000"/>
|
||||
<axis xyz="-1.000000 0.000000 0.000000"/>
|
||||
<limit lower="-3.141593" upper="3.141593" effort="100" velocity="10"/>
|
||||
</joint>
|
||||
<joint name="Joint3" type="revolute">
|
||||
<parent link="Ellbow"/>
|
||||
<child link="Arm2"/>
|
||||
<origin xyz="0.090000 0.000000 0.000000" rpy="0.000000 0.000000 0.000000"/>
|
||||
<axis xyz="0.000000 -1.000000 0.000000"/>
|
||||
<limit lower="-3.141593" upper="3.141593" effort="100" velocity="10"/>
|
||||
</joint>
|
||||
<joint name="Joint4" type="revolute">
|
||||
<parent link="Arm2"/>
|
||||
<child link="Hand"/>
|
||||
<origin xyz="0.000000 -0.250000 0.000000" rpy="0.000000 0.000000 0.000000"/>
|
||||
<axis xyz="1.000000 0.000000 0.000000"/>
|
||||
<limit lower="-3.141593" upper="3.141593" effort="100" velocity="10"/>
|
||||
</joint>
|
||||
<joint name="Joint3" type="revolute">
|
||||
<parent link="Hand"/>
|
||||
<child link="Palm"/>
|
||||
<origin xyz="0.000000 0.000000 0.000000" rpy="0.000000 0.000000 0.000000"/>
|
||||
<axis xyz="0.000000 -1.000000 0.000000"/>
|
||||
<limit lower="-3.141593" upper="3.141593" effort="100" velocity="10"/>
|
||||
</joint>
|
||||
<joint name="Slider" type="prismatic">
|
||||
<parent link="Palm"/>
|
||||
<child link="FingerA"/>
|
||||
<origin xyz="0.004000 -0.035000 0.000000" rpy="0.000000 0.000000 0.000000"/>
|
||||
<axis xyz="1.000000 0.000000 0.000000"/>
|
||||
<limit lower="-1.0" upper="1.0" effort="100" velocity="10"/>
|
||||
</joint>
|
||||
<joint name="Slider" type="prismatic">
|
||||
<parent link="Palm"/>
|
||||
<child link="FingerB"/>
|
||||
<origin xyz="-0.004000 -0.035000 0.000000" rpy="0.000000 0.000000 0.000000"/>
|
||||
<axis xyz="-1.000000 0.000000 0.000000"/>
|
||||
<limit lower="-1.0" upper="1.0" effort="100" velocity="10"/>
|
||||
</joint>
|
||||
</robot>
|
||||
Reference in New Issue
Block a user