Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import numpy as np
- import math
- from enum import Enum
- class FollowerType(Enum):
- ROLLER = "roller"
- KNIFE_EDGE = "knife_edge"
- FLAT_FACE = "flat_face"
- class MotionType(Enum):
- SHM = "simple_harmonic"
- CYCLOIDAL = "cycloidal"
- UNIFORM = "uniform"
- def calculate_lift_motion(fraction, motion_type):
- """Calculate lift motion displacement"""
- if motion_type == MotionType.SHM:
- return (1 - np.cos(np.pi * fraction)) / 2
- elif motion_type == MotionType.CYCLOIDAL:
- return fraction - (1/(2*np.pi)) * np.sin(2*np.pi*fraction)
- elif motion_type == MotionType.UNIFORM:
- if fraction <= 0.5:
- return 2 * fraction * fraction
- else:
- return 1 - 2 * (1 - fraction) * (1 - fraction)
- return 0
- def calculate_fall_motion(fraction, motion_type):
- """Calculate fall motion displacement"""
- if motion_type == MotionType.SHM:
- return (1 + np.cos(np.pi * fraction)) / 2
- elif motion_type == MotionType.CYCLOIDAL:
- return 1 - (fraction - (1/(2*np.pi)) * np.sin(2*np.pi*fraction))
- elif motion_type == MotionType.UNIFORM:
- if fraction <= 0.5:
- return 1 - 2 * fraction * fraction
- else:
- return 2 * (1 - fraction) * (1 - fraction)
- return 0
- def generate_cam_profile(
- follower_type=FollowerType.ROLLER,
- base_circle_radius=25,
- roller_radius=12.5,
- follower_width=30,
- lift=40,
- lift_angle=120,
- fall_angle=150,
- pre_lift_dwell_angle=30, # Changed from dwell_angle to pre_lift_dwell_angle
- offset=12.5,
- lift_motion=MotionType.SHM,
- fall_motion=MotionType.UNIFORM,
- num_points=720):
- # Calculate the post-fall dwell angle
- total_motion_angle = lift_angle + fall_angle
- post_fall_dwell_angle = 360 - (pre_lift_dwell_angle + total_motion_angle)
- # Arrays to store points
- theta = np.linspace(0, 2*np.pi, num_points)
- x = np.zeros(num_points)
- y = np.zeros(num_points)
- z = np.zeros(num_points)
- for i, angle in enumerate(theta):
- angle_deg = np.rad2deg(angle)
- # First dwell (pre-lift)
- if angle_deg <= pre_lift_dwell_angle:
- displacement = 0
- # Lift period
- elif angle_deg <= (pre_lift_dwell_angle + lift_angle):
- lift_fraction = (angle_deg - pre_lift_dwell_angle) / lift_angle
- displacement = lift * \
- calculate_lift_motion(lift_fraction, lift_motion)
- # Dwell at maximum lift
- elif angle_deg <= (pre_lift_dwell_angle + lift_angle + post_fall_dwell_angle):
- displacement = lift
- # Fall period
- else:
- fall_fraction = (angle_deg - (pre_lift_dwell_angle +
- lift_angle + post_fall_dwell_angle)) / fall_angle
- displacement = lift * \
- calculate_fall_motion(fall_fraction, fall_motion)
- # Calculate basic profile coordinates
- r = base_circle_radius + displacement
- x[i] = r * np.cos(angle) + offset * np.sin(angle)
- y[i] = r * np.sin(angle) - offset * np.cos(angle)
- z[i] = 0
- # Apply follower-specific modifications
- if follower_type == FollowerType.ROLLER:
- for i in range(num_points):
- angle = theta[i]
- x[i] += roller_radius * np.cos(angle)
- y[i] += roller_radius * np.sin(angle)
- elif follower_type == FollowerType.KNIFE_EDGE:
- pass # Basic profile is used for knife edge
- elif follower_type == FollowerType.FLAT_FACE:
- for i in range(num_points):
- angle = theta[i]
- tangent_angle = np.arctan2(y[i], x[i])
- x[i] += (follower_width/2) * np.sin(tangent_angle)
- y[i] -= (follower_width/2) * np.cos(tangent_angle)
- return x, y, z
- def save_to_adams(x, y, z, filename='cam_profile.txt'):
- """Save the profile points in Adams View compatible format"""
- with open(filename, 'w') as f:
- for i in range(len(x)):
- f.write(f"{x[i]:.6f}, {y[i]:.6f}, {z[i]:.6f}\n")
- print(f"Profile saved to {filename}")
- # Example usage
- def main():
- # Example 1: Roller follower with SHM lift and Uniform fall
- x, y, z = generate_cam_profile(
- follower_type=FollowerType.ROLLER,
- base_circle_radius=25,
- roller_radius=12.5,
- lift=40,
- lift_angle=120,
- fall_angle=150,
- pre_lift_dwell_angle=30,
- offset=12.5,
- lift_motion=MotionType.SHM,
- fall_motion=MotionType.UNIFORM
- )
- save_to_adams(x, y, z, 'roller_cam.txt')
- # Example 2: Knife edge with cycloidal motion
- x, y, z = generate_cam_profile(
- follower_type=FollowerType.KNIFE_EDGE,
- base_circle_radius=50,
- lift=40,
- lift_angle=100,
- fall_angle=90,
- pre_lift_dwell_angle=80,
- offset=0,
- lift_motion=MotionType.UNIFORM,
- fall_motion=MotionType.UNIFORM
- )
- save_to_adams(x, y, z, 'knife_edge_cam.txt')
- # Example 3: Flat face with uniform motion
- x, y, z = generate_cam_profile(
- follower_type=FollowerType.FLAT_FACE,
- base_circle_radius=25,
- follower_width=30,
- lift=40,
- lift_angle=120,
- fall_angle=150,
- pre_lift_dwell_angle=30,
- offset=0,
- lift_motion=MotionType.UNIFORM,
- fall_motion=MotionType.UNIFORM
- )
- save_to_adams(x, y, z, 'flat_face_cam.txt')
- if __name__ == "__main__":
- main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement