pythonnumpyscipylinear-algebrascipy-spatial

How do I translate the position of a moving point according to a reference point?


Given two moving points/particles with positions in cartesian coordinates x, y, z as a function of time as given bellow, how do I center one of the points and calculate the resulting positions of the second point while maintaining their relative distance and orientation constant?

# Given the absolute positions of point 1 (p1) and point 2 (p2): 
p1 = [
    [7.74, 9.48, 9.61],
    [7.02, 8.83, 9.42],
    [7.91, 9.08, 9.56],
    [8.61, 8.92, 9.50],
    [8.87, 9.35, 9.63],
    [7.77, 9.83, 9.86]
]

p2 = [
    [7.90, 10.48, 10.2],
    [8.30, 10.74, 9.59],
    [8.23, 10.24, 9.86],
    [8.15, 10.42, 9.91],
    [8.05, 10.44, 9.92],
    [8.4, 10.78, 10.04]
]

# Center p1. It does not necessarily have to be at (0, 0, 0). 
p1 = [
    [0, 0, 0], 
    [0, 0, 0], 
    [0, 0, 0],
    [0, 0, 0],
    [0, 0, 0], 
    [0, 0, 0]
]

# Translate p2 so its relative position (distance & orientation) relative to p1 remains constant. 
p2 = []

Intuitively, I'd try to find translation and rotation matrices for the conversion. I looked at scipy.spatial but could not find a solution to my problem (that I could understand, at least).

How would I try to solve this problem?

Edit 1: Both points move supposedly independently from each other, so their distance+orientation should not be constant. My goal is to test that supposition: do the points exert any influence on each other.
Specifically, I want to calculate the density of point 2 relative to point 1, but for this calculation to make sense I need point 1 fixed first. Hope this further clarifies the problem.


Solution

  • This may be a bit cryptic if you are unfamiliar with linear algebra but in essence you can manipulate the vectors to calculate the length and cylindrical rotation of the vector between the two points. It would go like this:

    import numpy as np
    from scipy import linalg
    
    p1 = [
        [7.74, 9.48, 9.61],
        [7.02, 8.83, 9.42],
        [7.91, 9.08, 9.56],
        [8.61, 8.92, 9.50],
        [8.87, 9.35, 9.63],
        [7.77, 9.83, 9.86]
    ]
    
    p2 = [
        [7.90, 10.48, 10.2],
        [8.30, 10.74, 9.59],
        [8.23, 10.24, 9.86],
        [8.15, 10.42, 9.91],
        [8.05, 10.44, 9.92],
        [8.4, 10.78, 10.04]
    ]
    
    # Transform lists to arrays
    a1, a2 = np.array(p1), np.array(p2)
    # Get vector from p1 to p2
    v = a2 - a1
    
    # Get the norm of all vectors p1p2, i.e. the distance between p1 and p2
    n = linalg.norm(v, axis=1)
    # Normalize the vectors if need be
    unit_v = v / n[:, None]
    
    # Normalize the vectors in xy plane
    unit_v_xy = (v / linalg.norm(v[:, 0:2], axis=1)[:, None])[:, 0:2]
    # Get angles modulo pi in xy plane
    xy_angles = np.column_stack((np.arccos(unit_v_xy[:, 0]), np.arcsin(unit_v_xy[:, 1])))
    
    # Get pitch angle, i.e. angle between vector and z axis
    pitch_angles = np.arccos(np.dot(unit_v, np.array([0, 0, 1])))