Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RGBカメラによるライントレースの実装 #47

Merged
merged 24 commits into from
Dec 6, 2023

Conversation

YusukeKato
Copy link
Contributor

@YusukeKato YusukeKato commented Nov 22, 2023

What does this implement/fix?

ラズパイマウスに搭載したRGBカメラを使用してライントレースを行うサンプルを実装しました。

Does this close any currently open issues?

しません。

How has this been tested?

シミュレータ環境で動作確認

端末1で下記のコマンドを実行して、シミュレータを起動

ros2 launch raspimouse_gazebo raspimouse_with_line_follower_field.launch.py use_rgb_camera:=true camera_downward:=true

端末2で下記のコマンドを実行して、RGBカメラによるライントレースのノードを起動

ros2 launch raspimouse_ros2_examples camera_line_follower.launch.py mouse:=false use_camera_node:=false

端末3で下記のコマンドを実行して、switchesトピックを介してcmd_velトピックの配信

ros2 topic pub --once /switches raspimouse_msgs/msg/Switches "{switch0: false, switch1: false, switch2: true}"

止める場合は下記のコマンドを実行

ros2 topic pub --once /switches raspimouse_msgs/msg/Switches "{switch0: true, switch1: false, switch2: false}"

実機で動作確認

下記のコマンドを実行

ros2 launch raspimouse_ros2_examples camera_line_follower.launch.py

スイッチ2を押すと走り始めて、スイッチ0を押すと止まります。

Any other comments?

シミュレータで動作確認する場合、下記のリポジトリが必要です。

raspimouse_descriptionのros2ブランチ

https://github.com/rt-net/raspimouse_description/tree/ros2

raspimouse_simのros2ブランチ

https://github.com/rt-net/raspimouse_sim/tree/ros2

Checklists

@YusukeKato YusukeKato self-assigned this Nov 22, 2023
@YusukeKato YusukeKato added the Type: Feature New Feature label Nov 22, 2023
@YusukeKato YusukeKato marked this pull request as ready for review November 22, 2023 09:32
@ShotaAk
Copy link
Contributor

ShotaAk commented Nov 28, 2023

image

オドメトリがずれますね。raspimouse_simで呼び出しているコントローラのパラメータを見直して、改善するか確認してほしいです。

(自己位置補正がないので限界はあります)

Copy link
Contributor

@ShotaAk ShotaAk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

動作確認できました。コードレビューは途中です。

一旦コメントの確認と修正お願いします。

@@ -0,0 +1,82 @@
// Copyright 2020 RT Corporation
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// Copyright 2020 RT Corporation
// Copyright 2023 RT Corporation

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ソースファイルも同様に対応してください。

@@ -0,0 +1,90 @@
# Copyright 2020 RT Corporation
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# Copyright 2020 RT Corporation
# Copyright 2023 RT Corporation

@@ -0,0 +1,272 @@
// Copyright 2020 RT Corporation
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// Copyright 2020 RT Corporation
// Copyright 2023 RT Corporation

Comment on lines 30 to 31
using namespace std::chrono_literals;
using CallbackReturn = rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

他コードへの影響を抑えるため、usingはnamespace内で使用してください。

namespace hoge
{
  using fuga = piyo;
}

void Camera_Follower::image_callback(const sensor_msgs::msg::Image::SharedPtr msg_image)
{
auto cv_img = cv_bridge::toCvShare(msg_image, msg_image->encoding);
auto msg = std::make_unique<sensor_msgs::msg::Image>();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

msgは使われてないです。

Suggested change
auto msg = std::make_unique<sensor_msgs::msg::Image>();

Comment on lines 67 to 70
const double LINEAR_VEL = 0.2; // unit: m/s
const double ANGULAR_VEL = -0.8; // unit: rad/s
const double TARGET_AREA = 0.1; // 0.0 ~ 1.0
const double OBJECT_AREA_THRESHOLD = 0.01; // 0.0 ~ 1.0
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

コンパイル時に定数化できるのでconstexprを使いましょう。

Suggested change
const double LINEAR_VEL = 0.2; // unit: m/s
const double ANGULAR_VEL = -0.8; // unit: rad/s
const double TARGET_AREA = 0.1; // 0.0 ~ 1.0
const double OBJECT_AREA_THRESHOLD = 0.01; // 0.0 ~ 1.0
constexpr double LINEAR_VEL = 0.2; // unit: m/s
constexpr double ANGULAR_VEL = -0.8; // unit: rad/s
constexpr double TARGET_AREA = 0.1; // 0.0 ~ 1.0
constexpr double OBJECT_AREA_THRESHOLD = 0.01; // 0.0 ~ 1.0

const double TARGET_AREA = 0.1; // 0.0 ~ 1.0
const double OBJECT_AREA_THRESHOLD = 0.01; // 0.0 ~ 1.0

// Detects an object and tracks it
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ここではオブジェクトをdetectしてないので文章を変えてください。

detectされたobjectを追うように速度を出す ならわかります。

Comment on lines 82 to 88
if (switches_.switch0) {
RCLCPP_INFO(this->get_logger(), "Stop following.");
can_publish_cmdvel_ = false;
} else if (switches_.switch2) {
RCLCPP_INFO(this->get_logger(), "Start following.");
can_publish_cmdvel_ = true;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ここの処理はswitchesのcallback関数に移動したほうが分かりやすいです。

そうするとswitches_変数が不要になります。

}
switches_ = raspimouse_msgs::msg::Switches(); // Reset switch values

if (!can_publish_cmdvel_) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can_publish_cmdvel_がfalseでもcmd_velをpublishしているので、変数名と処理が一致してません。

enable_following_ のような変数名はどうでしょうか?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ありがとうございます。
enable_following_に変更しました。

msg.header.frame_id = "camera_frame";
}

void Camera_Follower::following(const cv::Mat & input_frame, cv::Mat & result_frame)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ここでは追跡ではなく、追跡するための物体検出をしています。
関数名を変更してください。

Copy link
Contributor Author

@YusukeKato YusukeKato Dec 5, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

detecting_line()に変更しました。

Copy link
Contributor

@ShotaAk ShotaAk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

その他のコードを読みました。コメントの確認おねがします。

Comment on lines 180 to 182
cv::putText(
result_frame, text, cv::Point(0, 30),
cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(255, 0, 0), 2);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

テキストが見にくいので明るい色に変えてください。

image

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

青から白に変更しました。

);
// Normalize the the contour area to [0.0, 1.0].
object_normalized_area_ = max_area / (input_frame.rows * input_frame.cols);
object_is_detected_ = true;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

object_is_detected_ の変更箇所をわかりやすくするため、
この関数の返り値をbool型に変更してください

例(image_callback()内での処理):

 // following関数名は適宜変更してください。
 object_is_detected_ = following();

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

この変更に伴い、following関数をconstメンバ関数にしてください。

bool following() const;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

この関数にconstを付けると

object_normalized_area_ = max_area / (input_frame.rows * input_frame.cols);

の行でエラーが発生します。

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

変数が2つありましたね、変更なしでOKです。

"Service motor_power is not avaliable.");
return CallbackReturn::FAILURE;
}
auto request = std::make_shared<std_srvs::srv::SetBool::Request>();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

サービスが失敗したらFAILUREするように実装してくれると嬉しいです。

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

「サービスが失敗したらFAILUREする」とは具体的にはどういう処理を指すでしょうか。
単純にプログラムを終了すれば良いでしょうか。

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

motor_power サービスが失敗する可能性もあるので、そのときはon_activateが失敗するように実装お願いします。

参考情報:https://robotics.stackexchange.com/a/96076/37280

auto future_result = motor_power_client_->async_send_request(request);
if (rclcpp::spin_until_future_complete(this->get_node_base_interface(), result) 
    != rclcpp::executor::FutureReturnCode::SUCCESS)
{
  return CallbackReturn::FAILURE;
}

ただ、spin周りはROS 2仕様による不具合があるので、エラーが出る場合はあきらめましょう。
ros2/rclcpp#1916

YusukeKato and others added 3 commits December 1, 2023 16:15
Co-authored-by: Shota Aoki <[email protected]>
Co-authored-by: Shota Aoki <[email protected]>
Co-authored-by: Shota Aoki <[email protected]>
@YusukeKato
Copy link
Contributor Author

image

オドメトリがずれますね。raspimouse_simで呼び出しているコントローラのパラメータを見直して、改善するか確認してほしいです。

(自己位置補正がないので限界はあります)

こちらのraspimouse_simのPRでオドメトリのズレに対応しました。
rt-net/raspimouse_sim#76

@ShotaAk
Copy link
Contributor

ShotaAk commented Dec 6, 2023

オドメトリの調整いい感じです
image

Comment on lines 77 to 78
// Detect and follow the line
// when the number of pixels of the object is greater than the threshold.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ここではDetectしてないので訂正してほしいです。(画像処理もここで行われている と勘違いします)

Suggested change
// Detect and follow the line
// when the number of pixels of the object is greater than the threshold.
// Follow the line
// when the number of pixels of the object is greater than the threshold.

);
// Normalize the the contour area to [0.0, 1.0].
object_normalized_area_ = max_area / (input_frame.rows * input_frame.cols);
object_is_detected_ = true;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

変数が2つありましたね、変更なしでOKです。

Copy link
Contributor

@ShotaAk ShotaAk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

細かいところにコメントしました。確認お願いします

"Service motor_power is not avaliable.");
return CallbackReturn::FAILURE;
}
auto request = std::make_shared<std_srvs::srv::SetBool::Request>();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

motor_power サービスが失敗する可能性もあるので、そのときはon_activateが失敗するように実装お願いします。

参考情報:https://robotics.stackexchange.com/a/96076/37280

auto future_result = motor_power_client_->async_send_request(request);
if (rclcpp::spin_until_future_complete(this->get_node_base_interface(), result) 
    != rclcpp::executor::FutureReturnCode::SUCCESS)
{
  return CallbackReturn::FAILURE;
}

ただ、spin周りはROS 2仕様による不具合があるので、エラーが出る場合はあきらめましょう。
ros2/rclcpp#1916

Comment on lines 114 to 116
void Camera_Follower::convert_frame_to_message(
const cv::Mat & frame, sensor_msgs::msg::Image & msg)
{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

これもconstメンバ関数にできそうです

@YusukeKato
Copy link
Contributor Author

下記のコードを追加したところエラーが発生し、ライントレースは正常に動きませんでした。

auto future_result = motor_power_client_->async_send_request(request);
if (rclcpp::spin_until_future_complete(this->get_node_base_interface(), future_result) 
    != rclcpp::FutureReturnCode::SUCCESS)
{
  return CallbackReturn::FAILURE;
}

エラー内容↓

[component_container_mt-1] [ERROR] [1701853265.381801467] [camera_follower]: Caught exception in callback for transition 13
[component_container_mt-1] [ERROR] [1701853265.381822847] [camera_follower]: Original error: Node '/camera_follower' has already been added to an executor.
[component_container_mt-1] [WARN] [1701853265.381833738] [camera_follower]: Error occurred while doing error handling.
[lifecycle_node_manager-2] [ERROR] [1701853265.382155052] [manager]: Failed to activate nodes.
[component_container_mt-1] [WARN] [1701853265.452359650] [LifecyclePublisher]: Trying to publish message on the topic '/result_image', but the publisher is not activated

@ShotaAk
Copy link
Contributor

ShotaAk commented Dec 6, 2023

エラーについて了解です。ノード外部にexecutorがいるのでspinの権限を取られているんですよね。。。

ひとまずこのままにしましょう

Copy link
Contributor

@ShotaAk ShotaAk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OKです!マージします

@ShotaAk ShotaAk merged commit 153c25c into master Dec 6, 2023
2 checks passed
@ShotaAk ShotaAk deleted the add-camera-line-follower branch December 6, 2023 09:36
@ShotaAk ShotaAk mentioned this pull request Jan 12, 2024
2 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Type: Feature New Feature
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants