Simple URDF support for MoonBit
let robot = @urdf.Robot::new("demo")
.add_link(
@urdf.Link::new("base").with_inertial(
@urdf.Inertial::from_box_density(
0.2, 0.1, 0.05, density=@urdf.Density::aluminum_6061(),
),
).add_visual(
@urdf.Visual::new(@urdf.Geometry::box(0.2, 0.1, 0.05))
.with_color("body", @urdf.Rgba::orange()),
),
)
.add_link(@urdf.Link::new("arm"))
.add_joint(
@urdf.Joint::revolute(
"shoulder",
parent="base",
child="arm",
axis=(0.0, 1.0, 0.0),
limit=@urdf.JointLimit::new(
lower=Some(-1.5), upper=Some(1.5), effort=10.0, velocity=2.0,
),
),
)
robot.write_urdf(Some("demo.urdf"), checked=true)let hip = @urdf.MateConnector::from_mm_deg("hip", x=100.0, axis=(1.0, 0.0, 0.0))
let leg = @urdf.MateConnector::new("leg_mount")
let joint = @urdf.Joint::from_mates(
"hip_joint", @urdf.JointType::Revolute,
parent_link="base", parent_mate=hip,
child_link="leg", child_mate=leg,
limit=Some(@urdf.JointLimit::new(effort=20.0, velocity=5.0)),
)
let poses = robot.forward_kinematics(
joint_positions={ "hip_joint": 0.5 },
)// triangles is Array[(Vec3, Vec3, Vec3)] in millimeters.
let inertial = @urdf.Inertial::from_triangles_mm(
triangles,
density=@urdf.Density::pla(),
)match @urdf.parse_urdf_from_string_result(xml) {
@urdf.ParseUrdfResult::Ok(robot) => { /* ... */ }
@urdf.ParseUrdfResult::Err(info) =>
println(@urdf.format_urdf_parse_error(info))
}| Example | Description |
|---|---|
| 01-single-link-box | Parameterized box: millimeter units, density, analytical inertia |
| 02-two-link-pendulum | Revolute pendulum assembled with mate connectors |
| 03-planetary-gearbox-urdf | Sun/ring/planets/carrier with mimic coupling |
| 04-six-dof-arm | Six-axis arm with Inertial::combine, safety controllers, transmissions |
| 05-wheeled-quadruped | Galileo-style quadruped: 17 links, 16 joints, full mesh bundle |
| 06-assistive-scooter | Rider-parameterized assistive scooter/wheelchair |
./run-example.sh 01 -o box.urdf
./run-example.sh 02 --length1 200 -o pendulum.urdf --validate
./run-example.sh 05 -o galileo.urdf
./run-example.sh 05 --bundle /tmp/galileo_pkg
python3 scripts/validate_urdf.py --check-meshes \
/tmp/galileo_pkg/urdf/galileo_quadruped.urdf./test-all.sh # moon fmt, moon info, moon test
python3 scripts/validate_urdf_test.py # validator self-tests
python3 scripts/validate_urdf.py robot.urdf # structural/physics checkspub struct Angle {
radians : Double
}pub struct Density {
kg_per_m3 : Double
}pub(all) enum Diagnostic {
EmptyRobot(String)
DuplicateLinkName(String)
DuplicateJointName(String)
MissingParentLink(String, String)
MissingChildLink(String, String)
SelfLoopJoint(String, String)
MultipleParentJoints(String)
KinematicCycle(String)
DisconnectedGraph(String)
ZeroJointAxis(String)
MissingJointLimit(String)
InvalidJointLimit(String, String)
InvalidMimicJoint(String, String)
InvalidGeometry(String, String)
NonPositiveMass(String, Double)
NonPhysicalInertia(String, String)
} derive(Eq, Debug)pub(all) struct Joint {
name : String
joint_type : JointType
origin : Origin
parent : String
child : String
axis : (Double, Double, Double)
limit : JointLimit?
dynamics : JointDynamics?
calibration : JointCalibration?
safety_controller : SafetyController?
mimic : JointMimic?
extra : Array[RawXmlNode]
} derive(Eq, Debug)fn Joint::continuous(name : String, parent~ : String, child~ : String, origin? : Origin, axis? : (Double, Double, Double), limit? : JointLimit?) -> Jointfn Joint::from_mates(name : String, joint_type : JointType, parent_link~ : String, parent_mate~ : MateConnector, child_link~ : String, child_mate~ : MateConnector, offset? : Double, angle_rad? : Double, flip_axis? : Bool, limit? : JointLimit?, dynamics? : JointDynamics?) -> Jointfn Joint::prismatic(name : String, parent~ : String, child~ : String, limit~ : JointLimit, origin? : Origin, axis? : (Double, Double, Double)) -> Jointfn Joint::revolute(name : String, parent~ : String, child~ : String, limit~ : JointLimit, origin? : Origin, axis? : (Double, Double, Double)) -> Jointfn JointLimit::new(effort~ : Double, velocity~ : Double, lower? : Double?, upper? : Double?) -> JointLimitpub struct Length {
meters : Double
}pub struct Mass {
kilograms : Double
}fn MateConnector::from_mm_deg(name : String, x? : Double, y? : Double, z? : Double, rx_deg? : Double, ry_deg? : Double, rz_deg? : Double, axis? : (Double, Double, Double)) -> MateConnectorfn MateConnector::new(name : String, origin? : Origin, axis? : (Double, Double, Double)) -> MateConnectorpub(all) struct RawXmlNode {
tag : String
attrs : Array[(String, String)]
text : String
children : Array[RawXmlNode]
} derive(Eq, Debug)fn Transmission::simple(name : String, joint_name : String, actuator_name : String, reduction? : Double, hardware_interface? : String) -> Transmissionfn UrdfBundle::package_xml(self : UrdfBundle, version? : String, description? : String, maintainer? : String, email? : String, license? : String) -> Stringfn fmt_num(n : Double) -> Stringfn snap_mates(parent_mate : MateConnector, child_mate : MateConnector, offset? : Double, angle_rad? : Double, flip_axis? : Bool) -> (Origin, (Double, Double, Double))fn v3_add(a : (Double, Double, Double), b : (Double, Double, Double)) -> (Double, Double, Double)fn v3_cross(a : (Double, Double, Double), b : (Double, Double, Double)) -> (Double, Double, Double)fn v3_sub(a : (Double, Double, Double), b : (Double, Double, Double)) -> (Double, Double, Double)async fn write_text_file(text : String, out_path : String?) -> Unitfn xml_escape(s : String) -> String