Reputation: 6328
I have a homogeneous transformation matrix of size (4x4) and a trajectory of size (nx3). Each row of this trajectory is a vector.
I want to multiply homogeneous transformation matrix by each row of trajectory. Below is the code:
#append zero column at last
trajectory = np.hstack((trajectory, np.zeros((trajectory.shape[0], 1)))) #(nx3)->(nx4)
trajectory_new = np.zeros((1, 3)) #(1x3)
for row in trajectory:
vect = row.reshape((-1,1)) #convert (1x4) to (4x1)
vect = np.dot(HTM, vect) #(4x4) x (4x1) = (4x1)
vect = vect.T #(1x4)
vect = np.delete(vect, -1, axis=1) #remove last element from vector
trajectory_new = np.vstack((trajectory_new, vect)) #(nx3)
trajectory_new = np.delete(trajectory_new, 0, axis=0)#remove first row
The above code works. However, I am looking for simpler solution, such as following:
trajectory_new = np.apply_along_axis(np.multiply, 0, trajectory, HTM)
Any help, please.
Answer:
trajectory = np.hstack((trajectory, np.ones((trajectory.shape[0], 1))))#(nx3)->(nx4)
trajectory_new = trajectory.dot(HTM.T)[:,:-1]
Upvotes: 4
Views: 3186
Reputation: 11347
Your trajectory is nx3
, but in order to multiply correctly you need 3xn
. Therefore you'll need to transpose twice. Once before multiply and once after.
Like this,
trajectory = (HTM[:3,:3] @ trajectory.T).T
I assume that trajectory is a vector and you want to ignore the HTM origin? If you want to also add the origin, then you can do this.
trajectory = (HTM[:3,:3] @ trajectory.T).T + HTM[:3,3]
Upvotes: 0
Reputation: 221524
You can simply use matrix-multiplication with np.dot
on the input before stacking zeros
-
trajectory.dot(HTM[:,:3].T)[:,:3]
Approaches -
def dot_based(trajectory):
return trajectory.dot(HTM[:,:3].T)[:,:3]
def original_app(trajectory):
# append zero column at last
traj_stacked = np.hstack((trajectory, np.zeros((trajectory.shape[0], 1))))
trajectory_new = np.zeros((1, 3)) #(1x3)
for row in traj_stacked:
vect = row.reshape((-1,1)) #convert (1x4) to (4x1)
vect = np.dot(HTM, vect) #(4x4) x (4x1) = (4x1)
vect = vect.T #(1x4)
vect = np.delete(vect, -1, axis=1) #remove last element from vector
trajectory_new = np.vstack((trajectory_new, vect)) #(nx3)
trajectory_new = np.delete(trajectory_new, 0, axis=0)#remove first row
return trajectory_new
Sample run -
In [37]: n = 5
...: trajectory = np.random.rand(n,3)
...: HTM = np.random.rand(4,4)
...:
In [38]: np.allclose(dot_based(trajectory), original_app(trajectory))
Out[38]: True
Upvotes: 1
Reputation: 14399
I think what you want is something like:
trajectory_new = np.einsum('ij,kj->ik', HTM[:,:3], trajectory)
Not sure about the order, but that should work much faster than for
loops
Upvotes: 1
Reputation: 13218
Could you include an example of input and output? But it seems that
np.dot(HTM, trajectory.T)[:3].T
could do the trick?
Rather than appending a column of 0 to trajectory
, why don't you drop the last row of HTM
?
Upvotes: 1