Help us understand the problem. What is going on with this article?

roslaunchのコードAPIを使う part2

More than 1 year has passed since last update.

Day9の記事を受けて。
https://qiita.com/Nasupl_r/items/a1449cf192c57f03ffa5

「Q. roslaunchをPythonから叩きたいやつおるか?w」

A. ここにおるでw

場面によっては使えるツールだと思います

例えばテキトーにwrapして…

import roslaunch
import os

class SimpleRosLaunch(object):
    def __init__(self, ):
        self.launchfile = ""
        self.reinitialize()

    def __del__(self,):
        self.stop()

    def load_file(self, launchfile):
        if self.is_alive():
            raise RuntimeError("you need to stop before you load another launch file")
        self.launchfile = os.path.abspath(os.path.expanduser(launchfile))
        self.launch.parent.config = roslaunch.config.load_config_default([self.launchfile], None)

    def start(self,):
        local_machine = roslaunch.core.local_machine()
        for n in self.launch.parent.config.nodes:
            n.machine = local_machine
        self.launch.start()

    def is_alive(self,):
        if self.launch.parent.pm is not None and self.launch.parent.pm.is_alive() and len(self.launch.parent.pm.get_active_names())>0:
            return True
        return False

    def current_file(self, ):
        return self.launchfile

    def reinitialize(self, ):
        self.launch = roslaunch.scriptapi.ROSLaunch()

    def stop(self,):
        self.launch.stop()
        self.reinitialize()
        self.load_file(self.launchfile)

こうしてやると…

import os
import roslaunch
import rospkg
from simple_roslaunch import SimpleRosLaunch

# 初期化
simple_roslaunch = SimpleRosLaunch()
# signalをいい感じに処理する
roslaunch.pmon._sig_initialized = True
rospy.on_shutdown(simple_roslaunch.stop)
launchfile = os.path.join(rospkg.RosPack().get_path('sample_pkg'), 'launch', 'sample.launch')

simple_roslaunch.load_file(launchfile)


# スタート
if simple_roslaunch.is_alive():
    rospy.logerr("you've already executed launch file")
    return False
simple_roslaunch.start()
return True

# ストップ
if not simple_roslaunch.is_alive():
    rospy.logerr("no launch file is launched")
    return False
simple_roslaunch.stop()

起動したり止めたりできます

なにが嬉しいかというと、
例えばOccupancyGrid(/map)を保存したい時に、

<launch>
    <node pkg="map_server" type="map_saver" name="map_saver">
    </node>
</launch>

のようなlaunch fileを準備しておき、

from map_msgs.msg import SaveMap

def run_map_saver(self, req):
    global simple_roslaunch
    try:
        for n in simple_roslaunch.launch.parent.config.nodes:
            if (n.package == "map_server" and n.type == "map_saver"):
                # <node>のargsが変更できる
                n.args = unicode('-f %s'%(req.filename.data, ))
        # rosparamも変更できる
        # simple_roslaunch.launch.parent.config.params['/hoge/fuga/piyo'].value = '...'
        simple_roslaunch.start()
        while not rospy.is_shutdown():
            rospy.loginfo("saving map...")
            if not simple_roslaunch.is_alive():
                rospy.loginfo("saving map done!")
                break
            rospy.sleep(0.2)
        simple_launch.stop()
    except Exception as e:
        rospy.logerr(e)

sample_service = rospy.Service('~sample_service', SaveMap, run_map_saver)

このようにlaunch fileに定義された引数などを動的に変更できます
mapに何か後処理を加えて保存したい場合もlaunch fileに後処理ノードを加えて、<remap>でmap_saverとtopicを繋げばよい、ということになります

当然ながらlaunch fileをわざわざ準備する必要もなくて

launch = roslaunch.scriptapi.ROSLaunch()
node = roslaunch.core.Node('map_server', 'map_saver')
node.args = unicode('-f %s'%(req.filename.data, ))
# namespaceも変更できる
# node.namespace = '/hogefuga'
launch.start()
launch.launch(node)
while not rospy.is_shutdown():
    rospy.loginfo("saving map...")
    if len(launch.parent.pm.get_active_names()) == 0:
        rospy.loginfo("saving map done!")
        break
    rospy.sleep(0.2)
launch.stop()
del launch

その場でプロセスが起動できちゃう!プロセス管理はroslaunchにお任せ!(?)

まとめ

roslaunch APIは very unstableです
なるべく使わないようにしましょう

ompugao
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした