// it's for Latex

pages

[hector_slam code review] #03. hector_mapping : MapDimensionProperties.h

MapDimensionProperties.h







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
//=================================================================================================
// Copyright (c) 2011, Stefan Kohlbrecher, TU Darmstadt
// All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//     * Neither the name of the Simulation, Systems Optimization and Robotics
//       group, TU Darmstadt nor the names of its contributors may be used to
//       endorse or promote products derived from this software without
//       specific prior written permission.
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//=================================================================================================
#ifndef __MapDimensionProperties_h_
#define __MapDimensionProperties_h_
class MapDimensionProperties
{
public:
  MapDimensionProperties()
    : topLeftOffset(-1.0f,-1.0f)
    , mapDimensions(-1,-1)
    , cellLength(-1.0f)
  {}
  MapDimensionProperties(const Eigen::Vector2f& topLeftOffsetIn, const Eigen::Vector2i& mapDimensionsIn, float cellLengthIn)
    : topLeftOffset(topLeftOffsetIn)
    , mapDimensions(mapDimensionsIn)
    , cellLength(cellLengthIn)
  {
    mapLimitsf = (mapDimensionsIn.cast<float>()).array() - 1.0f;
  }
  bool operator==(const MapDimensionProperties& other) const
  {
    return (topLeftOffset == other.topLeftOffset) && (mapDimensions == other.mapDimensions) && (cellLength == other.cellLength);
  }
  bool hasEqualDimensionProperties(const MapDimensionProperties& other) const
  {
    return (mapDimensions == other.mapDimensions);
  }
  bool hasEqualTransformationProperties(const MapDimensionProperties& other) const
  {
     return  (topLeftOffset == other.topLeftOffset) && (cellLength == other.cellLength);
  }
  bool pointOutOfMapBounds(const Eigen::Vector2f& coords) const
  {
    return ((coords[0< 0.0f) || (coords[0> mapLimitsf[0]) || (coords[1< 0.0f) || (coords[1> mapLimitsf[1]));
  }
  void setMapCellDims(const Eigen::Vector2i& newDims)
  {
    mapDimensions = newDims;
    mapLimitsf = (newDims.cast<float>()).array() - 2.0f;
  }
  void setTopLeftOffset(const Eigen::Vector2f& topLeftOffsetIn)
  {
    topLeftOffset = topLeftOffsetIn;
  }
  void setSizeX(int sX) { mapDimensions[0= sX; };
  void setSizeY(int sY) { mapDimensions[1] = sY; };
  void setCellLength(float cl) { cellLength = cl; };
  const Eigen::Vector2f& getTopLeftOffset() const { return topLeftOffset; };
  const Eigen::Vector2i& getMapDimensions() const { return mapDimensions; };
  int getSizeX() const { return mapDimensions[0]; };
  int getSizeY() const { return mapDimensions[1]; };
  float getCellLength() const { return cellLength; };
protected:
  Eigen::Vector2f topLeftOffset;
  Eigen::Vector2i mapDimensions;
  Eigen::Vector2f mapLimitsf;
  float cellLength;
};
#endif
cs

위 내용을 하나하나 분석해보자.
먼저 시작하기 전에 주의할 사항은
Dimention이 아니라 Dimension이란 것이다.
즉, 맵의 차원이 아니라 맵의 면적, 크기 에 대한 것이다.


  MapDimensionProperties()
    : topLeftOffset(-1.0f,-1.0f)
    , mapDimensions(-1,-1)
    , cellLength(-1.0f)
  {}

MapDimensionProperties 클래스의 디폴트 생성자이다.

이 때, 콜론(:) 뒤의 내용들은 초기화 리스트이며
멤버 변수 topLeftOffset를 (-1.0f,-1.0f)로
멤버 변수 mapDimensions를 (-1,-1)로
멤버 변수 cellLength를 (-1.0f)로
초기화하는 역할을 한다.

그냥 생성자 함수{} 내에서 초기화하는 것과 이렇게 초기화 리스트를 쓰는 것의 차이는
초기화 리스트에서 초기화를 하는 경우, 생성자가 호출될 때 객체의 생성과 초기화가 한 번에 이루어진다는 것이다.
생성자 함수 {} 내에서 초기화를 하는 경우, 객체가 생성되어 default 생성자로 초기화된 상태에서 다시 한 번 할당을 받게 되므로 default 할당 - user 할당 2단계를 거치게 되어 오버헤드가 생긴다.

초기화 리스트를 써야만 하는 상황은 크게 다음과 같다.

- 클래스가 레퍼런스를 멤버로 가질 때
- non static const 멤버가 있을 때
- default 생성자가 없을 때
- base class 를 초기화할 때
생성자 파라미터의 이름이 데이터 멤버랑 같을 때 ( 이 경우는 this를 써서 해결할 수도 있다. )


  MapDimensionProperties(const Eigen::Vector2f& topLeftOffsetIn, const Eigen::Vector2i& mapDimensionsIn, float cellLengthIn)
    : topLeftOffset(topLeftOffsetIn)
    , mapDimensions(mapDimensionsIn)
    , cellLength(cellLengthIn)
  {
    mapLimitsf = (mapDimensionsIn.cast<float>()).array() - 1.0f;
  }

MapDimensionProperties 클래스의 매개변수 생성자이다.
각 멤버변수의 값들을 매개변수로 받아 초기화한다.

    mapLimitsf = (mapDimensionsIn.cast<float>()).array() - 1.0f;

위 내용은 다음과 같다.

mapDimensionsIn.cast<float>()
: mapDimensionsIn 을 float 형태로 cast(형변환) 한다.

(mapDimensionsIn.cast<float>()).array()
: 이후 vector 형태를 array 형태로 변환한다.

mapLimitsf = (mapDimensionsIn.cast<float>()).array() - 1.0f;
: 그리고 이 배열에서 -1.0f를 빼 mapLimitsf 로 정의한다.

Dimensions는 차원이 아니라 면적.
즉, 사이즈를 1만큼 빼서 맵을 다룰 때 안정적으로 하기 위해서이다.



  bool operator==(const MapDimensionProperties& other) const
  {
    return (topLeftOffset == other.topLeftOffset) && (mapDimensions == other.mapDimensions) && (cellLength == other.cellLength);
  }

"operator" 는 "연산자 오버로딩" 이라고 부은다.

그 중에서도 "operator==" 는 "비교연산자 오버로딩" 이 된다.

기본적으로 프로그램에서 연산자는 정수 혹은 실수 등에만 적용되게 된다.

하지만 위와같은 "연산자 오버로딩" 을 통해서 클래스와 같은 구조체 형태 끼리도
비교연산이 가능해진다.

operator==(const MapDimensionProperties& other)
: MapDimensionProperties 클래스에 대해 비교연산을 하겠다.

return (topLeftOffset == other.topLeftOffset) && (mapDimensions == other.mapDimensions) && (cellLength == other.cellLength);
: MapDimensionProperties 클래스 형태의 각 객체에 대해 멤버변수끼리 비교하여 모든 값들이 같은 경우 true를 return하겠다.


  bool hasEqualDimensionProperties(const MapDimensionProperties& other) const
  {
    return (mapDimensions == other.mapDimensions);
  }


앞에서 정의된 operator 연산자를 이용하여 mapDimensions에 대해서 비교연산을 진행한다.

예를 들어,

a = MapDimensionProperties();
b = MapDimensionProperties();
a.hasEqualDimensionProperties(b);

와 같이 사용할 수 있는 것이다.



  bool hasEqualTransformationProperties(const MapDimensionProperties& other) const
  {
     return  (topLeftOffset == other.topLeftOffset) && (cellLength == other.cellLength);
  }

이 부분도 위와 같다.





  bool pointOutOfMapBounds(const Eigen::Vector2f& coords) const
  {
    return ((coords[0< 0.0f) || (coords[0> mapLimitsf[0]) || (coords[1< 0.0f) || (coords[1> mapLimitsf[1]));
  }

인자로 넘어온 coordinates가 MapBounds 안에 존재하는 정상적인 값인지 판단한다.
0.0f 보다 작거나 mapLimitsf보다 크다면 true를 반환한다.
true를 반환한다는 것은 해당 coordinates가 MapBounds에서 벗어난다는 의미이다.
false를 반환한다는 것은 해당 coordinates가 MapBounds 안에 존재한다는 것이다.



  void setMapCellDims(const Eigen::Vector2i& newDims)
  {
    mapDimensions = newDims;
    mapLimitsf = (newDims.cast<float>()).array() - 2.0f;
  }

Map의 Cell의 Dimension을 setting한다.
이를 통해 mapLimitsf의 값도 새로 정의해준다.



  void setTopLeftOffset(const Eigen::Vector2f& topLeftOffsetIn)
  {
    topLeftOffset = topLeftOffsetIn;
  }

TopLeftOffset 값을 setting한다.



  void setSizeX(int sX) { mapDimensions[0= sX; };
  void setSizeY(int sY) { mapDimensions[1] = sY; };

map의 X축과 Y축의 size를 setting한다.



  void setCellLength(float cl) { cellLength = cl; };

cell의 length를 설정한다.



  const Eigen::Vector2f& getTopLeftOffset() const { return topLeftOffset; };
  const Eigen::Vector2i& getMapDimensions() const { return mapDimensions; };
  int getSizeX() const { return mapDimensions[0]; };
  int getSizeY() const { return mapDimensions[1]; };
  float getCellLength() const { return cellLength; };

각 멤버변수 값들을 가져올 수 있는 함수들이다.



protected:
  Eigen::Vector2f topLeftOffset;
  Eigen::Vector2i mapDimensions;
  Eigen::Vector2f mapLimitsf;
  float cellLength;

각 멤버변수들이다.



댓글 없음:

댓글 쓰기