oit-ipbl / Integration

0 stars 0 forks source link

Message exchange between a ROS node and multi Windows programs #6

Closed jinno-oit closed 3 years ago

jinno-oit commented 3 years ago

https://github.com/oit-ipbl/Integration/blob/65982735fe2b98f40ee0595164d11fdb4b9c33f8/win_multi/win_multi.md についてです.


show_hand_game_win.py このプログラムはmediapipesを利用して,コンピュータが指示した手をユーザがカメラに翳すゲームです

コンピュータ->ROSの方が良い?


start_game functionでは,ROSとの間でメッセージの送受信が行われる.例えば,message_from_ros = ros_bridge_tcp.wait_response(pub_msg, hand_types, timeout=30) では,pub_msgをROSに送信し,hand_typesに含まれる文字列がROSから返ってくることを最大30秒待ち,返り値をmessage_from_rosに保存する

ここのところで,第二引数についてもう少し説明した方が良いかもしれません. ・第二引数は文字列のリストで,その中に格納されている文字列と完全一致する場合のみ受け取ります(丁寧すぎる?) ・Noneにするとどのような内容でも受け取るようにできます(ただし,予期せぬメッセージを受け取って先に進んでしまう可能性がある) ※ちなみに,Message exchange between a Windows program and a ROS nodeの方では,ros_bridge_tcp.wait_response(pub_msg, timeout=10)のように書かれてもいるようで,Noneと入れなくても同じことができそうです.どちらかに統一しておいてあげた方が良いと思います.Noneと入れた方が安心な気はします.


現在の仕様では,start_on_windows_single.pyはwhile True:でROSからのメッセージ送信を無限ループで待機するようになっている

これにプラスして,無限ループで待機状態のときにROSから"The end"というメッセージが届くと無限ループを終了するということを追加するのが良いと思います.


start_on_win_single.py や start_on_ros_single.py などで,「呼び出す処理を追加する」となっていますが,配布するプログラムでは削除しておきますか?


show_hand_game_ros.py と show_hand_game_win.py のやりとり部分にコメントで番号を付けてあげると横に並べてみたときに良いのかもしれません.また,画像処理部分が長いとタイムアウトになる可能性があることも伝えたいところですが,図を作るのが良いかもですね.ちょっと考えてみます.


たまに正常に動作しない場合があります.その場合はWindows Terminalを再起動してみよう.

この現象は,配っているポータル環境のVSCodeを使うときに発生するので,特定のプログラムで発生するわけではなさそうです.うちの学生はbasicを試しているときになっていました.


bright_dark_game についても,show_hand_gameのような説明があると良いと思います.

「このプログラムは,ROSが指示する"bright"と"dark"に合わせて,カメラの映像を明るくしたり暗くしたりするゲームです.明るくしたり暗くしたりする方法は,例えば,カメラを照明に向けたり,カメラを手で覆ったりです」

また,判定基準はユーザーの環境によるので,プログラムを読んで自分で調整してみると良いかもしれません.とか書いておくと良いかもしれません.


Exercise (integration 2) Add navigation function between game A and game B. See Robot control 3.

game A と game B をそれぞれ,show_hand_game bright_dark_game に変えればOK


Challenge (integration 3)

確かにチャレンジは次のTeam exerciseに託して良いと思います.

igaki commented 3 years ago

@jinno-oit これどこですかね?

start_on_win_single.py や start_on_ros_single.py などで,「呼び出す処理を追加する」となっていますが,配布するプログラムでは削除しておきますか?

jinno-oit commented 3 years ago

@igaki 以下の二つの箇所で,「***を呼び出す処理を追加してコマンドを実施する」となっていますが,配布しているプログラムでは既にコードが追加されていると思います.

start_on_windows_single.py show_hand_game_win.pyが正常に実行できるかを確認できたら,start_on_windows_single.pyにshow_hand_game_win.pyを呼び出す処理を追加し,下記コマンドを実行してROSとの通信を確認すると良い 現在の仕様では,start_on_windows_single.pyはwhile True:でROSからのメッセージ送信を無限ループで待機するようになっている

start_on_ros_single.py show_hand_game_ros.pyが正常に実行できるかを確認できたら,start_on_ros_single.pyにshow_hand_game_ros.pyを呼び出す処理を追加し,下記コマンドを実行してWindows側プログラム(show_hand_game_win.py)との通信を確認すると良い もし,roslaunch oit_stage_ros navitation.launchを実行していない場合は実行し,別のターミナルでコマンドを実行する

igaki commented 3 years ago

@jinno-oit ナビゲーションプログラム追加しました.ロボットの移動部分を別ファイルにしたんですが,これ,単独で動作するようなmain()追加する書き方ご存じないでしょうか..?

jinno-oit commented 3 years ago

@igaki ありがとうございます.以下で動きました. 現在の move_robot_ros.py には import os が足りないようです.

def demo():
    script_name = os.path.basename(__file__)
    rospy.init_node(os.path.splitext(script_name)[0])
    rospy.sleep(0.5)  # rospy.Time.now() returns 0, without this sleep.

    rospy.loginfo("%s:Started", rospy.get_name())
    process(2.0, 2.5, -90)
    rospy.loginfo("%s:Exiting", rospy.get_name())

if __name__ == '__main__':
    try:
        demo()
    except Exception as e:
        rospy.logerr("%s:%s", rospy.get_name(), str(e))
        exit(1)
igaki commented 3 years ago

@jinno-oit ありがとうございます.コード修正してコミットしておきます.

jinno-oit commented 3 years ago

とりあえず,ざっと担当分を英訳しました.

Objectives

Let's Make multiple image processing programs on windows and a ROS node which can communicate with each other via TCP/IP.

This page explains how to communicate between many image processing programs on Windows and the ROS node.

Prerequisite

You have to finish all of robots, image processing, and Message exchange between a Windows program and a ROS node

Practice1(Single image processing program and a ros node)

Make a Windows side python program

show_hand_game_win.py

python show_hand_game_win.py

start_on_windows_single.py

python start_on_windows_single.py
    while True:
        messages = ros_bridge_tcp.wait() #Wait for message from ROS and assign the response into 'messages'
        for message in messages:
            # If message['msg']['data'] is "[shg]start show hand game", then shg.star_game is invoked
            if message['msg']['data'] == "[shg]start show hand game":
                shg.start_game(topic_name_from_win, ros_bridge_tcp)
            if message['msg']['data'] == "The end":
                pub_msg = {
                    "op": "publish",
                    "topic": topic_name_from_win,
                    "msg": {"data": "Every game has finished!"}
                }
                print("Every game has finished!")
                # Send message "Every game has finished!" to ros.
                ros_bridge_tcp.wait_response(pub_msg, ["Every game has finished"], timeout=5)
                break
        else:
            continue
        break

Make a ROS node

show_hand_game_ros.py

def play_show_hand_game():
    rospy.sleep(3)
    node_name = rospy.get_name()
    # Prepare to play show hand game
    # Specify topic names to commnicate with show hand game
    to_win_pub = rospy.Publisher("/from_ros", String, queue_size=1)
    messenger = RosWinMessenger(to_win_pub, "/from_windows")
    # Start game sequence
    rospy.loginfo("%s:Try to start show hand game", node_name)

    # Send game start signal to Windows, and wait Windows side response.
    message_from_win = messenger.wait_response(
        "[shg]start show hand game", ["[shg]OK_start"], timeout=30)
    if message_from_win:
        rospy.loginfo("%s:Receive from win:%s",
                          node_name, message_from_win)
    else:
        rospy.logerr("%s:Timeout. can't start show hand game on windows", node_name)
        return "[shg]timeout"

    # Select robot's hand_type
    hand_types = ["[shg]left", "[shg]right"]
    hand_type = random.choice(hand_types)
    rospy.loginfo("%s:Robot selects '%s'", node_name, hand_type)

    # Send hand_type chosen by robot to windows show hand game, and wait game result
    message_from_win = messenger.wait_response(
        hand_type, ["[shg]correct", "[shg]wrong"], timeout=30)
    if message_from_win:
        rospy.loginfo("%s:Receive from win:%s",
                    node_name, message_from_win)
    else:
        rospy.logerr(
            "%s:Timeout. can't get show hand game result on windows", node_name)
        return "[shg]timeout"
    rospy.sleep(3)
    return message_from_win

start_on_ros_single.py

def process():
    rospy.sleep(10)
    node_name = rospy.get_name()

    print("---shg---")
    result = shgr.play_show_hand_game()
    rospy.sleep(5)
    end_game()
    rospy.loginfo("/* GAME:%s */", result)
igaki commented 3 years ago

@jinno-oit ありがとうございます! Markdownファイルお願いしますーm(__)m

jinno-oit commented 3 years ago

なるほど,ここだとRawで見られないのですね.SlackのDMに投げておきます.m( )m

KMiyawaki commented 3 years ago

@igaki @jinno-oit https://github.com/oit-ipbl/Integration/blob/singletopic2/win_multi/win/start_on_windows_single.py#L39 で、Win側からはEvery game has finished!を送信し、ROSからのメッセージEvery game has finishedを待つ、というようにビックリマークの有無がありますが、使い分けている、ということですか? あと、StartとFinishのシグナルはもう少し簡単に(一単語に)してもよさそうな気がします。

igaki commented 3 years ago

@KMiyawaki finishedメッセージは統一しようと思います. それと,ご指摘の,シグナルを簡単にしたほうが良いという主旨はなんでしょう? @jinno-oit 先生と相談したときにはOKとかだけだと,他のゲーム等のメッセージと重複するかもという懸念があったので[shg]といったprefixをつけることにしました.で,長さを短くすること自体は問題ないのですが,開始・終了が明確に分かるほうが良いのかなという意図で今のメッセージにしています.

KMiyawaki commented 3 years ago

@igaki 先生、 @jinno-oit 先生、シグナルを簡単にするのは単に間違いを防ぐためです。受信先識別のマークは当然必要だと思います。スペースありの文章よりは一単語の方がよさそうだと思いましたが、どちらでも結構です。

igaki commented 3 years ago

@KMiyawaki 長かったりスペースがあったりするとコーディング時に入力ミスが発生するのではということですね.確かにそのとおりのような気もしてきました(実際!のありなし間違えてましたし).ちょっと考えてみます. @jinno-oit