Skip to content

getKDEfit for on-manifold KDEs (Pose2) / credibility of mmiSAM solutions #45

@lemauee

Description

@lemauee

Hi,

I want to have a look mmiSAMs credibility (for example using NEES) and therfore need to estimate the variance / standard deviation of a normal distribution fit to a KDE. For euclidean manifolds getKDEfit does this just fine, but as the current comment implies:

function getKDEfit(p::BallTreeDensity; distribution=MvNormal)
  # TODO: update for on-manifold operations
  fit(distribution, getPoints(p))
end

on (partly) circular manifolds with large spread crossing the -pi, pi boundaries this will lead wrong results.

I already came up with a solution that at least covers the diagonal of the covariance matrix:

function getKDEfitPose2(p::BallTreeDensity)
    pp = getPoints(p)
    ppEuclid = pp[1:2,:]
    ppCirc = pp[3,:]
    normalEuclid = fit(MvNormal,ppEuclid)
    μ = zeros(3)
    μ[1:2] = normalEuclid.μ
    μ[3] = cmean(ppCirc)
    Σ = zeros(3,3)
    Σ[1:2,1:2] = normalEuclid.Σ
    Σ[3,3] = cstd(ppCirc)^2
    MvNormal(μ,PDMat(Σ))
end

it uses the CircStats.jl packages functions cmean and cstd.

Calculating the mean of angles is almost straightforward (see https://en.wikipedia.org/wiki/Mean_of_circular_quantities). Even the implementation in CircStats.jl is only a line long:

cmean(a) = atan(sum(sin.(a)), sum(cos.(a)))

The variance is another story. In circular statistics the variance is NOT defined as the standard deviation squared as described in https://en.wikipedia.org/wiki/Directional_statistics#Measures_of_location_and_spread . But I chose this implementation to stay consistent with the current behavior of getKDEfit in case we have only a small variance and are far from -pi or pi. Wikipedia describes this more formally as "for a wrapped normal distribution, it is an estimator of the standard deviation of the underlying normal distribution". In the end this should be the right measure to calculate credibility on. CircStats implements the calculation of the resultant vector and then calculates the standard deviation based on this just like described in Wikipedia

cresultant(a, degrees::Bool=false) = degrees ?
    sqrt(sum(sin.(deg2rad.(a)))^2 + sum(cos.(deg2rad.(a)))^2)/length(a) :
    sqrt(sum(sin.(a))^2 + sum(cos.(a))^2)/length(a)
cstd(a, degrees::Bool=false) = sqrt(-2*log(cresultant(a, degrees)))

Concerning the covariance matrices off-diagonal entries I have not found any literature by now and just left them zero. Perhaps handing back two seperate distributions or putting NaNs in these places would be the better idea.

Last but not least, the Implementation as seperate function getKDEfitPose2 seems pretty un-julia-ish. Can you think of a better option?

I would be happy to file a pull-request (which i actually never did to this date ;)) if you think this function in its current state is of general interest :)

OT: Are there any other options you can think of concerning evaluating the credibility of an mmiSAM solution?

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions