function [link_set, R_joints, R_links, link_set_local, link_vectors_in_world, links_in_world, link_end_set, link_end_set_with_base] = planar_robot_arm_links(link_vectors, joint_angles)
    % Initialize the number of links
    n = length(link_vectors);
    
    % Initialize cell arrays for outputs
    R_joints = cell(n, 1);
    R_links = cell(n, 1);
    link_set_local = cell(n, 1);
    link_vectors_in_world = cell(n, 1);
    links_in_world = cell(n, 1);
    link_end_set = cell(n, 1);
    
    % First step: Generate rotation matrices for the joints
    for i = 1:n
        R_joints{i} = planar_rotation_set(joint_angles(i));
    end
    
    % Second step: Generate cumulative product of joint rotation matrices
    R_links{1} = R_joints{1}; % The first link's orientation is just its rotation
    for i = 2:n
        R_links{i} = R_links{i-1} * R_joints{i}; % Cumulative product
    end
    
    % Third step: Generate local link endpoints
    for i = 1:n
        link_set_local{i} = [zeros(2, 1), link_vectors{i}]; % [0; 0] and link vector
    end
    
    % Fourth step: Rotate link vectors to world coordinates
    for i = 1:n
        link_vectors_in_world{i} = R_links{i} * link_vectors{i}; % Rotate link vectors
    end
    
    % Fifth step: Calculate the world positions of the links
    for i = 1:n
        if i == 1
            links_in_world{i} = link_set_local{i}; % First link
        else
            % Previous link's end position
            prev_end_pos = link_end_set{i-1}(:, end);
            links_in_world{i} = prev_end_pos + link_vectors_in_world{i}; % Translate by previous end position
        end
    end
    
    % Sixth step: Cumulative sum of link vectors to get endpoints
    link_end_set{1} = link_vectors_in_world{1}; % First link endpoint
    for i = 2:n
        link_end_set{i} = link_end_set{i-1} + link_vectors_in_world{i}; % Cumulative sum
    end
    
    % Seventh step: Add the base point (origin) to link_end_set
    link_end_set_with_base = cell(n, 1);
    link_end_set_with_base{1} = [zeros(2, 1), link_end_set{1}]; % Origin to first endpoint
    for i = 2:n
        link_end_set_with_base{i} = [link_end_set_with_base{i-1}(:, end), link_end_set{i}]; % Append each endpoint
    end
    
    % Eighth step: Generate the final link set with the start and endpoints
    link_set = cell(n, 1);
    for i = 1:n
        link_set{i} = links_in_world{i}; % Combine the basepoint and endpoints
    end
end
link_vectors = {[1; 0], [1; 0]};
joint_angles = [pi/4; -pi/2];
link_set = planar_robot_arm_links(link_vectors, joint_angles);
disp(link_set{:});
