본문 바로가기
project

[Go] Golang을 이용한 칼만 필터 적용 구현 및 시뮬레이션

by Jayson Jeong 2023. 7. 11.

https://jbground.tistory.com/82

 

[SLAM] 칼만 필터(Kalman Filter)란?

로봇의 각종 센서 정보를 통해 로봇의 위치를 추정하고 이동 경로 계획을 위한 SLAM을 하는 과정에서 센서를 통해 들어오는 정보에 잡음(노이즈)이 섞이는 경우가 발생한다. 이로 인해 추정된 위

jbground.tistory.com

 

공부했었던 칼만 필터를 실제로 적용하는 과정을 직접 확인해보기 위해 시뮬레이션 개발을 진행했습니다.

칼만 필터는 github.com/konimarti/kalman 라이브러리를 적용했습니다.

 

간단한 웹 구현을 위해 Gin을 활용하여 개발했습니다.

func RoutingByGin() *gin.Engine {
	r := gin.New()
	r.Use(gin.Logger())
	r.Use(gin.Recovery())

	kalman := r.Group("/kalman")
	kalman.GET("/index", api.KalmanIndex)
	kalman.GET("/uniform", api.KalmanUniform)
	kalman.POST("/pdf", api.KalmanPdf)
	kalman.POST("/exec", api.KalmanExecute)
	return r

}

 

 

URL와 연결할 함수 구현

func KalmanIndex(c *gin.Context) {

	files, err := template.ParseFiles("asset/filter.html")
	if err != nil {
		log.Fatalf("template execution: %s", err)
	}
	err = files.Execute(c.Writer, nil)
	if err != nil {
		log.Fatalf("template execution: %s", err)
	}

	return
}

func KalmanPdf(c *gin.Context) {
	//LoggingBodyContent(c)

	var val []app.Coordinate
	if err := c.ShouldBind(&val); err != nil {
		fmt.Println(err)
	}

	c.JSON(http.StatusOK, app.GeneratePdfData())
}

func KalmanExecute(c *gin.Context) {
	var val []app.Coordinate
	if err := c.ShouldBind(&val); err != nil {
		fmt.Println(err)
	}

	app.ExecuteKalmanFilterByLib(val)

	c.JSON(http.StatusOK, val)

}

 

칼만 필터 서비스 구현

칼만 필터를 적용할 수 있는 정규분포를 따르는 x, y 좌표 배열을 생성합니다. 생성된 좌표를 web으로 보여주고 

좌표에 칼만 필터를 적용하여 칼만 필터가 적용된 결과를 web으로 확인했습니다.

func GeneratePdfData() []*Coordinate {
	var s []*Coordinate
	corr := 0.5
	for i := 0; i < 1000; i++ {
		val1 := rand.NormFloat64()
		val2 := corr*val1 + math.Sqrt(1-corr)*rand.NormFloat64()
		x := 5.0 + val1
		y := 5.0 + val2

		c := NewCoordinate(x, y)
		s = append(s, c)
	}
	return s
}

func ExecuteKalmanFilterByLib(source []Coordinate) {

	ctx := newContext(source[0].X, source[0].Y) //kalman filter setup
	lti, nse := newSetup()

	filter := kalman.NewFilter(lti, nse) // create Kalman filter
	control := mat.NewVecDense(4, nil)   // no control

	for i := range source {
		measurement := mat.NewVecDense(2, []float64{source[i].X, source[i].Y})
		filtered := filter.Apply(ctx, measurement, control)
		source[i].X = filtered.AtVec(0)
		source[i].Y = filtered.AtVec(1)
	}

}

 

 

 

실행 결과