[docs]classBallBallFrictionModel(StrEnum):"""An Enum for different ball-ball friction models Attributes: AVERAGE: The friction is calculated as the average of ball-ball sliding friction of the two balls. ALCIATORE: Friction fit curve :math:`u_b = a + b e^{ -c v_{rel} }` used in David Alciatore's TP A-14. """AVERAGE=auto()ALCIATORE=auto()
classBallBallFrictionStrategy(Protocol):"""Ball-ball friction models must satisfy this protocol"""defcalculate_friction(self,ball1:Ball,ball2:Ball)->float:"""This method calculates ball-ball friction"""...@attrs.defineclassAlciatoreBallBallFriction:"""Friction fit curve :math:`u_b = a + b * e^{ -c * v_{rel} }` used in David Alciatore's TP A-14"""a:float=9.951e-3b:float=0.108c:float=1.088model:BallBallFrictionModel=attrs.field(default=BallBallFrictionModel.ALCIATORE,init=False,repr=False)defcalculate_friction(self,ball1:Ball,ball2:Ball)->float:unit_normal=ptmath.unit_vector(ball2.xyz-ball1.xyz)v1_c=tangent_surface_velocity(ball1.state.rvw,unit_normal,ball1.params.R)v2_c=tangent_surface_velocity(ball2.state.rvw,-unit_normal,ball2.params.R)relative_surface_speed=ptmath.norm3d(v1_c-v2_c)returnself.a+self.b*math.exp(-self.c*relative_surface_speed)@attrs.defineclassAverageBallBallFriction:model:BallBallFrictionModel=attrs.field(default=BallBallFrictionModel.AVERAGE,init=False,repr=False)defcalculate_friction(self,ball1:Ball,ball2:Ball)->float:return(ball1.params.u_b+ball2.params.u_b)/2ball_ball_friction_models:dict[BallBallFrictionModel,type[BallBallFrictionStrategy]]={BallBallFrictionModel.AVERAGE:AverageBallBallFriction,BallBallFrictionModel.ALCIATORE:AlciatoreBallBallFriction,}