Advertisement
NaroxEG

Cam Profile Coordinates Executer

Dec 20th, 2024 (edited)
35
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.53 KB | None | 0 0
  1. import numpy as np
  2. import math
  3. from enum import Enum
  4.  
  5.  
  6. class FollowerType(Enum):
  7.     ROLLER = "roller"
  8.     KNIFE_EDGE = "knife_edge"
  9.     FLAT_FACE = "flat_face"
  10.  
  11.  
  12. class MotionType(Enum):
  13.     SHM = "simple_harmonic"
  14.     CYCLOIDAL = "cycloidal"
  15.     UNIFORM = "uniform"
  16.  
  17.  
  18. def calculate_lift_motion(fraction, motion_type):
  19.     """Calculate lift motion displacement"""
  20.     if motion_type == MotionType.SHM:
  21.         return (1 - np.cos(np.pi * fraction)) / 2
  22.     elif motion_type == MotionType.CYCLOIDAL:
  23.         return fraction - (1/(2*np.pi)) * np.sin(2*np.pi*fraction)
  24.     elif motion_type == MotionType.UNIFORM:
  25.         if fraction <= 0.5:
  26.             return 2 * fraction * fraction
  27.         else:
  28.             return 1 - 2 * (1 - fraction) * (1 - fraction)
  29.     return 0
  30.  
  31.  
  32. def calculate_fall_motion(fraction, motion_type):
  33.     """Calculate fall motion displacement"""
  34.     if motion_type == MotionType.SHM:
  35.         return (1 + np.cos(np.pi * fraction)) / 2
  36.     elif motion_type == MotionType.CYCLOIDAL:
  37.         return 1 - (fraction - (1/(2*np.pi)) * np.sin(2*np.pi*fraction))
  38.     elif motion_type == MotionType.UNIFORM:
  39.         if fraction <= 0.5:
  40.             return 1 - 2 * fraction * fraction
  41.         else:
  42.             return 2 * (1 - fraction) * (1 - fraction)
  43.     return 0
  44.  
  45.  
  46. def generate_cam_profile(
  47.         follower_type=FollowerType.ROLLER,
  48.         base_circle_radius=25,
  49.         roller_radius=12.5,
  50.         follower_width=30,
  51.         lift=40,
  52.         lift_angle=120,
  53.         fall_angle=150,
  54.         pre_lift_dwell_angle=30,  # Changed from dwell_angle to pre_lift_dwell_angle
  55.         offset=12.5,
  56.         lift_motion=MotionType.SHM,
  57.         fall_motion=MotionType.UNIFORM,
  58.         num_points=720):
  59.  
  60.     # Calculate the post-fall dwell angle
  61.     total_motion_angle = lift_angle + fall_angle
  62.     post_fall_dwell_angle = 360 - (pre_lift_dwell_angle + total_motion_angle)
  63.  
  64.     # Arrays to store points
  65.     theta = np.linspace(0, 2*np.pi, num_points)
  66.     x = np.zeros(num_points)
  67.     y = np.zeros(num_points)
  68.     z = np.zeros(num_points)
  69.  
  70.     for i, angle in enumerate(theta):
  71.         angle_deg = np.rad2deg(angle)
  72.  
  73.         # First dwell (pre-lift)
  74.         if angle_deg <= pre_lift_dwell_angle:
  75.             displacement = 0
  76.  
  77.         # Lift period
  78.         elif angle_deg <= (pre_lift_dwell_angle + lift_angle):
  79.             lift_fraction = (angle_deg - pre_lift_dwell_angle) / lift_angle
  80.             displacement = lift * \
  81.                 calculate_lift_motion(lift_fraction, lift_motion)
  82.  
  83.         # Dwell at maximum lift
  84.         elif angle_deg <= (pre_lift_dwell_angle + lift_angle + post_fall_dwell_angle):
  85.             displacement = lift
  86.  
  87.         # Fall period
  88.         else:
  89.             fall_fraction = (angle_deg - (pre_lift_dwell_angle +
  90.                              lift_angle + post_fall_dwell_angle)) / fall_angle
  91.             displacement = lift * \
  92.                 calculate_fall_motion(fall_fraction, fall_motion)
  93.  
  94.         # Calculate basic profile coordinates
  95.         r = base_circle_radius + displacement
  96.         x[i] = r * np.cos(angle) + offset * np.sin(angle)
  97.         y[i] = r * np.sin(angle) - offset * np.cos(angle)
  98.         z[i] = 0
  99.  
  100.     # Apply follower-specific modifications
  101.     if follower_type == FollowerType.ROLLER:
  102.         for i in range(num_points):
  103.             angle = theta[i]
  104.             x[i] += roller_radius * np.cos(angle)
  105.             y[i] += roller_radius * np.sin(angle)
  106.  
  107.     elif follower_type == FollowerType.KNIFE_EDGE:
  108.         pass  # Basic profile is used for knife edge
  109.  
  110.     elif follower_type == FollowerType.FLAT_FACE:
  111.         for i in range(num_points):
  112.             angle = theta[i]
  113.             tangent_angle = np.arctan2(y[i], x[i])
  114.             x[i] += (follower_width/2) * np.sin(tangent_angle)
  115.             y[i] -= (follower_width/2) * np.cos(tangent_angle)
  116.  
  117.     return x, y, z
  118.  
  119.  
  120. def save_to_adams(x, y, z, filename='cam_profile.txt'):
  121.     """Save the profile points in Adams View compatible format"""
  122.     with open(filename, 'w') as f:
  123.         for i in range(len(x)):
  124.             f.write(f"{x[i]:.6f}, {y[i]:.6f}, {z[i]:.6f}\n")
  125.     print(f"Profile saved to {filename}")
  126.  
  127. # Example usage
  128.  
  129.  
  130. def main():
  131.     # Example 1: Roller follower with SHM lift and Uniform fall
  132.     x, y, z = generate_cam_profile(
  133.         follower_type=FollowerType.ROLLER,
  134.         base_circle_radius=25,
  135.         roller_radius=12.5,
  136.         lift=40,
  137.         lift_angle=120,
  138.         fall_angle=150,
  139.         pre_lift_dwell_angle=30,
  140.         offset=12.5,
  141.         lift_motion=MotionType.SHM,
  142.         fall_motion=MotionType.UNIFORM
  143.     )
  144.     save_to_adams(x, y, z, 'roller_cam.txt')
  145.  
  146.     # Example 2: Knife edge with cycloidal motion
  147.     x, y, z = generate_cam_profile(
  148.         follower_type=FollowerType.KNIFE_EDGE,
  149.         base_circle_radius=50,
  150.         lift=40,
  151.         lift_angle=100,
  152.         fall_angle=90,
  153.         pre_lift_dwell_angle=80,
  154.         offset=0,
  155.         lift_motion=MotionType.UNIFORM,
  156.         fall_motion=MotionType.UNIFORM
  157.     )
  158.     save_to_adams(x, y, z, 'knife_edge_cam.txt')
  159.  
  160.     # Example 3: Flat face with uniform motion
  161.     x, y, z = generate_cam_profile(
  162.         follower_type=FollowerType.FLAT_FACE,
  163.         base_circle_radius=25,
  164.         follower_width=30,
  165.         lift=40,
  166.         lift_angle=120,
  167.         fall_angle=150,
  168.         pre_lift_dwell_angle=30,
  169.         offset=0,
  170.         lift_motion=MotionType.UNIFORM,
  171.         fall_motion=MotionType.UNIFORM
  172.     )
  173.     save_to_adams(x, y, z, 'flat_face_cam.txt')
  174.  
  175.  
  176. if __name__ == "__main__":
  177.     main()
  178.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement