Skip to content

Commit e85473e

Browse files
authored
Merge pull request #4 from amslabtech/localizer
Localizer
2 parents 071f948 + a0986f5 commit e85473e

19 files changed

Lines changed: 1141 additions & 46 deletions

a_localizer/CMakeLists.txt

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
cmake_minimum_required(VERSION 3.8)
2+
project(team_a_localizer)
3+
4+
# find dependencies
5+
find_package(ament_cmake_auto REQUIRED)
6+
# package.xmlのdependをチェックして自動的にfind_packageしてくれる
7+
ament_auto_find_build_dependencies()
8+
# 実行ファイルを作成する
9+
ament_auto_add_executable(${PROJECT_NAME}_node
10+
src/localizer.cpp
11+
src/localizer_node.cpp
12+
src/odom_model.cpp
13+
src/particle.cpp
14+
src/pose.cpp)
15+
# launchファイルをインストール(ament_package_indexが探せる場所に置く)
16+
install(DIRECTORY
17+
launch
18+
param
19+
DESTINATION share/${PROJECT_NAME}/
20+
)
21+
# ヘッダーのインストールや共有ライブラリのエクスポート等を自動で行ってくれる
22+
ament_auto_package()
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
node_name1:
2+
ros__parameters:
3+
4+
# 基本設定
5+
hz: ###### # ループ周期 [Hz]
6+
particle_num: ###### # パーティクルの個数 [-]
7+
max_particle_num: ###### #パーティクルの最大個数
8+
min_particle_num: ###### #パーティクルの最小個数
9+
move_dist_th: ###### # ロボットの移動開始判断用(スタートからの距離の閾値)[m]
10+
11+
# 初期ポーズ関連
12+
init_x: 0.0 # 初期位置 [m]
13+
init_y: 0.0 # 初期位置 [m]
14+
init_yaw: 0.0 # 初期姿勢 [rad]
15+
init_x_dev: 0.50 # 初期位置xの標準偏差 [m]
16+
init_y_dev: 0.65 # 初期位置yの標準偏差 [m]
17+
init_yaw_dev: 0.5 # 初期姿勢の標準偏差 [rad]
18+
19+
# リセット関連
20+
alpha_th: 0.0017 # リセットに関する平均尤度の閾値 [-]
21+
reset_count_limit: 5 # 連続リセットの回数の上限 [-]
22+
expansion_x_dev: 0.05 # 膨張リセットの位置xの標準偏差 [m]
23+
expansion_y_dev: 0.05 # 膨張リセットの位置yの標準偏差 [m]
24+
expansion_yaw_dev: 0.01 # 膨張リセットの姿勢の標準偏差 [rad]
25+
26+
# センサ関連
27+
laser_step: 10 # 何本ずつレーザを見るか(全1080本)[-]
28+
sensor_noise_ratio: 0.03 # 距離に対するセンサノイズ比 [-]
29+
30+
# --- 柱に関する角度範囲の配列 [rad] ---
31+
# 以下が無視される
32+
# [0] < angle < [1], [2] < angle
33+
# [num] -> num:index
34+
ignore_angle_range_list: [#####, #####, #####]
35+
36+
# フラグ
37+
flag_init_noise: true # 初期位置にノイズを加えるか
38+
flag_broadcast: true # tf情報を含むbagファイルを使うときはfalse
39+
flag_reverse: false # 初期姿勢を逆にするか
40+
is_visible: true # パーティクルクラウドを表示(パブリッシュ)するか
41+
42+
# ===== クラスOdomModel =====
43+
ff: 0.17 # 直進1[m]で生じる道のりのばらつきの標準偏差 [m]
44+
fr: 0.0005 # 回転1[rad]で生じる道のりのばらつきの標準偏差 [m]
45+
rf: 0.13 # 直進1[m]で生じる向きのばらつきの標準偏差 [rad]
46+
rr: 0.2 # 回転1[rad]で生じる向きのばらつきの標準偏差 [rad]
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
#ifndef LOCALIZER_HPP
2+
#define LOCALIZER_HPP
3+
4+
#include <rclcpp/rclcpp.hpp>
5+
#include <functional> // bind, placeholders
6+
#include <memory> // SharedPtr
7+
#include <type_traits>
8+
#include <utility>
9+
#include <nav_msgs/msg/occupancy_grid.hpp>
10+
#include <nav_msgs/msg/odometry.hpp>
11+
#include <sensor_msgs/msg/laser_scan.hpp>
12+
#include <geometry_msgs/msg/pose.hpp>
13+
#include <geometry_msgs/msg/pose_stamped.hpp>
14+
#include <geometry_msgs/msg/pose_array.hpp>
15+
#include <tf2/utils.h>
16+
#include <tf2_ros/transform_broadcaster.h>
17+
#include <tf2_geometry_msgs/tf2_geometry_msgs.hpp>
18+
19+
#include <random>
20+
21+
#include "localizer/odom_model.hpp"
22+
#include "localizer/particle.hpp"
23+
#include "localizer/pose.hpp"
24+
25+
class Localizer : public rclcpp::Node
26+
{
27+
public:
28+
Localizer(); // デフォルトコンストラクタ
29+
int getOdomFreq(); // 制御周期(hz_)を返す関数
30+
void initialize(); // パーティクルの初期化
31+
void process(); // main文のループ内で実行する関数
32+
private:
33+
// ----- 関数(引数あり)------
34+
// コールバック関数
35+
void map_callback(const nav_msgs::msg::OccupancyGrid::SharedPtr msg);
36+
void odom_callback(const nav_msgs::msg::Odometry::SharedPtr msg);
37+
void laser_callback(const sensor_msgs::msg::LaserScan::SharedPtr msg);
38+
39+
// その他の関数
40+
double normalize_angle(double angle); // 適切な角度(-M_PI ~ M_PI)を返す
41+
double norm_rv(const double mean, const double stddev); // ランダム変数生成関数(正規分布)
42+
void resampling(const double alpha); // リサンプリング(系統サンプリング)
43+
44+
// ----- 関数(引数なし)------
45+
void reset_weight(); // パーティクルの重みの初期化
46+
void broadcast_odom_state(); // map座標系からみたodom座標系の位置と姿勢をtfでbroadcast
47+
void localize(); // 自己位置推定
48+
void motion_update(); // 動作更新
49+
void observation_update(); // 観測更新
50+
void estimate_pose(); // 推定位置の決定
51+
void normalize_belief(); // 重みの正規化
52+
void expansion_resetting(); // 膨張リセット
53+
void publish_estimated_pose(); // 推定位置のパブリッシュ
54+
void publish_particles(); // パーティクルクラウドのパブリッシュ
55+
double calc_marginal_likelihood(); // 周辺尤度の算出
56+
57+
// Subscriber
58+
rclcpp::Subscription<nav_msgs::msg::OccupancyGrid>::SharedPtr sub_map_;
59+
rclcpp::Subscription<nav_msgs::msg::Odometry>::SharedPtr sub_odom_;
60+
rclcpp::Subscription<sensor_msgs::msg::LaserScan>::SharedPtr sub_laser_;
61+
62+
// Publisher
63+
rclcpp::Publisher<geometry_msgs::msg::PoseStamped>::SharedPtr pub_estimated_pose_;
64+
rclcpp::Publisher<geometry_msgs::msg::PoseArray>::SharedPtr pub_particle_cloud_;
65+
66+
// ----- 変数 -----
67+
// 基本設定
68+
int hz_; // ループ周波数 [Hz]
69+
int particle_num_; // パーティクルの個数 [-]
70+
int max_particle_num_; // パーティクルの個数 [-]
71+
int min_particle_num_; // パーティクルの個数 [-]
72+
double move_dist_th_; // ロボットの移動開始判断用(スタートからの距離の閾値)[m] int reset_counter = 0; // 連続リセットの回数 [-]
73+
// 初期ポーズ関連
74+
double init_x_; // 初期位置 [m]
75+
double init_y_; // 初期位置 [m]
76+
double init_yaw_; // 初期姿勢 [rad]
77+
double init_x_dev_; // 初期位置xの標準偏差 [m]
78+
double init_y_dev_; // 初期位置yの標準偏差 [m]
79+
double init_yaw_dev_; // 初期姿勢の標準偏差 [rad]
80+
// リセット関連
81+
double alpha_th_; // リセットに関する平均尤度の閾値 [-]
82+
int reset_counter = 0; // 連続リセットの回数 [-]
83+
int reset_count_limit_; // 連続リセットの回数の上限 [-]
84+
double expansion_x_dev_; // 膨張リセットの位置xの標準偏差 [m]
85+
double expansion_y_dev_; // 膨張リセットの位置yの標準偏差 [m]
86+
double expansion_yaw_dev_; // 膨張リセットの姿勢の標準偏差 [rad]
87+
// センサ関連
88+
int laser_step_; // 何本ずつレーザを見るか [-]
89+
double sensor_noise_ratio_; // 距離に対するセンサノイズ比 [-]
90+
91+
Pose estimated_pose_; // 推定位置
92+
OdomModel odom_model_; // odometryのモデル
93+
94+
// リスト
95+
std::vector<Particle> particles_; // パーティクルクラウド(計算用)
96+
std::vector<double> ignore_angle_range_list_; // 柱に関する角度範囲の配列 [rad]
97+
98+
// msg受け取りフラグ
99+
bool flag_map_ = false;
100+
bool flag_odom_ = false;
101+
bool flag_laser_ = false;
102+
103+
// その他のフラグ
104+
bool flag_move_ = false; // 機体が動いたか判断用
105+
bool flag_init_noise_; // 初期位置にノイズを加えるか
106+
bool flag_broadcast_; // tf broadcastをするか
107+
bool flag_reverse_; // 初期姿勢を逆にするか
108+
bool is_visible_; // パーティクルクラウドをパブリッシュするか
109+
110+
// OdomModel関連
111+
double ff_; // 直進1[m]で生じる道のりのばらつきの標準偏差 [m]
112+
double fr_; // 回転1[rad]で生じる道のりのばらつきの標準偏差 [m]
113+
double rf_; // 直進1[m]で生じるロボットの向きのばらつきの標準偏差 [rad]
114+
double rr_; // 回転1[rad]で生じるロボットの向きのばらつきの標準偏差 [rad]
115+
116+
// 正規分布用乱数
117+
std::random_device seed_gen_;
118+
std::default_random_engine engine_;
119+
120+
// 各種オブジェクト
121+
nav_msgs::msg::OccupancyGrid map_; // map_serverから受け取るマップ
122+
nav_msgs::msg::Odometry last_odom_; // 最新のodometry
123+
nav_msgs::msg::Odometry prev_odom_; // 1制御周期前のodometry
124+
sensor_msgs::msg::LaserScan laser_; // レーザ値
125+
geometry_msgs::msg::PoseStamped estimated_pose_msg_; // 推定位置
126+
geometry_msgs::msg::PoseArray particle_cloud_msg_; // パーティクルクラウド(パブリッシュ用)
127+
};
128+
129+
#endif
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#ifndef ODOM_MODEL_HPP
2+
#define ODOM_MODEL_HPP
3+
4+
#include <random>
5+
6+
class OdomModel
7+
{
8+
public:
9+
OdomModel(); // デフォルトコンストラクタ
10+
OdomModel(const double ff, const double fr, const double rf, const double rr); // コンストラクタ
11+
OdomModel& operator =(const OdomModel& model); // 代入演算子
12+
13+
void set_dev(const double length, const double angle); // 標準偏差の設定
14+
double get_fw_noise(); // 直進に関するノイズの取得
15+
double get_rot_noise(); // 回転に関するノイズの取得
16+
17+
private:
18+
double fw_var_per_fw_; // ffの分散
19+
double fw_var_per_rot_; // frの分散
20+
double rot_var_per_fw_; // rfの分散
21+
double rot_var_per_rot_; // rrの分散
22+
23+
double fw_dev_; // 直進に関するノイズ
24+
double rot_dev_; // 回転に関するノイズ
25+
26+
// 正規分布
27+
std::normal_distribution<> std_norm_dist_;
28+
std::random_device seed_gen_;
29+
std::default_random_engine engine_;
30+
};
31+
32+
#endif
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#ifndef PARTICLE_HPP
2+
#define PARTICLE_HPP
3+
4+
#include <nav_msgs/msg/occupancy_grid.hpp>
5+
#include <sensor_msgs/msg/laser_scan.hpp>
6+
#include "localizer/pose.hpp"
7+
8+
class Particle
9+
{
10+
public:
11+
Particle(); // デフォルトコンストラクタ
12+
Particle(const double x, const double y, const double yaw, const double weight); // コンストラクタ
13+
Particle& operator =(const Particle& p); // 代入演算子
14+
15+
// accessor
16+
void set_weight(const double weight); // 重みのセット
17+
double weight() const { return weight_; }
18+
19+
// 尤度関数
20+
double likelihood(const nav_msgs::msg::OccupancyGrid& map, const sensor_msgs::msg::LaserScan& laser,
21+
const double sensor_noise_ratio, const int laser_step, const std::vector<double>& ignore_angle_range_list);
22+
23+
// --- メンバ変数 ---
24+
Pose pose_;
25+
26+
private:
27+
// 柱か判断
28+
bool is_ignore_angle(double angle, const std::vector<double>& ignore_angle_range_list);
29+
30+
// 壁までの距離を算出
31+
double calc_dist_to_wall(double x, double y, const double laser_angle, const nav_msgs::msg::OccupancyGrid& map,
32+
const double laser_range, const double sensor_noise_ratio);
33+
34+
// 座標からグリッドのインデックスを返す
35+
int xy_to_grid_index(const double x, const double y, const nav_msgs::msg::MapMetaData& map_info);
36+
37+
// マップ内か判断
38+
bool in_map(const int grid_index, const int map_data_size);
39+
40+
// 確率密度関数(正規分布)
41+
double norm_pdf(const double x, const double mean, const double stddev);
42+
43+
// --- メンバ変数 ---
44+
double weight_; // [-]
45+
};
46+
47+
#endif
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#ifndef POSE_HPP
2+
#define POSE_HPP
3+
4+
#include <cmath>
5+
6+
class Pose
7+
{
8+
public:
9+
Pose(); // デフォルトコンストラクタ
10+
Pose(const double x, const double y, const double yaw); // コンストラクタ
11+
Pose& operator =(const Pose& pose); // 代入演算子
12+
Pose& operator /=(const double a); // 複合代入演算子/=
13+
14+
// accessor
15+
void set(const double x, const double y, const double yaw);
16+
double x() const { return x_; }
17+
double y() const { return y_; }
18+
double yaw() const { return yaw_; }
19+
20+
// パーティクルの移動
21+
void move(double length, double direction, double rotation, const double fw_noise, const double rot_noise);
22+
23+
// 適切な角度(-M_PI ~ M_PI)に変更
24+
void normalize_angle();
25+
26+
// private:
27+
double x_; // [m]
28+
double y_; // [m]
29+
double yaw_; // [rad]
30+
};
31+
32+
#endif

a_localizer/package.xml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?xml version="1.0"?>
2+
<package format="3">
3+
<name>team_a_localizer</name>
4+
<version>0.0.0</version>
5+
<description>the team_a_localizer package</description>
6+
<maintainer email="amsl@todo.todo">amsl</maintainer>
7+
<license>TODO</license>
8+
9+
<buildtool_depend>ament_cmake_ros</buildtool_depend>
10+
11+
<depend>ament_cmake_auto</depend>
12+
<depend>rclcpp</depend>
13+
<depend>nav_msgs</depend>
14+
<depend>sensor_msgs</depend>
15+
<depend>geometry_msgs</depend>
16+
<depend>random</depend>
17+
<depend>tf2</depend>
18+
<depend>tf2_ros</depend>
19+
<depend>tf2_geometry_msgs</depend>
20+
21+
<export>
22+
<build_type>ament_cmake</build_type>
23+
</export>
24+
</package>

0 commit comments

Comments
 (0)