PlanarMechanics.SlipBasedWheelJoint
Slip-based wheel joint with slip-dependent friction characteristics.
Models the behavior of a wheel rolling on an x,y-plane whose contact patch has slip-dependent friction. The driving direction (at phi=0) is given by parameter r.
The slip is decomposed into lateral and longitudinal components. For low rolling velocity, a dry-friction model is used. The friction force is computed using MultibodyComponents.limit_S_triple for smooth transitions between adhesion and sliding.
Connectors:
frame_a: 2D frame for steering on the planeflange_a: 1D rotational flange for wheel rolling actuationdynamicLoad: Input for dynamic component of normal load
This component extends from MultibodyComponents.Renderable
Usage
MultibodyComponents.PlanarMechanics.SlipBasedWheelJoint(render=true, color=[0.1, 0.1, 0.1, 1], specular_coefficient=0.7, r=[1, 0], N, vAdhesion_min, vSlide_min, sAdhesion, sSlide, mu_A, mu_S, radius=0.1, rim_diameter=0.1, wheel_width=0.06, z_position=0)
Parameters:
| Name | Description | Units | Default value |
|---|---|---|---|
render | – | true | |
color | – | [0.1, 0.1, 0.1, 1] | |
specular_coefficient | – | 0.7 | |
r | Driving direction of the wheel at angle phi = 0 | – | [1, 0] |
N | Base normal load | N | |
vAdhesion_min | Minimum adhesion velocity | m/s | |
vSlide_min | Minimum sliding velocity | m/s | |
sAdhesion | Adhesion slippage | – | |
sSlide | Sliding slippage | – | |
mu_A | Friction coefficient at adhesion | – | |
mu_S | Friction coefficient at sliding | – | |
radius | Radius of the wheel | m | 0.1 |
rim_diameter | Diameter of the rim cylinders | – | 0.1 |
wheel_width | Width of the wheel | – | 0.06 |
z_position | z-position of the wheel in animations | – | 0 |
Connectors
frame_a- Coordinate system (2-dim.) fixed to the component with one cut-force and cut-torque.
All variables are resolved in the planar world frame. (Frame2D)
flange_a- This connector represents a rotational spline with angle and torque as the potential and flow variables, respectively. (Spline)dynamicLoad- This connector represents a real signal as an input to a component (RealInput)
Variables
| Name | Description | Units |
|---|---|---|
e0 | Unit vector in direction of r resolved w.r.t. inertial frame | – |
phi_roll | wheel angle | rad |
w_roll | Roll velocity of wheel | rad/s |
v_vec | velocity | m/s |
v_lat | Velocity in lateral direction | m/s |
v_long | Velocity in longitudinal direction | m/s |
v_slip_long | Slip velocity in longitudinal direction | m/s |
v_slip_lat | Slip velocity in lateral direction | m/s |
v_slip | Slip velocity, norm of component slip velocities | m/s |
f | Total traction force | N |
f_lat | Lateral force | N |
f_long | Longitudinal force | N |
fN | Base normal load | N |
vAdhesion | Adhesion velocity | m/s |
vSlide | Sliding velocity | m/s |
Behavior
Dict{MIME{Symbol("text/plain")}, String} with 1 entry: MIME type text/plain => "Error displaying result"
Source
"""
Slip-based wheel joint with slip-dependent friction characteristics.
Models the behavior of a wheel rolling on an x,y-plane whose contact patch has
slip-dependent friction. The driving direction (at phi=0) is given by parameter `r`.
The slip is decomposed into lateral and longitudinal components. For low rolling
velocity, a dry-friction model is used. The friction force is computed using
`MultibodyComponents.limit_S_triple` for smooth transitions between adhesion and sliding.
Connectors:
- `frame_a`: 2D frame for steering on the plane
- `flange_a`: 1D rotational flange for wheel rolling actuation
- `dynamicLoad`: Input for dynamic component of normal load
"""
component SlipBasedWheelJoint
extends MultibodyComponents.Renderable(color = [0.1, 0.1, 0.1, 1])
frame_a = Frame2D() {
"Dyad": {
"placement": {
"diagram": {"iconName": "default", "x1": 450, "y1": 50, "x2": 550, "y2": 150, "rot": 0}
},
"tags": []
}
}
flange_a = Spline() {
"Dyad": {
"placement": {
"diagram": {"iconName": "default", "x1": 950, "y1": 450, "x2": 1050, "y2": 550, "rot": 0}
},
"tags": []
}
}
dynamicLoad = RealInput() {
"Dyad": {
"placement": {
"diagram": {"iconName": "default", "x1": -50, "y1": 450, "x2": 50, "y2": 550, "rot": 0}
},
"tags": []
}
}
"Tire shape (main cylinder)"
tire_shape = MultibodyComponents.CylinderShape(render = render, color = [0.1, 0.1, 0.1, 1.0])
"Rim shape 1 (cross cylinder showing rotation)"
rim1_shape = MultibodyComponents.CylinderShape(render = render, color = [0.8, 0.8, 0.8, 1.0])
"Rim shape 2 (cross cylinder at 90 degrees)"
rim2_shape = MultibodyComponents.CylinderShape(render = render, color = [0.8, 0.8, 0.8, 1.0])
"Driving direction of the wheel at angle phi = 0"
parameter r::Real[2] = [1, 0]
"Base normal load"
parameter N::Dyad.Force
"Minimum adhesion velocity"
parameter vAdhesion_min::Velocity
"Minimum sliding velocity"
parameter vSlide_min::Velocity
"Adhesion slippage"
parameter sAdhesion::Real
"Sliding slippage"
parameter sSlide::Real
"Friction coefficient at adhesion"
parameter mu_A::Real
"Friction coefficient at sliding"
parameter mu_S::Real
"Radius of the wheel"
parameter radius::Length = 0.1
"Diameter of the rim cylinders"
parameter rim_diameter::Real = 0.1
"Width of the wheel"
parameter wheel_width::Real = 0.06
"z-position of the wheel in animations"
parameter z_position::Real = 0
"Unit vector in direction of r resolved w.r.t. inertial frame"
variable e0::Real[2]
"wheel angle"
variable phi_roll::Angle
"Roll velocity of wheel"
variable w_roll::AngularVelocity
"velocity"
variable v_vec::Velocity[2]
"Velocity in lateral direction"
variable v_lat::Velocity
"Velocity in longitudinal direction"
variable v_long::Velocity
"Slip velocity in longitudinal direction"
variable v_slip_long::Velocity
"Slip velocity in lateral direction"
variable v_slip_lat::Velocity
"Slip velocity, norm of component slip velocities"
variable v_slip::Velocity
"Total traction force"
variable f::Dyad.Force
"Lateral force"
variable f_lat::Dyad.Force
"Longitudinal force"
variable f_long::Dyad.Force
"Base normal load"
variable fN::Dyad.Force
"Adhesion velocity"
variable vAdhesion::Velocity
"Sliding velocity"
variable vSlide::Velocity
relations
# Unit vector in driving direction resolved in world frame
e0 = [[cos(frame_a.phi), -sin(frame_a.phi)], [sin(frame_a.phi), cos(frame_a.phi)]] * (r / sqrt(adjoint(r) * r))
# Velocity of the wheel center
v_vec = [der(frame_a.x), der(frame_a.y)]
# Wheel angle coupling
phi_roll = flange_a.phi
w_roll = der(phi_roll)
# Decompose velocity into longitudinal and lateral
v_long = dot(v_vec, e0)
v_lat = -v_vec[1] * e0[2] + v_vec[2] * e0[1]
# Slip velocities
v_slip_lat = v_lat
v_slip_long = v_long - radius * w_roll
v_slip = sqrt(v_slip_long ^ 2 + v_slip_lat ^ 2) + 0.0001
# Flange torque from longitudinal force
0 = flange_a.tau + f_long * radius
# No torque on the 2D frame
frame_a.tau = 0
# Velocity-dependent adhesion/slide thresholds
vAdhesion = max(vAdhesion_min, sAdhesion * abs(radius * w_roll))
vSlide = max(vSlide_min, sSlide * abs(radius * w_roll))
# Normal force (base + dynamic load, clamped to non-negative)
fN = max(0, N + dynamicLoad)
# Total friction force from slip curve
f = fN * MultibodyComponents.limit_S_triple(vAdhesion, vSlide, mu_A, mu_S, v_slip)
# Distribute friction force proportionally to slip components
f_long = f * v_slip_long / v_slip
f_lat = f * v_slip_lat / v_slip
# Frame force equations: project onto world axes via e0
f_long = dot([frame_a.fx, frame_a.fy], e0)
f_lat = dot([frame_a.fy, -frame_a.fx], e0)
# Tire shape: cylinder along the axle (perpendicular to driving direction e0)
tire_shape.r = [frame_a.x, frame_a.y, z_position]
tire_shape.R = MultibodyComponents.RR(MultibodyComponents.nullrotation())
tire_shape.r_shape = -0.03 * [-e0[2], e0[1], 0]
tire_shape.length_direction = [-e0[2], e0[1], 0]
tire_shape.width_direction = [0, 0, 1]
tire_shape.length = wheel_width
tire_shape.width = radius * 2
tire_shape.height = radius * 2
# Rim 1: cross cylinder that rotates with the wheel around the axle
rim1_shape.r = [frame_a.x, frame_a.y, z_position]
rim1_shape.R = MultibodyComponents.planar_rotation([-e0[2], e0[1], 0], -phi_roll, -w_roll)
rim1_shape.r_shape = [0, 0, -radius]
rim1_shape.length_direction = [0, 0, 1]
rim1_shape.width_direction = [1, 0, 0]
rim1_shape.length = radius * 2
rim1_shape.width = rim_diameter
rim1_shape.height = rim_diameter
# Rim 2: same but offset by 90 degrees
rim2_shape.r = [frame_a.x, frame_a.y, z_position]
rim2_shape.R = MultibodyComponents.planar_rotation([-e0[2], e0[1], 0], -phi_roll + 3.14159265358979 / 2, -w_roll)
rim2_shape.r_shape = [0, 0, -radius]
rim2_shape.length_direction = [0, 0, 1]
rim2_shape.width_direction = [1, 0, 0]
rim2_shape.length = radius * 2
rim2_shape.width = rim_diameter
rim2_shape.height = rim_diameter
metadata {
"Dyad": {
"icons": {"default": "dyad://MultibodyComponents/SlipBasedWheelJoint.svg"},
"labels": [
{
"label": "$(instance)",
"x": 500,
"y": 900,
"rot": 0,
"attrs": {"font-size": "160"}
}
]
}
}
endFlattened Source
"""
Slip-based wheel joint with slip-dependent friction characteristics.
Models the behavior of a wheel rolling on an x,y-plane whose contact patch has
slip-dependent friction. The driving direction (at phi=0) is given by parameter `r`.
The slip is decomposed into lateral and longitudinal components. For low rolling
velocity, a dry-friction model is used. The friction force is computed using
`MultibodyComponents.limit_S_triple` for smooth transitions between adhesion and sliding.
Connectors:
- `frame_a`: 2D frame for steering on the plane
- `flange_a`: 1D rotational flange for wheel rolling actuation
- `dynamicLoad`: Input for dynamic component of normal load
"""
component SlipBasedWheelJoint
parameter render::Boolean = true
parameter color::Real[4] = [0.5, 0.5, 0.5, 1.0]
parameter specular_coefficient::Real = 0.7
frame_a = Frame2D() {
"Dyad": {
"placement": {
"diagram": {"iconName": "default", "x1": 450, "y1": 50, "x2": 550, "y2": 150, "rot": 0}
},
"tags": []
}
}
flange_a = Spline() {
"Dyad": {
"placement": {
"diagram": {"iconName": "default", "x1": 950, "y1": 450, "x2": 1050, "y2": 550, "rot": 0}
},
"tags": []
}
}
dynamicLoad = RealInput() {
"Dyad": {
"placement": {
"diagram": {"iconName": "default", "x1": -50, "y1": 450, "x2": 50, "y2": 550, "rot": 0}
},
"tags": []
}
}
"Tire shape (main cylinder)"
tire_shape = MultibodyComponents.CylinderShape(render = render, color = [0.1, 0.1, 0.1, 1.0])
"Rim shape 1 (cross cylinder showing rotation)"
rim1_shape = MultibodyComponents.CylinderShape(render = render, color = [0.8, 0.8, 0.8, 1.0])
"Rim shape 2 (cross cylinder at 90 degrees)"
rim2_shape = MultibodyComponents.CylinderShape(render = render, color = [0.8, 0.8, 0.8, 1.0])
"Driving direction of the wheel at angle phi = 0"
parameter r::Real[2] = [1, 0]
"Base normal load"
parameter N::Dyad.Force
"Minimum adhesion velocity"
parameter vAdhesion_min::Velocity
"Minimum sliding velocity"
parameter vSlide_min::Velocity
"Adhesion slippage"
parameter sAdhesion::Real
"Sliding slippage"
parameter sSlide::Real
"Friction coefficient at adhesion"
parameter mu_A::Real
"Friction coefficient at sliding"
parameter mu_S::Real
"Radius of the wheel"
parameter radius::Length = 0.1
"Diameter of the rim cylinders"
parameter rim_diameter::Real = 0.1
"Width of the wheel"
parameter wheel_width::Real = 0.06
"z-position of the wheel in animations"
parameter z_position::Real = 0
"Unit vector in direction of r resolved w.r.t. inertial frame"
variable e0::Real[2]
"wheel angle"
variable phi_roll::Angle
"Roll velocity of wheel"
variable w_roll::AngularVelocity
"velocity"
variable v_vec::Velocity[2]
"Velocity in lateral direction"
variable v_lat::Velocity
"Velocity in longitudinal direction"
variable v_long::Velocity
"Slip velocity in longitudinal direction"
variable v_slip_long::Velocity
"Slip velocity in lateral direction"
variable v_slip_lat::Velocity
"Slip velocity, norm of component slip velocities"
variable v_slip::Velocity
"Total traction force"
variable f::Dyad.Force
"Lateral force"
variable f_lat::Dyad.Force
"Longitudinal force"
variable f_long::Dyad.Force
"Base normal load"
variable fN::Dyad.Force
"Adhesion velocity"
variable vAdhesion::Velocity
"Sliding velocity"
variable vSlide::Velocity
relations
# Unit vector in driving direction resolved in world frame
e0 = [[cos(frame_a.phi), -sin(frame_a.phi)], [sin(frame_a.phi), cos(frame_a.phi)]] * (r / sqrt(adjoint(r) * r))
# Velocity of the wheel center
v_vec = [der(frame_a.x), der(frame_a.y)]
# Wheel angle coupling
phi_roll = flange_a.phi
w_roll = der(phi_roll)
# Decompose velocity into longitudinal and lateral
v_long = dot(v_vec, e0)
v_lat = -v_vec[1] * e0[2] + v_vec[2] * e0[1]
# Slip velocities
v_slip_lat = v_lat
v_slip_long = v_long - radius * w_roll
v_slip = sqrt(v_slip_long ^ 2 + v_slip_lat ^ 2) + 0.0001
# Flange torque from longitudinal force
0 = flange_a.tau + f_long * radius
# No torque on the 2D frame
frame_a.tau = 0
# Velocity-dependent adhesion/slide thresholds
vAdhesion = max(vAdhesion_min, sAdhesion * abs(radius * w_roll))
vSlide = max(vSlide_min, sSlide * abs(radius * w_roll))
# Normal force (base + dynamic load, clamped to non-negative)
fN = max(0, N + dynamicLoad)
# Total friction force from slip curve
f = fN * MultibodyComponents.limit_S_triple(vAdhesion, vSlide, mu_A, mu_S, v_slip)
# Distribute friction force proportionally to slip components
f_long = f * v_slip_long / v_slip
f_lat = f * v_slip_lat / v_slip
# Frame force equations: project onto world axes via e0
f_long = dot([frame_a.fx, frame_a.fy], e0)
f_lat = dot([frame_a.fy, -frame_a.fx], e0)
# Tire shape: cylinder along the axle (perpendicular to driving direction e0)
tire_shape.r = [frame_a.x, frame_a.y, z_position]
tire_shape.R = MultibodyComponents.RR(MultibodyComponents.nullrotation())
tire_shape.r_shape = -0.03 * [-e0[2], e0[1], 0]
tire_shape.length_direction = [-e0[2], e0[1], 0]
tire_shape.width_direction = [0, 0, 1]
tire_shape.length = wheel_width
tire_shape.width = radius * 2
tire_shape.height = radius * 2
# Rim 1: cross cylinder that rotates with the wheel around the axle
rim1_shape.r = [frame_a.x, frame_a.y, z_position]
rim1_shape.R = MultibodyComponents.planar_rotation([-e0[2], e0[1], 0], -phi_roll, -w_roll)
rim1_shape.r_shape = [0, 0, -radius]
rim1_shape.length_direction = [0, 0, 1]
rim1_shape.width_direction = [1, 0, 0]
rim1_shape.length = radius * 2
rim1_shape.width = rim_diameter
rim1_shape.height = rim_diameter
# Rim 2: same but offset by 90 degrees
rim2_shape.r = [frame_a.x, frame_a.y, z_position]
rim2_shape.R = MultibodyComponents.planar_rotation([-e0[2], e0[1], 0], -phi_roll + 3.14159265358979 / 2, -w_roll)
rim2_shape.r_shape = [0, 0, -radius]
rim2_shape.length_direction = [0, 0, 1]
rim2_shape.width_direction = [1, 0, 0]
rim2_shape.length = radius * 2
rim2_shape.width = rim_diameter
rim2_shape.height = rim_diameter
metadata {
"Dyad": {
"icons": {"default": "dyad://MultibodyComponents/SlipBasedWheelJoint.svg"},
"labels": [
{
"label": "$(instance)",
"x": 500,
"y": 900,
"rot": 0,
"attrs": {"font-size": "160"}
}
]
}
}
endTest Cases
No test cases defined.
Related
Examples
Experiments
Analyses