ROS2 Lambda 함수

brewmaster
newworld-kim
Published in
5 min readMar 14, 2021

ros2 공부를 시작했다. 첫 스터디 커리큘럼으로 공식 Tutorials을 따라가기로 했는데 Modern C++ 내용이 잘 반영되어 있어, ros2 도메인 지식만 공부되는게 아니라 C++ 공부도 함께 되어 찬찬히 보는 재미가 쏠쏠하다.

Tutorials 과정 중, “Expanding on ROS 2 Interfaces”에서 람다(Lambda) 함수를 사용한 예제코드가 있었다. 람다 함수에 대해 잘 모르던터라 이번 기회에 정리해보기로 했다.

< tutorial에서 소개된 lambda 함수를 포함한 코드 >

Lambda 함수

람다 함수는 C++11 부터 도입된 기능으로, 수십 줄의 복잡한 코드를 한두줄의 간략하고 명시적인 코드로 작성할 수 있는 강력한 기능이다. 익명함수(Anonymous Function) 또는 클로저(Closure)라고도 불리며, 람다, 람다함수 모두 같은 표현이다.

아래의 적용 예를 먼저 살펴보자.

Vector 타입의 객체의 원소들을 곱을 구하기 위한 코드이다. cardinal의 시작과 끝을 iterator를 통해 모든 원소의 곱을 while() 문을 통해 계산하여 total_elements 에 저장한다.
이 코드를 람다를 적용하면 아래 코드처럼 구현할 수 있다.

코드가 훨씬 간결해졌다. 람다의 장점은 훨씬 더 복잡한 코드에 적용할 때 더욱 효과적이다.

Lambda 구성

람다는 6 개의 구성요소로 볼수 있다. 이 중, Parameters, Mutable, Exception, Return type 은 옵션으로 반드시 설정하지 않아도 무방하다.

  1. Capture clause
  2. Parameters list (Optional)
  3. Mutable specification (Optional)
  4. Exception specification (Optional)
  5. Trailing return type (Optional)
  6. Lambda body

Capture Clause

캡처절이라고 부르며, Lambda body에 필요한 변수들의 참조값 또는 변수값을 캡처하여 넘겨줄 수 있다. 캡처하여 넘겨준다는 말은 람다함수도 객체이기 때문에 생성자를 통한 복사하는 시점이 있다는 뜻이다.
아래처럼 참조값/변수값을 선택하여 캡처할 수 있다. 특정 참조값과 변수값만, 전체 변수값과 특정 참조값만, 전체 참조값과 특정 변수값 등 원하는 조합으로 선택하여 캡처할 수 있다. [] 형태로 아무것도 입력하지 않으면 기본옵션으로 모든 참조값과 변수값을 캡처하여 넘겨준다.
단, Default와 중복표현 형태는 불가능 하다.

[&total, factor] 
[factor, &total]
[&, factor]
[factor, &]
[=, &total]
[&total, =]

Parameters list

캡처절을 통해서 뿐만 아니라, 매개변수 형태로도 값을 입력할 수 있다. 캡처절을 통해 입력할 것인지, 매개변수를 통해 입력할 것인지는 선택사항이다.

Mutable specification

캡처절을 통해 입력받는 모든 참조값/변수값들은 상수형태로 입력된다. 이해가 쉬운 말로 설명하면, 람다함수 스코프 내에서 지역변수와 같은 형태로 존재한다는 말이다.
캡처절로 입력하여 수정한 참조값/변수값들을 람다함수 스코프 외부에도 반영하기 위해서는 mutable옵션을 사용하면 된다.

Exception specification

일반적인 함수의 C++ 예외처리와 동일한 방법으로 Exception 기능을 활용할 수도 있다. noexcept 를 통해 람다함수가 예외를 throw 하지 않게 할수 있다.

Trailing Return Type

람다함수의 반환타입은 auto 를 통해 자동으로 결정되기 때문에 굳이 키워드를 사용하지 않아도 되지만, Trailing Return Type을 통해 명시적으로 선택할 수도 있다.
아무런 입력이 없다면 -> void 가 기본형이다.

Lambda body

람다함수의 스코프를 뜻하며, 캡처절에서 캡처한 변수들과 매개변수를 통해 입력한 변수 모두 접근할 수 있다. 또한, 전역변수도 접근가능하며, 일반적인 함수들처럼 변수들을 선언할 수도 있다.
특정 클래스 내 선언되었고, 캡처절에서 this 를 캡처했다면 해당 클래스의 멤버변수도 접근할 수 있다.

ROS2 예제로 다시보기

람다함수에 대해 알아봤다. 이제 다시 ROS2 에서 소개된 Lambda 함수 코드를 보면서 정리해보자.

< tutorial에서 소개된 lambda 함수를 포함한 코드 >
  • publish_msg 에 클로저 객체를 입력.
  • [this] 로 클래스를 람다함수 내에서 참조할 수 있음.
  • () 매개변수 입력은 없음.
  • return type은 -> void 로 기본값임.
  • 람다함수 스코프 내에서 this->address_book_publisher_->publish(message); 로 캡처를 통해 전달 받은 this 를 참조.

람다함수를 알아봤다. 이제 강력한 람다함수를 잘 활용하는 일만 남았다!

--

--