簡體   English   中英

計算運動矢量之間的角度

[英]compute angle between moving vectors

我有一個看起來像這樣的數據框:

    structure(list(K = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L), T = c(1L, 2L, 3L, 4L, 5L, 6L, 
7L, 8L, 9L, 10L, 11L, 12L, 13L, 14L, 15L, 16L, 17L, 18L, 19L, 
20L, 21L, 22L, 23L, 24L, 25L, 26L, 27L, 28L, 29L, 30L, 31L, 32L, 
33L, 34L, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, 11L, 12L, 
13L, 14L, 15L, 16L, 17L, 18L, 19L, 20L, 21L, 22L, 23L, 24L, 25L, 
26L, 27L, 28L, 29L, 30L, 31L, 32L), X = c(26.892, 23.904, 23.904, 
23.904, 23.904, 23.904, 23.904, 23.904, 23.904, 20.916, 20.916, 
20.916, 20.916, 20.916, 20.916, 20.916, 20.916, 20.916, 20.916, 
20.916, 29.88, 20.916, 14.94, 8.964, 8.964, 5.976, 5.976, 5.976, 
5.976, 5.976, 5.976, 5.976, 5.976, 5.976, 857.56, 860.54, 857.56, 
857.56, 857.56, 857.56, 857.56, 857.56, 857.56, 857.56, 857.56, 
857.56, 857.56, 857.56, 857.56, 857.56, 857.56, 857.56, 857.56, 
857.56, 857.56, 857.56, 857.56, 857.56, 857.56, 857.56, 857.56, 
857.56, 857.56, 857.56, 857.56, 857.56), Y = c(167.33, 167.33, 
164.34, 164.34, 164.34, 164.34, 164.34, 164.34, 164.34, 143.42, 
143.42, 143.42, 143.42, 143.42, 143.42, 143.42, 143.42, 143.42, 
143.42, 143.42, 176.29, 182.27, 185.26, 188.24, 188.24, 188.24, 
188.24, 188.24, 188.24, 188.24, 188.24, 188.24, 188.24, 188.24, 
256.97, 256.97, 256.97, 256.97, 256.97, 256.97, 256.97, 256.97, 
256.97, 256.97, 256.97, 256.97, 256.97, 256.97, 256.97, 256.97, 
256.97, 256.97, 256.97, 256.97, 256.97, 256.97, 256.97, 256.97, 
256.97, 256.97, 256.97, 256.97, 256.97, 256.97, 256.97, 256.97
), V = c(2.1128, 1.494, 0, 0, 0, 0, 0, 10.564, 10.564, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 17.034, 19.422, 8.7114, 6.6814, 3.3407, 
1.494, 1.494, 0, 0, 0, 0, 0, 0, 0, 0, 20.1, 0, 1.494, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 1.494, 1.494), P = c(-135, -90, 0, 0, 0, 0, 0, -98.13, 
-98.13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 74.745, 90, 149.04, 153.43, 
153.43, 180, 180, 0, 0, 0, 0, 0, 0, 0, 0, 41.987, 0, 180, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 90, 90)), .Names = c("K", "T", "X", "Y", "V", 
"P"), row.names = c(NA, 66L), class = "data.frame")

由於我具有X,Y位置以生成兩個向量,因此我應該考慮三個X,Y位置以便能夠計算一個角度。 我知道:

theta <- acos( sum(a*b) / ( sqrt(sum(a * a)) * sqrt(sum(b * b)) ) )

來自另一個stackoverflow答案( R中兩個向量之間的夾角 )。

我還需要計算每個T的角度作為每個K中的一個因子。我知道我可以在其中使用split

但是,如何定義用於計算角度的向量和用於角度本身的函數? 謝謝。

在此圖上,我有一個機芯的X,Y位置,並且需要計算該機芯的角度。 希望對您有所幫助。 還應注意,第一個和最后一個X,Y位置沒有可能的角度。 謝謝

運動路徑

因此,您的數據框有6行。 前三個(X,Y)集定義一個直角(th = 90)。 接下來的三組(X,Y),第4-6行,與第3行相同。因此,這些點位於彼此的頂部,沒有角度。 另外,K僅有一個值,因此很難證明K的聚合。

但是,這似乎可行:

df <- rbind(df,df,df)     # replicate the original data 3 times
df$K <- rep(1:3,each=6)   # K = 1, 2, 3
# theta in degrees
theta <- function(a,b)(180/pi)*(acos( sum(a*b) / ( sqrt(sum(a * a)) * sqrt(sum(b * b)))))
# this returns a vector of the angles between successive line segmeents
get.angles <- function(df.split){
  dx<- diff(df.split$X)
  dy<- diff(df.split$Y)
  sapply(1:(nrow(df.split)-2),function(i){
    a <- c(dx[i],dy[i])
    b <- c(dx[i+1],dy[i+1])
    theta(a,b)
  }) 
}
# this calls get.angles(...) for each subset of df, based on K
sapply(split(df,df$K),get.angles)
#        1   2   3
# [1,]  90  90  90
# [2,] NaN NaN NaN
# [3,] NaN NaN NaN
# [4,] NaN NaN NaN

編輯 (響應OP的其他數據和注釋)

因此,通過對問題進行相當實質性的更改,這種經過重新設計的解決方案似乎行得通。 使用新的df定義,

theta <- function(a,b)(180/pi)*(acos(sum(a*b)/(sqrt(sum(a*a))*sqrt(sum(b*b)))))
get.angles <- function(df.split){
  dx<- diff(df.split$X)
  dy<- diff(df.split$Y)
  stops <- which(dx^2+dy^2==0)
  dx<- dx[-stops]
  dy<- dy[-stops]
  df<- df.split[-(stops+1),]
  sapply(1:(length(dx)-1),function(i){
    a <- c(dx[i],dy[i])
    b <- c(dx[i+1],dy[i+1])
    return(cbind(df[i+1,],angle=180-theta(a,b)))
  })
}
result <- t(do.call(cbind,lapply(split(df,df$K),get.angles)))
result
#      K T  X      Y      V      P      angle   
# [1,] 1 2  23.904 167.33 1.494  -90    90      
# [2,] 1 3  23.904 164.34 0      0      171.8714
# [3,] 1 10 20.916 143.42 0      0      7.125665
# [4,] 1 21 29.88  176.29 8.7114 149.04 108.4535
# [5,] 1 22 20.916 182.27 6.6814 153.43 172.8726
# [6,] 1 23 14.94  185.26 3.3407 153.43 179.9233
# [7,] 1 24 8.964  188.24 1.494  180    153.4963
# [8,] 2 2  860.54 256.97 1.494  180    0       

此版本刪除dx 2 + dy 2 = 0(長度為0的線)的點,換句話說,在同一位置重復點,並計算其余點的角度。 請注意,我使用的是“內部”角度(<180)。 最后,我們繪制數據以顯示這些確實是正確的角度:

library(ggplot2)
ggplot(df[df$K==1,],aes(x=X,y=Y))+
  geom_path()+geom_point(colour="red")+coord_fixed()

注意使用coord_fixed() 這將縱橫比強制設為1:1。 否則角度會失真。

您可以使用'lapply'包裝split以執行此操作:

getAngle <- function(X, Y) acos( sum(X*Y) / ( sqrt(sum(X * X)) * sqrt(sum(Y * Y)) ) )
lapply(split(df[, c("X", "Y")], f = list(df$K)), 
       FUN = function(x){ getAngle(x[, 1], x[, 2])})

# $`1`
#[1] 0.04074904

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM