[SLAM] 최적화 문제를 풀기위한 Ceres Solver Tutorial

예문을 포함한 Ceres tutorial PPT & github code


Ceres Solver

Ceres solver는 비선형 최적화 문제를 풀기위한 오픈소스 기반의 c++ 라이브러리이다. 우리가 풀어야 하는 대부분의 문제들은 비선형 문제이다. Ceres solver는 다른 최적화 라이브러리에 비해 확장성이 좋으며, SLAM을 위한 다양한 예제도 제공해주고 있다. SLAM을 연구 및 개발하는 사람이라면 기본적으로 Ceres Solver 는 다룰 수 있어야 한다.

Ceres Solver Tutorial

해당 발표 자료 및 tutorial code는 2023년 인하대학생들에게 제공하기 위해 작성한 자료들이다.

Ceres Tutorial 발표자료

Ceres Tutorial Code


[Book] 혼자서도 스타트업

혼자서도 스타트업 - 조현영 대표


Pasted image 20230927124351

2022년 중반부터 올라가기 시작한 금리에 따라 전반적인 시장이 얼어붙고, 그에 따라 투자 시장도 급격히 얼어붙음에 따라 많은 스타트업들이 어려워지고 있다. 내가 몸담고 있는 스타트업도 100억이 넘는 투자금을 받았지만 현재 많은 어려움을 겪고 있다. 작년까지만 해도 투자금은 회사의 비전을 제시할 수 있다면 언제든지 받아올수 있다고 생각할 만큼 현금이 넘쳐나는 시기였다. 하지만 지금과 같은 시기가 되니 투자자들은 더욱 보수적으로 스타트업을 평가하고 그에 따라 회사의 가치도 급격히 떨어지고 있다. 이런 시기가 올 것이라고 조금이라도 미리 예측하고 보수적으로 투자금을 사용했더라면 지금과 같은 어려움을 겪지 않지 않았을까 하는 생각을 계속 하는 시기이다. 이런 시기에 우연히 유튜브를 통해 하이퍼로컬의 조현영 대표님의 인터뷰를 보고 이 책을 읽게 되었다. 

첫 서비스는 망한다

조현영 대표님이 스타트업을 시작하기로 결심을 하고 카카오를 떠나면서 들었던 이야기가 “첫 서비스는 망한다” 였다고 한다. 시간이 지나고 나서 그 말이 현실이 되었음을 알게 되었다고 하신다. 그만큼 스타트업에서는 서비스를 만들어봤던 경험이 중요하고, 그 경험이 쌓이면서 더욱 경쟁력 있는 제품을 만들수 있다는 뜻이기도 한것 같다. 그리고 스타트업은 언제든지 방향이 잘못되었다고 판단이 되면 Pivot을 할 준비가되어 있어야 한다. 언제든지 열린 생각을 가지고 시장의 흐름을 읽고, 트랜드를 계속 파악해 나가야 한다. 

공동 창업자에 대하여

공동창업자와 열정의 크기가 다르고 생각하는 것이 다르다면 공동창업을 하지 않는 것이 더 좋다. 특히 본 직업을 갖고 있으면서 주말 혹은 업무시간 이후에 스타트업에 도전하려는 생각을 갖는 사람과의 공동 창업은 추천하지 않는다. 

회사의 직원에 대하여

현재 조현영 대표님은 “그루밍족” 과 “해주세요” 라는 두개의 서비스를 운영하고 계시며, 정직원 없이 혼자 회사를 운영하고 계신다. 기술 조직을 이끌어온 나로써 다시 생각해 보아도 지금의 조직을 혼자 이끌수는 없다고 생각한다. 왜냐하면 하드웨어 개발 및 소프트웨어 개발은 알아야 되는 분야가 너무 세분화 되어 있고 내가 그 지식을 다 갖추지 못했기 때문에다. 하지만 반대로 생각해보면 조현영 대표님도 개발자가 아니다. 개발자가 아니지만 서비스 기획부터 개발, 홍보, CS까지 혼자 계획하고 외주 개발자를 통해 어플을 만들어 지금까지 성장시켜왔다는것은 정말 쉬운일이 아닐 것이다. 물론 하드웨어 개발과 어플 개발의 기술적 난이도는 다를 것이다. 그럼에도 많은 스타트업들은 더 빠른 성장을 위해 값비싼 인건비에 능력있는 개발자들을 모시기위해 노력하고 있고, 그러한 인건비에 의해 적자를 벗어나지 못하고 있는 스타트업들이 많다.

나 또한 회사가 시리즈 A 투자를 받고 나서 어느정도 자금의 여유가 생김에 따라서 내가 그동안 재대로 커버하지 못했던 부분을 매우기 위해 채용에 속도를 냈었었다. 그 당시에는 나름대로 채용에 대한 시스템도 만들어 가면서 정말 좋은 분들을 모시기 위해 노력했었고 채용 자체는 실패하지 않았다고 생각한다. 하지만 지금 돌이켜 생각해보면 지금의 제품을 만들기 위해 지금까지 채용했던 모든 인원들이 반드시 필요하지는 않았을 것 같다. 그 당시에는 CTO로써 나의 업무가 너무 많아서 능력있는 직원을 빨리 뽑아서 나의 역할을 분배해주고 싶었던 마음이 컸었다. 그러다보니 점점 직원은 많아지고, 조금씩 잉여인력이 늘어났던것 같다. 

조현영 대표님은 대표가 모든 부분에 대해서 챙기고 이해를 하고 있어야만 회사 운영이 재대로 이뤄질수 있고, 직원이 변경되었을 때도 그 업무를 커버할 수 있다고 하신다. 물론 50명이 넘어가는 큰 회사에서도 동일하게 적용되기는 어려운 방법일 수 있다. 하지만 일반적인 스타트업은 수익이 나기까지 시간이 걸리고, 그 수익도 크지 않기 때문에 최대한 인건비를 줄이면서 성장해 나가는 것이 가장 좋은 방법임에는 공감한다. 

지금까지 제품 개발을 하면서 한 두번의 외주를 진행했었고 그다지 성공적이지 못했던 프로젝트였다. 그 당시에는 내가 전혀 알지 못하거나 부족하게 아는 부분에 대해 개발을 해야 했고 (Linux Kernel, 회로 개발), 나름대로 가이드는 작성하였지만 디테일이 부족했던 것 같다. 내가 그 분야에 대해 외주 개발자만큼 지식을 갖고 있었다면 더욱 성공적은 프로젝트였을 것 같다. 조현영 대표님 말처럼 대표가 모든 일을 할 수 는 없기에 프리랜서를 최대한 활용해야 한다. 하지만 프리랜서를 최대한 활용하기 위해서는 적어도 대표 스스로가 그 부분에 대한 지식을 충분히 갖춰야 한다. 

투자에 대하여

지금까지의 나 또한 스타트업을 하게 되면 투자가 반드시 필요하다고 생각을 했다. 투자를 해야만 회사의 벨류가 측정이 되고, 나의 지분의 가치가 올라간다고 생각했다. 물론 일부는 맞는말이다. 하지만 반드시 투자가 회사에 긍정적인 영향을 미치는 것만은 아니다. 우리 회사만 보더라도 한명의 미국 투자자에 의해서 회사의 CEO가 바뀌고 회사의 문화가 완전히 망가졌다. 많은 투자자들이 회사의 성장을 바라기 때문에 물심양면으로 회사를 성장시키기 위해 함께 노력해 나가고 있고, 다양한 도움을 주고 있다. 히지만 그 투자자들도 결국에는 회사의 성장에 의해 이익을 위해 움직이는 사람이고, 누구보다도 똑똑한 사람이다. 

조현영 대표님의 말씀처럼 투자를 받는것은 필수가 아니다. 회사의 제품을 개발하는 초기에 대표는 고객을 바라보고, 고객의 문제를 해결하기 위해 집중을 해야한다. 하지만 대부분의 대표들은 투자자들을 만나서 어떻게 투자자들을 설득시킬지를 고민한다. 어떻게 현재 개발하고 있는 제품이 미래지향적으로 보일지, 어떻게 돈이 되는 스토리를 만들지를 고민한다. 이것 또한 스타트업의 대표로써 잘 해야만 하는 일이지만, 회사의 제품이 어느정도 성숙해 지기 까지는 조금 더 고객의 Pain Point를 해결하는 것에 조금 더 집중하는 것이 맞다고 생각된다. 어느정도 회사의 성장 속도에 가속화를 내기 위해서는 당연히 어느정도의 투자는 필수적이다. 하지만 투자를 받는 것이 스타트업을 운영하는 첫번째 목표가 되어서는 안된다.

유의미한 데이터에 집중하라

현재 내가 만들고 있는 서비스가 의미있는 결과를 만들어 내고 있는지를 보기 위해서는 주기적으로 유의미한 데이터에 집중을 해야 한다. 어플기반의 서비스라면 DAU (Daily Active User), MAU (Monthly Active User)와 같은 지표가 될 것이다. 두개의 지표중에서는 DAU가 조금 더 의미있는 지표이다. 왜냐하면 MAU는 주기적인 광고 혹은 이벤트를 통해 채울수 있는 지표이기에 매일 접속하는 유저의 수를 의미하는 DAU가 더욱 의미있는 지표이다. 

내가 지금 개발하고 있는 제품은 B2B 제품이다. 제품을 구매하는 사람은 한 회사의 관리자 혹은 Inovation (혁신) 팀이고, 실제 사용자는 물류센터내의 작업자이다. 그러다 보니 제품의 실제 구매자와 사용자가 제품을 바라보는 관점이 다르다. 지금까지 B2B 제품이기에 실제 사용자에 대한 지표를 중요하게 분석해볼 생각을 많이 해보지 못했다. 하지만 해당 사용자가 어떤 기능에 만족해 하는지, 어떤 부분에 불편해 하는지 등 이러한 피드백에 계속 귀를 귀울여야 하고, 이러한 데이터를 자동으루 수집할 수 있는 시스템을 구축하여 고객의 데이터를 만들어 나가야 할 것 같다. 

고객의 목소리 (고객의 응대는 대표가 하라)

CS (Customer Service)는 가장 감정 노동이 되는 업무이기에 회사를 운영하면서 가장 하기 싫은 부분이고, 직원에가 가장 먼저 넘기는 부분이 아닐까 한다. 나 또한 현재 제품을 개발하면서 고객을 직접 만나는 경우는 많지 않다. 주로 고객의 목소리는 필드 엔지니어, 혹은 세일즈 팀을 통해 듣고, 그 고객의 목소리를 다음 제품 기획에 반영하고 있다. 하지만 그렇다 보니 중간 메세지 전달역할을 하는 필드엔지니어나 세일즈팀의 제품 이해도에 따라 고객의 목소리가 외곡되어 전달되는 경우가 심심치 않게 있어왔다. 조현영 대표님은 대표가 직접 고객을 응대하고 고객의 니즈를 계속 제품에 반영해 나가야 한다고 강조하고 있다. 이러한 방법이 가장 직접적으로 고객의 피드백을 받아 제품 기획에 반영하고, 개발까지 이어질 수 있는 가장 빠른 방법이기도 하기 때문이다. 

물론 이 방법 또한 큰 조직에서 유지되기는 힘든 방법일수는 있겠지만, 대표가 고객의 목소리에 계속 집중해야 한다는 메세지는 꼭 기억해야 할 것 같다. 

총평

이 책은 사업을 할 때 계속해서 마음속에 담아둬야 하는 포인트들을 잘 담고 있는 책인것 같다. 새로운 사업을 시작하게 된다면 이 책은 다시 돌아와서 읽어볼 예정이다.


[Ubuntu] Background로 실행 중인 프로세스 output 확인

Check stdout of running process


top로 확인 가능한 process의 terminal output를 확인하기 위한 명령어

# std out
cat /proc/{pid of process}/fd/1
# std err
cat /proc/{pid of process}/fd/2



[Ubuntu] Ubuntu Memo widget

ubuntu memo widget


Install Ubuntu memo widget

sudo add-apt-repository ppa:umang/indicator-stickynotes
sudo apt-get update
sudo apt-get install indicator-stickynotes



Map and Unordered_map

STL map 그리고 unordered_map 비교


std::map은 Key와 value를 갖는 데이터 구조이다. std::map의 경우 key값에 따라서 정렬이 되지만, std::unordered_map은 hash_map과 동일하게 내부적으로 key 값에 의해 정렬되지 않는다. std::unordered_map은 c++11에서 STL 표준으로 추가되었다.

std::unordered_map의 장점은 빠른 탐색속도이다. N개의 데이터 쌍을 갖는 std::map의 경우에는 O(logN)의 탐색속도를 갖는 반면, std::unordered_map은 O(1)의 탐색속도를 갖는다.

Map

map은 기본적으로 red-black tree 기반으로 되어 있다. 따라서 모든 데이터는 key 값을 기준으로 정렬되어 저장되어 진다. map의 경우 입력되는 key 값의 분포가 고르지 못할 경우 balancing에 대한 비용이 계속 들어가기 때문에 성능이 저하된다. (탐색속도 O(logN)은 보장된다)

Unordered_map

unordered_map은 hash_table 기반의 hash_container이다.

node들을 정렬할 필요가 없기 때문에 탐색에서 꾸준한 성능 (O(1))의 성능을 보장한다.

Example

다음과 같은 알고리즘 문제에서 탐색을 위해 unordered map을 사용하면 빠르게 탐색이 가능하다

  1. Two Sum

Given an array of integers, return indices of the two numbers such that they add up to a specific target.

You may assume that each input would have exactly one solution, and you may not use the same element twice.

Example:

Given nums = [2, 7, 11, 15], target = 9,

Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].
  1. Solution
class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {

        unordered_map<int,int> map;
        vector<int> result;
        for(int i = 0 ; i < nums.size() ; ++i){
            int complement = target - nums[i];
            if(map.find(complement)!= map.end() && map[complement] != i){
                
                result.push_back(i);
                result.push_back(map[complement]);
                return result;
            }else{
                map[nums[i]] = i;
            }
        }
        return result;
    }
};

Reference

[C++] map vs hash_map(unordered_map)


Pagination