for Robot Artificial Inteligence

1. introduction to Visual SLAM practice.

|

기본 연습

#include <iostream>
using namespace std;

int main()
{
  cout<<"hello SLAM!"<<endl;
  return 0;
}
  • 컴파일러를 사용하여서 실행 파일을 만들어야하는데 많이 사용 되는 것은 g++이다
    • 만약 설치가 안되어있다면 sudo apt-get install g++
  • 컴파일
g++ helloSLAM.cpp
  • 컴파일이 되었으면 현재 목록에 실행파일 a.out 의 파일을 발견할 수 있다.

  • 실행

./a.out

---
output : hello SLAM!

CMake 사용

  • 다량의 cpp파일을 g++를 이용하여서 compile하는 것은 생각만해도 골치아프다.

  • 이런 Procedeure을 관리해주는 Cmake를 사용한다면 효과적으로 효율을 올릴 수 있따.
  • Cmake는 자동 Compile을 도와주는 도구이다.
  • CMakeLists.txt는 흔히 Makefile이라고 불리는데, 자동 컴파일을 지정해주는 파일이다.

  • 위에와 같은 프로그램을 CMakeLists.txt를 통하여 아래와 같이 자동 컴파일을 지정할 수있다.
# Cmake
cmake_minimum_required( VERSION 2.8)

# Named Project
project( HelloSLAM)

# add_executable, 실행파일 만들기
add_executable( helloSLAM helloSLAM.cpp)
  • CMakeLists.txt를 만들었으면, mkdir을 통해 build 폴더를 만고 cd build 장소에서 cmake .. 를 진행하여 compile 준비를 한다.

  • 준비가 끝났으면 make 를 통해서 compile 진행을 하면 아래와 같이 뜬다.

  • 성공을 하였다면 아래와 같이 실행할 수 있다.
./helloSLAM
Hello SLAM!

Library 사용하기

  • Visual SLAM을 하기 위해서 아래와 같은 라이브러리가 필요하다
    • Opencv Library : Computer Vision 알고리즘 Library
    • Eigen Library : Matrix, linear Algebra 알고리즘
  • Library 사용 대한 이해를 돕기 위해 예로 아래와 같이 Library를 만들어 보았다.
    • file name : libHelloSLAM.cpp
#include <iostream>
using namespace std;

void printHello()
{
  cout<<"hello SLAM!"<<endl;
  return 0;
}
  • printHello의 함수를 만들었지만, main 함수가 없으므로 실행을 할 수 없다. CMakeLists.txt에 아래와 같이 script를 더한다.
# Static library
add_library( hello libHelloSLAM.cpp )
  • 그리고 build 폴더에서 make를 다시한다면 libhello.a 라는 파일이 생성되는 것을 볼 수 있을것이다.
  • libhello.a 이것이 바로 우리의 library다
  • .a 는 Static Library를 뜻하고
    • Static Library는 매번 쓸때마다 복사본을 생성한다.
  • .so 는 Share Library를 뜻한다.
    • .so 는 Share Library로 오직 하나의 복사본만 가지고 있어 공간을 아낄 수 있다.
  • 만약 Static Library가 아닌 Share Library를 쓰고 싶다면 Cmakelists.txt에서 아래와 같이 쓸 수 있다.
# 共享库
add_library( hello_shared SHARED libHelloSLAM.cpp )
  • 그리고 build 폴더에서 make를 다시한다면 libhello.so 라는 파일이 생성되는 것을 볼 수 있을것이다.
  • Library는 compile이 이미 잘된 압축 파일이다. 그러나 .a 혹은 .so 안에 어떤 함수들이 있는지 알수가 없다.
  • 다른사람이 쓰거나 혹은 본인을 위해 Header파일이 필요하다.
  • Header 파일과 Library파일만 있다면 그 Library를 사용할 수 있다.
  • 아래와 같이 예시를 보겠다.

    libHelloSLAM.h

#ifndef LIBHELLOSLAM_H_
#define LIBHELLOSLAM_H_
// 上面的宏定义是为了防止重复引用这个头文件而引起的重定义错误
void printHello();
#endif

useHello.cpp

#include "libHelloSLAM.h"

// 使用 libHelloSLAM.h 中的 printHello() 函数
int main( int argc, char** argv )
{
    printHello();
    return 0;
}
  • 두 파일을 만들었다면 CMakeLists.txt에 명령어를 추가하여서 library파일인 libHelloSLAM.cpp를 사용할 수 있게 한다.
add_executable( useHello useHello.cpp )
# 将库文件链接到可执行程序上
target_link_libraries( useHello hello_shared )
  • 이렇게 된다면 useHello 프로그램은 언제든지 hello_share의 프로그램을 사용할 수 있다.

Debug

  • Linux 중에서 Debug Tool은 기본적으로 gdb이다.
  • CmakeList.txt를 이용하여서 쉽게 Debug를 할 수 있다.
# 设置编译模式
set( CMAKE_BUILD_TYPE "Debug" )

Reference

SLAM KR 视觉SLAM书

Cmake Tutorial : https://github.com/TheErk/Cmake-tutorial.

Comment  Read more

5. Recursion

|

  1. what is recursion
  2. Example of Recursion
  3. tracing recursion
  4. stack used in recursion
  5. time complexity
  6. recurrence relation

what is recursion

  • 로컬 함수 스스로 cycling 하는 것.
    • 스프링이라 생각하면 된다.
    • 땡겨서 정확한 index 데이터 값을 찾는데 주로 쓰인다.
  • they are two method in recursion(Tail recursion, Head Recursion)

Recursion 하기 전에 print out(Tail Recursion)

void fun1(int n)
{
  if(n>0) // 1 unit
  {
    cout<<n; // 1 unit
    fun1(n-1); // func1(n-1)
  }
}
int main()
{
  int x = 3;
  fun1(x);
}

Recursion이후 print out(Head Recursion)

void fun1(int n)
{
  if(n>0) // 1 unit
  {
    fun1(n-1); // func1(n-1)
    cout<<n; // 1 unit
  }
}
int main()
{
  int x = 3;
  fun1(x);
}

  • 연속적으로 연결되어있는 (like tail) 방이 있는데 안쪽에서 부터 불을 끌것이냐, 들어가면서 불을 끌것이냐 와 같은 문제이다.

  • 들어가면서 불을 끌껏이다
    • Recursion 하기 전에 print out 방법(Tail recursion)
  • 나오면서 불을 끄겟다
    • Recursion이후 print out(Haed Recursion)
  • 이것을 더 정확하게 말하자면 Recursive functions에서는 두가지 calling 방법이 있는데
    • Ascending
    • Descending 이다.
void fun(int n)
{
  if(n>0) // 1 unit
  {
    1.____ // calling (ascending 방법)
    2. fun(n-1);
    2.____ // returning (Descending 방법)
  }
}

Time Complexity

  • Calling n+1 time 이므로, O(n) 이다

  • Time complex를 조건부로 쓰자면

    • n=0 일 경우, Time complex of fun(n) =1
    • n>0 일 경우, time complex of fun(n) = fun(n-1)+1 = O(n)

Static or Global variables in Recursion

Static vairblae in Recursion

#include <stdio.h>
int fun1(int n)
{
 static int x=0; //static variable
 if(n>0)
 {
 x++;
 return fun(n-1)+x;
 }
 return 0;
}
int main() {
 int r;
 r=fun1(3);
 printf("%d\n",r); // output 9

 r=fun1(3);
 printf("%d\n",r); // output 18

 return 0;
}
  • static variable는 local function이 종료가 되도 value가 남아 있다. 다만 오직 local function에서만 사용할 수 있고 다른 함수에서는 사용 할 수없다

Global varibale in Recursion

#include <stdio.h>
int x=0; // global variable
int fun(int n)
{
 if(n>0)
 {
 x++;
 return fun(n-1)+x;
 }
 return 0;
}
int main() {
 int r;
 r=fun(3);
 printf("%d\n",r);

 r=fun(3);
 printf("%d\n",r);

 return 0;
}
  • 반면에 Global varible 같은 경우에는 값이 항상 유지 남아 있고 다른 function에도 사용할 수 있다.

Tree Recursion.

#include <stdio.h>
void fun(int n)
{
 if(n>0)
 {
 printf("%d ",n);
 fun(n-1);
 fun(n-1);
 }
}
int main() {
 fun(3);
 return 0;
}

// output : 3 2 1 1 2 1 1
  • Tail Recursion 뒤에 또다른 Tail Recursion을 넣은 방법.

  • time complexcity O(2^n)
    • 2^0 + 2^1 + 2^2 ….
  • Space complexity O(n)

    Indirect Recursion

#include <stdio.h>
void funB(int n);
void funA(int n)
{
 if(n>0)
 {
 printf("%d ",n);
 funB(n-1);
 }
}
void funB(int n)
{
 if(n>1)
 {
 printf("%d ",n);
 funA(n/2);
 }
}
int main()
{
 funA(20);
 return 0;
}
// output 20 19 8 4 3 1
  • 자기 자신을 Recursion 즉 circle 하는 것이 아닌, 다른 함수와 Link하여서 Recursion 방법으로 사용할 수있는 방법 (Indirect Recurion)

Nested Recursion

  • Recursion Function 안에 한번 더 Recursion Function 하는 것
#include <stdio.h>
int fun(int n)
{
 if(n>100)
 return n-10;
 return fun(fun(n+11));
}
int main()
{
 int r;
 r=fun(95);
 printf("%d\n",r);
 return 0;
}
// output 91

Comment  Read more

4. Essential concept (Physical and Logical data structure, ADT)

|

Physical data structure

  1. Array 는 Stack과 Heap에서 둘다 만들수 있다.
  2. Linked List는 heap에서 만든다.

Logical data structure

  • Linear data sturcture
    1. Stack (LIFO)
    2. Queue (FIFO)
  • Non-Linear
    1. trees
    2. Graph
  • Table
    1. Hash table

Abstract Data type

  1. what is ADT(Abstract Data Type)
    • representation of data
    • int, float, double … - operation on data.
    • +,-,*,/,%,++,–

Example

  • List -> 8,3,9,4,6,10,12

  • Data :
    1. space for storing element(Array, Linked list)
    2. capacity
    3. size
  • operation :
    • add(x)
    • remove()
    • search(key)
    • insert(key)
    • set(index, key)
    • replace(index, key)
    • get(index)
    • contain(key)

Comment  Read more

3. Essential concept (Data Structure, Static and Dynamic Allocation)

|

Data structure

  • Data Structure
  • Data Base
  • Big Data

Detail program execution procedure 1

Detail program execution procedure 2

Static vs Dynamic Memory Allocation

  • About Main memory
  • how a Program use memory
  • static Allocation
  • Dynamic Allocation

  • suppose this block shown a memory. so the memory is divided into smaller addressable.
  • memory unit that are called as bytes. so memory is divided into bytes.
  • every bytes is having its address

  • 만약 위와 같이 여러 Memery cell이 있다면
  • total number of bytes 는 65536이다.
  • 65536 = 64 * 1024 = 64Kb

Main Memory and how a program use memory

  • Main Memory로 옮겨가는 Programming code들은 전부 컴파일러가 되어서 machine Code 형태이다.

Static Allocation

void fun2(int i)
{
  int a; // 4bytes
}
void fun1(int x)
{
  int k = x;
  fun2(k)
}
int main()
{
  int a;
  int b;
  fun1(a);
}

  • local function {} bracket이 끝날때 마다 즉 lcoal function이 끝날때마다 Stack에 쌓여 있는 해당 function들은 deallocate가 된다.

Dynamic Allocation

int main()
{
  int* p; // 4bytes
  p = new int[5];
  p = nullptr;

}
  • Heap Memory에 행렬 5array를 만들고 stack에서 바로 heap memory를 access 할 수 없기 때문에 pointer를 이용하여서 access 한다.

  • Static Memory는 Heap Memory보다 Compile빠르다 그 이유는 static memory는 사용자가 지정한 사이즈만큼만 작동하기 때문에 compile이 빠르게 이뤄진다.

  • 반면에 Dynamic Memory 같은 경우 프로그램마다 size가 달라지므로 stack에 있는 포인터가 Heap에 있는 Memory를 Access하는데 시간이 걸리고 컴파일하는데 시간이 걸리므로 상대적으로 늦다.

Comment  Read more

2. Essential concept(Parameter passing, structure and function)

|

Parameter Passing Methods

int add(int& a, int& b)
{
  int c;
  c= a+b;
  return(c);
}
int main()
{
  int x,y,z;
  x= 10;
  y= 5;
  z = add(x,y);
  cout<<z;
}

  • Main에 생성된 data variable값을 그대로 Reference(즉 address에 있는 값을 공유하여 int a, int b의 어드레스를 x,y어드레스로 한다)

arrays as Parameter

void fun(int A[], int n)
{
  int i;
  for (i=0; i<n;i++)
    cout<<A[i];
}
int main()
{
  int A[5] = {2,4,6,8,10};
  fun(A,5);
}

  • Array an be passed only by address.
    • array parameter is working as a pointer which is pointing actual parameter.
    • actual parameter is address variable of array in base.
  • it can use pointer instead of int A[], like this
void fun(int* A, int n)
{
  int i;
  for (i=0; i<n;i++)
    cout<<A[i];
}
int main()
{
  int A[5] = {2,4,6,8,10};
  fun(A,5);
}
  • explain as above we can test
    void fun(int A[], int n)
    {
    A[0] = 25;
    }
    int main()
    {
    int A[5] = {2,4,6,8,10};
    fun(A,5);
    }
    

  • Value가 교체 된다.

Example

int[] fun(int n) // 리턴 값 데이터 유형이 int array형식
{
  int * p;
  p = new int[n]
  return p;
}
int main()
{
  int * A;
  A = fun(5);
  ---
  ---
}

int* fun(int n) // 리턴 값이 int 데이터 형식의 포인터 리턴
{
  int * p;
  p = new int[n]
  return p;
}
int main()
{
  int * A;
  A = fun(5);
  ---
  ---
}
  • Modern C++ 스타일로 이렇게 바꿀수 있다.
    int[] fun(int n) // 리턴 값 데이터 유형이 int array형식
    {
    std::share_ptr<int> p(new int[n]);
    return p;
    }
    int main()
    {
    std::share_ptr<int> A;
    A = fun(5);
    ---
    ---
    }
    
int* fun(int n) // 리턴 값이 int 데이터 형식의 포인터 리턴
{
  std::share_ptr<int> p(new int[n]);
  return p;
}
int main()
{
  std::share_ptr<int> A;
  A = fun(5);
  ---
  ---
}

Structure as Parameter

struct Rectangle
{
  int length;
  int height;
};
int area(struct Rectangle n)
{
  return n.length * n.height;
}
int main()
{
  struct Rectangle r = {10,5}
  area(r)
}

  • function parameter에 struct Ractangle 데이터 스타일의 n을 새롭게 스택에 생성하여 copy한다.

  • Refernce를 이용하여 새로운 데이터 variable을 생성하지 않고 address를 받아 쓰는 방법을 보자.

struct Rectangle
{
  int length;
  int height;
};
int area(struct Rectangle& n)
{
  return n.length * n.height;
}
int main()
{
  struct Rectangle r = {10,5}
  area(r)
}

Example

  • point터를 이용한 값 바꾸기
    struct Rectangle
    {
    int length;
    int height;
    };
    int changeLength(struct Rectangle* p, int x)
    {
    p->length = x;
    }
    int main()
    {
    struct Rectangle r = {10,5}
    changeLength(&r, 20)
    }
    

  • Reference를 이용한 값 바꾸기.
struct Rectangle
{
  int length;
  int height;
};
int changeLength(struct Rectangle& p, int x)
{
  p.length = x;
}
int main()
{
  struct Rectangle r = {10,5};
  changeLength(r, 20);
}

Example 2

void fun(struct Test t1)
{
  t1.A[0] = 10
  t1.n = 4;

}
struct Test
{
  int A[5];
  int n;
}
int main()
{
  struct Test t = {2,4,6,8,10}, 5;
  fun(t);
}
// 여기서도 t의 rvalue에 {}를 더 붙여야 하는데 안됨.. Jekyll..

structure and Functions

struct Rectangle
{
  int length;
  int height;
};
void initilize(struct Rectangle *r, int l, int b)
{
  r->length = l;
  r->height = b;
}
int area(struct Rectangle& r)
{
  return r.length * r.height;
}
void changeLength(struct Rectangle* r, int l)
{
  r->length=l;
}
int main()
{
  struct Rectangle r;

  initialize(&r,10,5);
  area(r);
  changeLength(&r,20);
}

Class and Constructor.

  • class는 오직 C++에만 있다.
  • Struct하고 비슷한 기능이지만 다른점은
    • Struct은 기본이 Public 이고
    • class는 기본이 Private 이다.
  • class에는 public, private, protect 3가지가 있다.
    • public은 다른 로컬 펑션이나 매인에서 class를 이용하여 사용할 수 있다.
    • private은 오직 해당 Class에서만 사용이 된다. 다른 로컬 펑션이나 메인에서 가져와 쓸 수 없다.
    • protected는 파생 클래스의 정의부에서 접근이 가능하지만 외부에서는 접근 불가하다.
  • Struct을 아래와 같이 바꿀 수 있다.
class Rectangle
{
public:
  Rectangle(int length, int height) : length_(length), height_(height) {}
  int area()
  {
      return length_ * height_;
  }
  void changeLength(int l)
  {
      length_=l;
  }
private:
  int length_;
  int height_;
};
int main()
{
  Rectangle r(10,5);
  int a = r.area();
  std::cout<<a<<" "; //50
  r.changeLength(20);
  a = r.area(); //100
  std::cout<<a<<" ";
  return 0;
}

Example

#include <iostream>
using namespace std;
class Rectangle
{
public:
  Rectangle(int length, int height) : length_(length), height_(height){}
  int area();
  int perimeter();
  int setLength(int k);
  int getLength();
  ~Rectangle();
private:
  int length_;
  int height_;
};
Rectangle::area()
{
  return length_*height_;
}
Rectangle::perimeter()
{
  return 2*(length_+height_);
}
Rectangle::setLength(int k)
{
  length_=k;
}
Rectangle::getLength()
{
  return length_;
}
Rectangle::~Rectangle()
{
}
int main()
{
  Rectangle r(10,5);
  cout<<r.area()<<" ";
  cout<<r.perimeter()<<" ";
  r.setLength(20);
  cout<<r.getLength()<<" ";
  return 0;
}

Template Class

  • Data 타입을 컴파일할떄 자동으로 맞춰준다.
    • 편하다
    • Class던 Data 타입이던 다 자동으로 할 수 있다.
  • Template 사용전
class Arithmateic
{
private:
  int a_;
  int b_;
public:
  Arithmateic(int a, int b) : a_(a), b_(b) {}
  int add();
  int sub();
}

Arithmateic::add()
{
  return a_ + b_;
}
Arithmateic::sub(){
  return a_ - B_;
}
int main()
{
  Arithmatic A(5,1);
  A.add();
  A.sub();
  return 0;
}
  • template 사용 후
#include <iostream>
using namespace std;
template <class T> // class안에 있는 data variable의 데이터 타입을 자동으로 맞춘다.
class Arithmateic
{
private:
  T a_;
  T b_;
public:
  Arithmateic(T a, T b) : a_(a), b_(b) {}
  T add();
  T sub();
};
template <class T>
T Arithmateic<T>::add()
{
  return a_ + b_;
}
template <class T>
T Arithmateic<T>::sub(){
  return a_ - b_;
}
int main()
{
  Arithmateic<int> A(5,1);
  A.add();
  A.sub();
  return 0;
}

Comment  Read more