LoginSignup
13
9

More than 5 years have passed since last update.

[rospy] ctrl-cで綺麗に終わるようにする

Last updated at Posted at 2018-11-14

ワーニングメッセージ

ROSのノードをctrl-cで終了させた時、そのノードと通信している他のノードで次のようなメッセージが出ることがあった。

[WARN] [1542224645.663897]: Inbound TCP/IP connection failed: connection from sender terminated before handshake header received. 0 bytes were received. Please check sender for additional details.

これはPythonでノードを動かしている場合、ctrl-cが裏で動いているスレッドを途中で止めてしまう事に原因があるように思われる。下記のプログラムテンプレートでは省略しているがsubscribeでコールバックがある場合もその処理は別スレッドなので同様の問題が発生する。
これを解決するにはctrl-cの処理をrospyにまかせずに自前で綺麗に書けば良い。

プログラムテンプレート

the_node.py
#!/usr/bin/env python

import signal
import rospy

cont = True

def handler(signal, frame):
    global cont
    cont = False

def the_node():
    global cont

    rospy.init_node('the_node', disable_signals = True)

    rate = rospy.Rate(40)
    while cont:
        ~~~
        rate.sleep()

    rospy.signal_shutdown('finish')
    rospy.spin()

if __name__ == '__main__':
    signal.signal(signal.SIGINT, handler)
    the_node()
  • 開始時: init_nodeでdisable_signals = Trueとしてrospyにctrl-cの処理をさせないようにする。
  • 終了時: signal_shutdownでrospyにshutdownを司令してspinでshutdownするまで待つ。
  • 全般: contはグローバル変数で別スレッドからもちゃんと読めるように各defでglobal contと宣言する必要がある。

シリアル通信

特にシリアル通信をしている場合、ROSをctrl-cでshutdownさせると通信途中で処理が中断してしまう確率が高い。そんなケースでもこの方法は有効だ。シリアル通信している部分を

try:
    sp.write(~)
    sp.flush()
except KeyboardInterrupt:
    cont = False

みたいにし、rospy.signal_shutdown('finish')の前に

sp.close()

すれば綺麗にシリアルポートを終了でき、次にちゃんとopenできる。

13
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
9