Mathias - Here’s another source of information that you might find useful: 
https://academic.oup.com/mnras/article/498/1/1062/5893804

Dan
---------------------------------------------
Bernard A. and Frances M. Weideman Professor
NVIDIA CUDA Fellow
Department of Mechanical Engineering
Department of Computer Science
University of Wisconsin - Madison
4150ME, 1513 University Avenue
Madison, WI 53706-1572
608 772 0914
http://sbel.wisc.edu/
http://projectchrono.org/
---------------------------------------------

From: [email protected] <[email protected]> On Behalf 
Of mathias dalby larsen
Sent: Wednesday, April 16, 2025 1:25 AM
To: ProjectChrono <[email protected]>
Subject: [chrono] Re: Help with Rolling Friction Behavior in PyChrono SMC Model

Thank you this was exactly what i needed.
onsdag den 26. marts 2025 kl. 20.09.35 UTC+1 skrev Radu Serban:
Hi Mathias,

The most complete SMC model is implemented in the Chrono::Multicore module.  I 
never got around to bring up the corresponding SMC model in the core Chrono 
module to the same level (although that is on one of the many TODO lists I 
keep).
Compared to the Chrono core implementation (see the implementation in 
ChContactSMC.h<https://urldefense.com/v3/__https:/github.com/projectchrono/chrono/blob/ca60083b2de78732f398adb895f1540ccfadd8b2/src/chrono/physics/ChContactSMC.h*L45__;Iw!!Mak6IKo!JsKD6Y-yJ9a3xuK2mDAsOhZgZVUoI3KeQ1hJJHWfZDy2pcwRjW0KHtP1S0qzEkX6jLZs-SKuRz6lZ3iuL6eOZUOwiA$>),
 the SMC contact model in Chrono::Multicore (see 
ChIterativeSolverMulticoreSMC.cpp<https://urldefense.com/v3/__https:/github.com/projectchrono/chrono/blob/ca60083b2de78732f398adb895f1540ccfadd8b2/src/chrono_multicore/solver/ChIterativeSolverMulticoreSMC.cpp*L56__;Iw!!Mak6IKo!JsKD6Y-yJ9a3xuK2mDAsOhZgZVUoI3KeQ1hJJHWfZDy2pcwRjW0KHtP1S0qzEkX6jLZs-SKuRz6lZ3iuL6eHvVfbMQ$>)
 has the following two main additional features:

  *   A multi-step tangential displacement model (see this 
paper<https://urldefense.com/v3/__https:/www.researchgate.net/publication/281538010_On_the_Importance_of_Displacement_History_in_Soft-Body_Contact_Models__;!!Mak6IKo!JsKD6Y-yJ9a3xuK2mDAsOhZgZVUoI3KeQ1hJJHWfZDy2pcwRjW0KHtP1S0qzEkX6jLZs-SKuRz6lZ3iuL6dvqSpzlA$>
 for details on why that is important in SMC); and
  *   Rolling and spinning friction

With the above, the kind of simulations you are interested in will give the 
expect results. In fact, such behaviors are implemented and tested in a series 
of tests that are included in the Chrono distribution: see the unit tests for 
multicore SMC 
contact<https://urldefense.com/v3/__https:/github.com/projectchrono/chrono/tree/main/src/tests/unit_tests/smc_contact/multicore__;!!Mak6IKo!JsKD6Y-yJ9a3xuK2mDAsOhZgZVUoI3KeQ1hJJHWfZDy2pcwRjW0KHtP1S0qzEkX6jLZs-SKuRz6lZ3iuL6eFD4D46Q$>.

Having said all of that, please note that the Chrono::Multicore module is 
currently *not* SWIG wrapped and as such not available through PyChrono.

Best,
Radu


From: [email protected] <[email protected]> On Behalf Of 
mathias dalby larsen
Sent: Monday, March 24, 2025 10:12 AM
To: [email protected]
Subject: [chrono] Help with Rolling Friction Behavior in PyChrono SMC Model

Hello,
I'm currently working on a PyChrono model using the SMC (Smooth Contact) method 
to demonstrate how rolling friction behaves in simulations. The setup I'm 
aiming to replicate is illustrated in the attached diagram, where the goal is 
to observe different states of motion: stationary, pure rolling, pure sliding, 
and combined rolling and sliding (as shown in the second image).
However, in my implementation, I am only able to achieve a combination of 
rolling and sliding, when chaning the friction values. Additionally, even with 
the wall set at a 0° incline and a friction coefficient of 0.25, the sphere 
continues to roll indefinitely instead of coming to rest.
Any guidance or insights into what might be wrong with my setup would be 
greatly appreciated.
PS.From my countless tests, it seems like the material data is only applied 
during the first contact, however, I'm not quite sure.
Best regards,
Mathias Dalby Larsen

Code used
import pychrono as chrono
import pychrono.irrlicht as chronoirr
import numpy as np

# Simulation Parameters
sphere_radius = 0.2  # meters
sphere_mass = 5.0  # kg
initial_velocity = 0.0  # m/s (parallel to incline, pointing up)
incline_angle = 5  # degrees (fix the floor at this angle)
static_friction = 0.25  # μs
kinetic_friction = 0.25 # μk
Rolling_friction = 0.50 # Rolling friction coefficient
measure_time = 4.5  # Time after which velocities will be measured
sim_time = 10
wall_depth = 15.0  # From wall dimensions

# Convert incline angle to radians
alpha_rad = np.radians(incline_angle)

# Create system
sys = chrono.ChSystemSMC()

# Check the current normal contact force model
print("Normal contact force before setting:", sys.GetContactForceModel())  # 
Should return default value

# Try setting it to Hooke
#sys.SetContactForceModel(chrono.ChSystemSMC.Hooke)  # Set Hooke model 
explicitly
# Try setting it to Hertz
sys.SetContactForceModel(chrono.ChSystemSMC.Hertz)  # Set Hertz model explicitly
# Try setting it to PlainCoulomb
#sys.SetContactForceModel(chrono.ChSystemSMC.PlainCoulomb)  # Set PlainCoulomb 
model explicitly
# Try setting it to Flores
#sys.SetContactForceModel(chrono.ChSystemSMC.Flores)  # Set Flores model 
explicitly

# Check if it changed
print("Normal contact force after setting:", sys.GetContactForceModel())  # 
Should print 1 (Hertz)

# Check the current tangential contact force model
print("Tangential contact force before setting:", 
sys.GetTangentialDisplacementModel())  # Should return default value

# Try setting it to None
#sys.SetTangentialDisplacementModel(chrono.ChSystemSMC._None)  # Set None model 
explicitly
# Try setting it to OneStep
#sys.SetTangentialDisplacementModel(chrono.ChSystemSMC.OneStep)  # Set OneStep 
model explicitly
# Try setting it to MultiStep
sys.SetTangentialDisplacementModel(chrono.ChSystemSMC.MultiStep)  # Set 
MultiStep model explicitly

# Check if it changed
print("Tangential contact force after setting:", 
sys.GetTangentialDisplacementModel())  # Should print 1 (Hertz)

# Create Collision detection system and solver
sys.SetCollisionSystemType(chrono.ChCollisionSystem.Type_BULLET)
sys.SetSolverType(chrono.ChSolver.Type_BARZILAIBORWEIN)
sys.GetSolver().AsIterative().SetMaxIterations(200)
sys.UseMaterialProperties(True)

# Set gravitational acceleration
sys.SetGravitationalAcceleration(chrono.ChVector3d(0, -9.81, 0))

# Create a material for the inclined wall
wall_mat = chrono.ChContactMaterialSMC()
wall_mat.SetStaticFriction(static_friction)
wall_mat.SetSlidingFriction(kinetic_friction)
wall_mat.SetRollingFriction(Rolling_friction/2)
wall_mat.SetRestitution(0.50)
wall_mat.SetYoungModulus(1e9)
wall_mat.SetPoissonRatio(0.3)
wall_mat.SetSpinningFriction(Rolling_friction * 20.0)
wall_mat.SetKn(1e9)
wall_mat.SetKt(1e9)

# Create the inclined wall (static floor)
wall = chrono.ChBodyAuxRef()
wall.SetFixed(True)
wall.SetInertiaXX(chrono.ChVector3d(0.1, 0.1, 0.1))
wall.EnableCollision(True)

# Apply correct rotation using `QuatFromAngleAxis`
rotation_axis = chrono.ChVector3d(1, 0, 0)  # Rotate around X-axis
wall_rotation = chrono.QuatFromAngleAxis(-alpha_rad, rotation_axis)
wall.SetRot(wall_rotation)

# Position the wall correctly
wall.SetPos(chrono.ChVector3d(0, 0, 0))

# Add collision shape
wall_shape = chrono.ChCollisionShapeBox(wall_mat, 2, 0.1, wall_depth)
wall.AddCollisionShape(wall_shape)

# Add visual representation
wall_vis = chrono.ChVisualShapeBox(2, 0.1, wall_depth)
wall_vis.SetColor(chrono.ChColor(1, 0, 0))  # Red for visibility
wall.AddVisualShape(wall_vis)

# Add to system
sys.Add(wall)

# Create the rolling sphere
sphere = chrono.ChBody()
sphere.SetMass(sphere_mass)
sphere.SetInertiaXX(chrono.ChVector3d(2/5 * sphere_mass * sphere_radius**2,
                                     2/5 * sphere_mass * sphere_radius**2,
                                     2/5 * sphere_mass * sphere_radius**2))

# Function to calculate the circle's center position
def get_circle_position(radius, theta):
    y_c = -(radius+0.05) * np.sin(theta)
    z_c = (radius+0.05) * np.cos(theta)
    return y_c, z_c
# Get the position of the circle center
circle_pos = get_circle_position(sphere_radius, alpha_rad)
sphere.SetPos(chrono.ChVector3d(0, circle_pos[1]+0.01, circle_pos[0]+0.01))

# Set initial velocity along the incline
sphere.SetPosDt(chrono.ChVector3d(0,initial_velocity * np.sin(alpha_rad),
                                 initial_velocity * np.cos(alpha_rad)))

# Add sphere collision and visualization
sphere_mat = chrono.ChContactMaterialSMC()
sphere_mat.SetStaticFriction(static_friction)
sphere_mat.SetSlidingFriction(kinetic_friction)
sphere_mat.SetRollingFriction(Rolling_friction/2)
sphere_mat.SetRestitution(0.50)
sphere_mat.SetYoungModulus(1e9)
sphere_mat.SetPoissonRatio(0.3)
sphere_mat.SetSpinningFriction(Rolling_friction * 20.0)
sphere_mat.SetKn(1e9)
sphere_mat.SetKt(1e9)

# Assign material directly to the body
sphere_shape = chrono.ChCollisionShapeSphere(sphere_mat, sphere_radius)
sphere.AddCollisionShape(sphere_shape)
sphere.EnableCollision(True)

sphere_vis = chrono.ChVisualShapeSphere(sphere_radius)
sphere_vis.SetColor(chrono.ChColor(1, 1, 0))  # Yellow sphere
sphere.AddVisualShape(sphere_vis)

# Add sphere to system
sys.Add(sphere)

# Set up the Irrlicht visualization
vis = chronoirr.ChVisualSystemIrrlicht()
vis.AttachSystem(sys)
vis.SetWindowSize(1024, 768)
vis.SetWindowTitle('Rolling Ball on Inclined Wall')
vis.Initialize()
vis.AddSkyBox()
vis.AddCamera(chrono.ChVector3d(-2, 0, -0.5), chrono.ChVector3d(0, 0, 0))
vis.AddTypicalLights()

# Simulation loop
time = 0.0
dt = 10e-6  # Keep accurate physics time step
render_interval = 1000  # Render every 10th step for 10x faster visual effect
step_count = 0
realtime_timer = chrono.ChRealtimeStepTimer()
lin_vel = None

while vis.Run():
    if step_count % render_interval == 0:  # Render only every 10th step
        vis.BeginScene()
        vis.Render()
        vis.EndScene()

    # Advance simulation
    sys.DoStepDynamics(dt)
    time += dt
    step_count += 1

    # Adjust real-time sync for 10x faster visualization
    if step_count % render_interval == 0:
        realtime_timer.Spin(dt * render_interval)

    # Measure velocities at exactly measure_time
    if time >= measure_time and lin_vel is None:  # Only measure once
        lin_vel = sphere.GetLinVel().Length()
        ang_acc = sphere.GetAngVelLocal().Length()  # Angular acceleration 
magnitude
        Rollslide = abs((sphere_radius * ang_acc))
        print(f"Measured at {measure_time}s -> Lin Vel: {lin_vel}, Rot Change: 
{ang_acc}, Rot rollslide: {Rollslide}")
        force = sphere.GetContactForce()
        torque = sphere.GetContactTorque()
        print(f"Time: {time:.3f} - Contact Force: {force.Length()}, Contact 
Torque: {torque.Length()}")


[https://groups.google.com/group/projectchrono/attach/5e91f84ca3335/image001.png?part=0.1&view=1][https://groups.google.com/group/projectchrono/attach/5e91f84ca3335/image002.png?part=0.2&view=1]
--
You received this message because you are subscribed to the Google Groups 
"ProjectChrono" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion visit 
https://groups.google.com/d/msgid/projectchrono/SA1P220MB1275A64A7BE884B285864FFDAEA42%40SA1P220MB1275.NAMP220.PROD.OUTLOOK.COM<https://urldefense.com/v3/__https:/groups.google.com/d/msgid/projectchrono/SA1P220MB1275A64A7BE884B285864FFDAEA42*40SA1P220MB1275.NAMP220.PROD.OUTLOOK.COM?utm_medium=email&utm_source=footer__;JQ!!Mak6IKo!IBQgS7fUmMwUVLU_nkkK6qZGuHR5easzklZgtkSA9NDWNMtz9r7RJ4VlvVWz7UrhEy-iiRS-1wtwgxUv7-hPT1GkFA$>.
--
You received this message because you are subscribed to the Google Groups 
"ProjectChrono" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to 
[email protected]<mailto:[email protected]>.
To view this discussion visit 
https://groups.google.com/d/msgid/projectchrono/64c9dcfe-60fc-4959-82c6-16cb6e9d92a3n%40googlegroups.com<https://urldefense.com/v3/__https:/groups.google.com/d/msgid/projectchrono/64c9dcfe-60fc-4959-82c6-16cb6e9d92a3n*40googlegroups.com?utm_medium=email&utm_source=footer__;JQ!!Mak6IKo!JsKD6Y-yJ9a3xuK2mDAsOhZgZVUoI3KeQ1hJJHWfZDy2pcwRjW0KHtP1S0qzEkX6jLZs-SKuRz6lZ3iuL6eOPWgK9w$>.

-- 
You received this message because you are subscribed to the Google Groups 
"ProjectChrono" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion visit 
https://groups.google.com/d/msgid/projectchrono/DM8PR06MB770395BFBE2DED6FE3E1F9B3B1BD2%40DM8PR06MB7703.namprd06.prod.outlook.com.

Reply via email to