jsk_common

jsk_common is common stacks used in JSK lab.

The code is open source, and available on github.

Contents:

Tips & FAQ

Speed-up compilation by ccache

You can use ccache to speed-up compilation.

sudo apt-get install ccache
sudo ln -sf /usr/bin/ccache /usr/local/bin/gcc
sudo ln -sf /usr/bin/ccache /usr/local/bin/cc
sudo ln -sf /usr/bin/ccache /usr/local/bin/g++
sudo ln -sf /usr/bin/ccache /usr/local/bin/c++
ccache -M 10G

And all of your compilation should be done by ccache.

ROS Packages:

jsk_data

A stack for data management tools which are used in JSK lab.

data_collection_server.py

What is this?

Save topics with synchronization by std_srvs/Trigger message as {SAVE_DIR}/{TIMESTAMP}/{FILENAME}.

Parameters

  • ~save_dir (String, Default: ~/.ros)

    Save directory.

  • topics (Required)

    This param should look like below:

topics:
  - name: /camera/rgb/image_raw
    msg_class: sensor_msgs/Image
    fname: image.png
    savetype: ColorImage
  - name: /camera/depth/image_raw
    msg_class: sensor_msgs/Image
    fname: depth.pkl
    savetype: DepthImage

Currently, the supported save type is:

  • ColorImage
  • DepthImage
  • LabelImage
  • YAML
  • params (Optional)

    This param should look like below:

params:
  - key: /in_hand_data_collection_main/object
    fname: label.txt
    savetype: Text

Currently, the supported save type is:

  • Text
  • YAML
  • method (String, Default: request)

    • request: Save data when service is called.
    • timer: Save data when start service is called. Finish collecting when end service is called.
    • all: Always save data.
  • message_filters: (Bool, Default: False)

    Subscribe topics with message_filters.

  • approximate_sync: (Bool, Default: False)

    Subscribe topic with ApproximateTimeSynchronizer in message_filters.

  • queue_size: (Int, Default: 10)

    Queue size of message_filters.

  • slop: (Float, Default 0.1)

    Slop of ApproximateTimeSynchronizer in message_filters.

  • timestamp_save_dir: (Bool, Default: True)

    Save data in timestamped dir.

    If you set this as False, data will be saved as {SAVE_DIR}/{FILENAME}.

Services

  • ~save_request (std_srvs/Trigger)

    Save data when method is request.

  • ~start_request (std_srvs/Trigger)

    Start saving data when method is timer.

  • ~end_request (std_srvs/Trigger)

    Finish saving data when method is timer.

jsk_data command

jsk_data is command line interface to rename, upload and download data, and this is fully designed for JSK lab members. (this command communicates with internal server in lab)

There are following sub commands. See jsk_data [sub command] --help for more detail.

  • ls: List data on the server.

    Usage is jsk_data ls [OPTIONS] [QUERY].

  • get: Download data from the server.

    Usage is jsk_data put [OPTIONS] FILENAME.

  • put: Upload data to the server.

    Usage is jsk_data put [OPTIONS] FILENAME. With --public option, it also uploads to public Google Drive folder, so please care about it when you handle secure data.

  • delete: Delete file on the server.

    Usage is jsk_data delete FILENAME. It only supports with --public option. If you want to delete private data, delete it manually by logging in aries via ssh.

  • pubinfo: Show public data info.

    Usage is jsk_data pubinfo [OPTIONS] FILENAME. Downloading large file with wget or curl from Google Drive can be failed. (see here) Please run sudo pip install gdown and use it at that time. (Usage: gdown [URL] -O [FILENAME])

  • pubopen: Open Google Drive Folder where public data is uploaded

    Usage is jsk_data pubopen.

Screencast

rosbag_always.py

rosbag_always.py can record bag files even if roscore is restarted. It also removes old bag files if recorded bag files exceed specified size.

$ rosrun jsk_data rosbag_always.py -h
usage: rosbag_always.py [-h] --topics TOPICS --size SIZE --save-dir SAVE_DIR
                        --max-size MAX_SIZE

rosbag record regardless of rosmaster status

optional arguments:
  -h, --help           show this help message and exit
  --topics TOPICS      topics to record
  --size SIZE          size of each rosbag
  --save-dir SAVE_DIR  directory to store rosbag
  --max-size MAX_SIZE  maximum size of rosbags in save_dir

jsk_tools

This package includes several useful tools and library for ROS software.

test_stdout.py

What is this?

This node is to test the expected stdout of shell command while running rostest.

Parameters

  • ~command (str)

    The command to run.

  • ~shell (bool)

    Run the command with shell mode or not. See here for more detail.

  • ~stdout (str)

    Expected stdout.

  • ~stdout_line%d (str)

    Expected stdout of the specific line.

Example

<test test-name="test_stdout"
      pkg="jsk_tools" type="test_stdout.py">
  <param name="command" value="timeout 10 rostopic echo /label_image_decomposer/output/header/frame_id -n1 || true" />
  <param name="stdout_line0" value="camera" />
  <param name="shell" value="true" />
</test>

test_topic_published.py

What is this?

This node is to test the expected published topics while running rostest.

Parameters

  • ~topic_%d (str)

    The name of topics to test if published.

  • ~timeout_%d (int)

    Timeout for the topic.

  • ~negative_%d (bool, Default: false, Optional)

    If it’s True, it tests if not published.

  • ~import (List[str], Default: [], Optional)

    List of Python modules to import and use in ~condition_%d expression. For commodity rospy and numpy modules are imported by default.

  • ~condition_%d (str, Default: None, Optional)

    Check bool value condition using the given Python expression. The Python expression can access any of the Python builtins plus: topic (the topic of the message), m (the message) and t (time of message).

    For example, topic is std_msgs/String and if you want to check whether a sentence is a hello, you can do the following.

    condition_0: m.data == 'hello'
    

    If you want to check the frame id of the header, you can do the following.

    condition_0: m.header.frame_id in ['base', 'base_link']
    

    Note that, use escape sequence when using the following symbols <(&lt;), >(&gt;), &(&amp;), '(&apos;) and "(&quot;).

    condition_0: m.data &lt; 'spbm'
    

    The modules given to ~import can also be used.

    condition_0: 'numpy.linalg.norm([m.wrench.force.x, m.wrench.force.y, m.wrench.force.z]) &lt; 10.0'
    

Example

<test test-name="image_view2_topics"
      name="image_view2_topics"
      pkg="jsk_tools" type="test_topic_published.py">
  <rosparam>
    topic_0: /camera_0/image/screenrectangle_image
    timeout_0: 10
    topic_1: /camera_1/image/screenrectangle_image
    timeout_1: 10
  </rosparam>
</test>

bag_plotter.py

bag_plotter is a script to plot from a bag file directly.

usage: bag_plotter.py [-h] [--duration DURATION] [--start-time START_TIME]
                      config bag

Plot from bag file

positional arguments:
  config                yaml file to configure plot
  bag                   bag file to plot

optional arguments:
  -h, --help            show this help message and exit
  --duration DURATION, -d DURATION
                        Duration to plot
  --start-time START_TIME, -s START_TIME
                        Start timestamp to plot

Format of yaml file is like:

global:
  layout: <vertical, horizontal or manual, optional and defaults to vertical>
plots:
  - title:  <title of plot, required>
    topic:  <list of topics, required>
    field:  <list of accessor to get value to plot, required>
    layout: <2-d layout. if global/layout is manual, this field is required>
    legend: <show legend or not, optional and defaults to true>

the length of topic and field should be same. You can use “array format” in field.

  • a/b/c[0] means the 1st element of array a/b/c.
  • a/b/c[0:3] means 1st, 2nd and 4rd elements of array a/b/c.

Example is like:

global:
  layout: vertical
plots:
  - title: "rleg temp"
    topic: [/motor_states]
    field: ["driver_temp[0:6]"]
  - title: "lleg temp"
    topic: [/motor_states]
    field: ["driver_temp[6:12]"]
  - title: "leg force (z)"
    topic: [/off_lfsensor, /off_rfsensor]
    field: [wrench/force/z, wrench/force/z,]

When you want to use manual layout, example should be like follows:

global:
  layout: manual
plots:
  - title: "rleg temp"
    topic: [/motor_states]
    field: ["driver_temp[0:6]"]
    layout: [0, 0]
  - title: "lleg temp"
    topic: [/motor_states]
    field: ["driver_temp[6:12]"]
    layout: [0, 1]
  - title: "chest temp"
    topic: [/motor_states]
    field: ["driver_temp[12:15]"]
    layout: [1, 0]
  - title: "head temp"
    topic: [/motor_states]
    field: ["driver_temp[15:17]"]
    layout: [1, 1]

config_switch

Seamlessly switch user configuration with dotfiles and shell.

Currently supports below dotfiles:

  • .bashrc
  • .zshrc
  • .vimrc
  • .vim
  • .gitconfig

Usage

$ gh_user=wkentaro
$ vim ~/.zshrc.$gh_user
$ vim ~/.vimrc.$gh_user

# set user and shell
$ config_switch wkentaro /usr/local/bin/zsh
Switching user: -> wkentaro
Linked .bashrc -> .bashrc.wkentaro
WARNING: .zshrc is not symlink, so skipping
Logging in as 'wkentaro' with '/usr/local/bin/zsh'

$ ls -la ~/.vimrc
~/.vimrc -> ~/.vimrc.wkentaro

$ cat ~/.ros/jsk_tools/current_config
wkentaro
/usr/local/bin/zsh

$ config_switch
Current user: wkentaro
Current shell: /usr/local/bin/zsh

restart_travis

Restart a travis job for specified github repository. Firstly, add below in your .bashrc:

# you can get SLACK_TOKEN at https://api.slack.com/web.
export SLACK_TOKEN=xoxp-XXXXXXXX-XXXXXXXX-XXXXXXXX

To restart travis, need the repository slug (ex: jsk-ros-pkg/jsk_common) and job id (ex: 2019.6):

$ restart_travis jsk-ros-pkg/jsk_common 2019.6  # usage: restart_travis <repo_slug> <job_id>
sending... 'restart travis jsk-ros-pkg/jsk_common 2019.6' -> #travis

rosbag_record_interactive

You can choose topics to record in GUI and record them into a bag file

roscore_regardless.py

This script always checks roscore liveness and automatically run and kill a program.

rosrun jsk_tools roscore_regardless.py rostopic echo /foo

Usage

$ rosrun jsk_tools roscore_regardless.py -h
usage: roscore_regardless.py [-h] [--respawn] [--timeout TIMEOUT]
                             [--ping-trials PING_TRIALS]
                             [--sigint-timeout SIGINT_TIMEOUT]
                             [--sigterm-timeout SIGTERM_TIMEOUT]
                             ...

positional arguments:
  commands

optional arguments:
  -h, --help            show this help message and exit
  --respawn, -r         respawn if child process stops
  --timeout TIMEOUT     Timeout to verify if rosmaster is alive by ping
                        command in seconds
  --ping-trials PING_TRIALS
                        If ping fails PING-TRIALS times, master is regarded as
                        dead
  --sigint-timeout SIGINT_TIMEOUT
                        Timeout to escalete from sigint to sigterm to kill
                        child processes
  --sigterm-timeout SIGTERM_TIMEOUT
                        Timeout to escalete from sigterm to sigkill to kill
                        child processes

rostopic_host_sanity

_images/rostopic_host_sanity.png

What is this?

Check the network connection between the local PC and each hosts which are inside the ROS topic graph.

In above example image, 111.111.111.111 is non-existent IP, and it detects the disconnected status.

Usage

rosrun jsk_tools rostopic_host_sanity

rosview

Usage

$ rosview jsk_tools CMakeLists.txt
cmake_minimum_required(VERSION 2.8.3)
project(jsk_tools)
...

This is short version of:

export PAGER=less
roscat jsk_tools CMakeLists | $PAGER

Setup environmental variables for ROS

You can use commands below after source /opt/ros/$DISTRO/setup.bash.

rossetip

Setup your ROS_IP and ROS_HOSTNAME.

$ rossetip
set ROS_IP and ROS_HOSTNAME to 192.168.11.1
$ echo $ROS_IP, $ROS_HOSTNAME
192.168.11.1, 192.168.11.1

rossetlocal

Setup your ROS_MASTER_URI to localhost.

$ rossetlocal
set ROS_MASTER_URI to http://localhost:11311
$ echo $ROS_MASTER_URI
http://localhost:11311

rossetmaster

Setup your ROS_MASTER_URI to robot’s hostname.

# rossetmaster ${hostname} ${ros_port}
# default: hostname=pr1040, ros_port=11311
user@host $ rossetmaster
set ROS_MASTER_URI to http://pr1040:11311
[http://pr1040:11311] user@host $ echo $ROS_MASTER_URI
http://pr1040:11311

rosdefault

Setup ROS_MASTER_URI with default hostname written in ~/.rosdefault.

$ cat ~/.rosdefault
pr1040
$ rosdefault
set ROS_MASTER_URI to http://pr1040:11311

It is recommended to run rosdefault in your .bashrc or .zshrc.

rossetdefault

Setup your default hostname. After running this command, you can setup ROS_MASTER_URI with default hostname by rosdefault. (default hostname will be stored at ~/.rosdefault)

# rossetdefault ${hostname}
# default: hostname=local
$ rossetdefault baxter
set ROS_MASTER_URI to http://baxter:11311
$ bash
$ rosdefault
set ROS_MASTER_URI to http://baxter:11311

topic_delay_monitor.py

This script is mostly same as topic_hz_monitor.py but it computes the time lag from sensor input using timestamp in the header.

Example

rosrun jsk_tools topic_delay_monitor.py /euclidean_segmentation/output --search-parent
rosrun jsk_tools topic_delay_monitor.py /euclidean_segmentation/output /camera/rgb/points

topic_hz_monitor.py

This script is used to find bottleneck of topic nodes flow. You can specify one topic and use --search-parent option to collect topics automatically. (Note Subscribing too many topics makes it difficult to get correct result.)

Example

rosrun jsk_tools topic_hz_monitor.py /euclidean_segmentation/output --search-parent
rosrun jsk_tools topic_hz_monitor.py /euclidean_segmentation/output /camera/rgb/points

sanity_lib.py

check Topic is published

  • If you set echo param as True, the topic message will be shown in terminal

Example

from jsk_tools.sanity_lib import *
from std_msgs.msg import String
rospy.init_node("check_sanity", anonymous = True)
checkTopicIsPublished("/chatter", String)

check Node State

There is 4 cases

  • Node exists, and you want to exist.
  • Node exists, and you don’t want to exist
  • Node doesn’t exist and you want to exist
  • Node doesn’t exist and you don’t want to exist

The second parameter is Needed Parameter.

Example

from jsk_tools.sanity_lib import *
rospy.init_node("check_sanity", anonymous = True)
checkNodeState("/listener", True)

check Params

Example

from jsk_tools.sanity_lib import *
rospy.init_node("check_sanity", anonymous = True)
checkROSParam("/param_test", 5)

sanity_diagnostics.py

What is this

This node publishes essential robot topic and node status to /diagnostics.

Publishing Topics

  • /diagnostics (diagnostic_msgs/DiagnosticStatus)

    Diagnostics topic

Subscribing Topics

  • topics specified in the ~sanity_targets yaml file

Parameter

  • ~sanity_targets (String, default: /var/lib/robot/sanity_targets.yaml)

    Yaml file which contains topics and nodes to be monitored.

    Sample yaml format for fetch:

    topics:
      - /audio
      - /base_scan
      - /battery_state
      - /edgetpu_human_pose_estimator/output/image
      - /edgetpu_object_detector/output/image
      - /gripper/imu
      - /head_camera/depth/image_raw
      - /head_camera/rgb/image_raw
      - /imu
      - /insta360/image_raw
      - /joint_states
      - /tf
    
    nodes:
      - /amcl
      - /auto_dock
      - /gripper_driver
      - /head_camera/head_camera_nodelet_manager
      - /move_base
      - /move_group
      - /respeaker_node
      - /robot_driver
      - /roswww
    
  • ~duration (Float, default: 60)

    Duration in which sanity is checked.

  • ~pub_duration (Float, default: 0.3)

    Duration in which /diagnostics is published.

Usage

Visualize topic and node diagnostics.

roslaunch jsk_tools sample_sanity_diagnostics.launch

sanity_diagnostics

emacs

We strongly recommend to use dot.emacs for common user.

(load "~/ros/hydro/src/jsk-ros-pkg/jsk_common/jsk_tools/dot-files/dot.emacs")

inferior-lisp-mode

inferior-lisp-mode is a classic lisp environment on emacs. You can invoke roseus by C-c e.

When you use inferior-lisp-mode, you can immediately evaluate sexpression without copy-and-paste it by C-x C-e.

tmux

Write following line in your ~/.tmux.conf

source-file ~/ros/hydro/src/jsk-ros-pkg/jsk_common/jsk_tools/dot-files/tmux.conf

jsk_topic_tools

This package includes several useful library for ROS software.

constant_rate_throttle_nodelet

images/lightweight_throttle_nodelet_diagram.svg

Description

This nodelet provides function like lightweight_throttle_nodelet, but support accurate publish rate.

The rate of throttled message is configurable by passing ~update rate parameter on launching this nodelet.

Subscribing Topic

  • ~input (AnyMsg):

    Input topic. This topic is throttled to low publish rate.

Publishing Topic

  • ~output (AnyMsg):

    Throttled topic. Publish rate of throttled topic is configurable by setting ~update_rate parameter. If ~update_rate is higher than input topic rate, published message is used from buffer.

Parameter

  • ~update_rate (Double, default: 1.0):

    Publish rate of throttled message [Hz]. This parameter is updated only on launching this nodelet.

lightweight_throttle_nodelet

images/lightweight_throttle_nodelet_diagram.svg

Description

This nodelet provides function like rosrun topic_tools throttle messages, but subscribes high rate topic only when throttled topic is subscribed by more than equal one subscriber.

The rate of throttled message is configurable by passing ~update rate parameter on launching this nodelet.

Subscribing Topic

  • ~input (AnyMsg):

    Input topic. This topic is throttled to low publish rate.

Publishing Topic

  • ~output (AnyMsg):

    Throttled topic. Publish rate of throttled topic is configurable by setting ~update_rate parameter.

Parameter

  • ~update_rate (Double, default: 1.0):

    Publish rate of throttled message [Hz]. This parameter is updated only on launching this nodelet.

Passthrough

jsk_topic_tools/Passthrough is a node/nodelet to relay topics only for specified duration. You can use the service call to turn relay on and off. By default, the topic relay is turned off.

Subscribing Topics

  • ~input (AnyMsg)

    Incoming topic to be relayed

Publishing Topics

  • ~output (AnyMsg, same type as ~input)

    Outgoing topic to publish on

Services

  • ~request (std_srvs/Empty)

    Start topic relay

  • ~stop (std_srvs/Empty)

    Stop topic relay

  • ~request_duration (jsk_topic_tools/PassthroughDuration)

    Perform topic relay for a specified duration. Duration 0 means infinite relay.

Parameters

  • ~default_duration (double, default: 10.0)

    Duration [s] to relay the topic. Duration 0 means infinite relay.

Usage

# Terminal 1
$ roslaunch jsk_topic_tools passthrough_sample.launch

# Terminal 2
$ rostopic pub /passthrough_sample/input std_msgs/String "data: 'hello'" -r10

# Terminal 3
$ rostopic echo /passthrough_sample/input

# Terminal 4
$ rostopic echo /passthrough_sample/output

# Terminal 5
$ rosservice call /passthrough_sample/request
$ rosservice call /passthrough_sample/stop

Relay

jsk_topic_tools/Relay is a node/nodelet that subscribes to ~input topic and republishes all incoming data to ~output topic like topic_tools/Relay but has several additional features such as latch and lazy mode.

Subscribing Topics

  • ~input (AnyMsg)

    Incoming topic to be relayed

Publishing Topics

  • ~output (AnyMsg, same type as ~input)

    Outgoing topic to publish on

Parameters

  • ~always_subscribe (bool, default: false)

    If true, it turns off its lazy mode, where the input topic is subscribed only when the output topic is subscribed.

  • ~latch (bool, default: false)

    If true, it publishes the output topic in latch mode.

standalone_complexed_nodelet

Why needed?

nodelet is a good framework to decrease overhead of network communication between ROS nodes.

roscpp has a feature to communicate topics by passing reference pointers if publisher and subscriber are in the same process. By taking advantage of this feature, nodelet can communicate without network overhead each other.

However, nodelet has a problem in system architecture of server-client model. server is a manager and all the actual computation run in this process. client just sends a request to manager to load some classes in the manager process by dynamic loading.

The issue occurs in bond between server and client. If server is killded, client should be killed as well. If a client is killed, the class which is requested by the client loaded in server process should be unloded. nodelet implements this functionality by bond package. server publishes heatbeat topic in fixed rate and client subscribes the topic. If client detects stoll of the topic, client regards manager is dead and kill itself and request unloading to the manager.

This mechanism works well if nodelet system is relatively small but if we run a lot of nodelet, it does not work because communication via ROS topics is not reliable and somtimes it has a lot of latency.

This “unreliable bond mechanism” issue occurs a lot and standalone_complexed_nodelet can solve it. standalone_complexed_nodelet is a nodelet manager but it does not require client to send request. standalone_complexed_nodelet knows nodelet classes via ros parameter instead of server-client model. Limitation of standalone_complexed_nodelet is that it does not support dynamic loading/unloading of nodelet classes but we know we do not need the feature from our experiences.

We recommend to use standalone_complexed_nodelet instead of normal nodelet.

APIs

standalone_complexed_nodelet read definition of nodelet classes from ros parameter. The parameter are ~nodelets, ~nodelets_0, ..., ~nodelets_99. You can extend the suffix numbers by ~candidate_num parameter. default is 100. These multiple parameters (~nodelets_0, nodelets_1, ...) are useful to include multiple launch files and run one standalone_complexed_nodelet.

nodelet definition should follow next format:

nodelets:
  - name: <name of nodelet, required>
    type: <type of nodelet, required>
    if: <the defnition is enabled only if this field is true, optional>
    unless: <the defnition is enabled only if this field is false, optional>
    remappings: <field to lead remapping definition, optional>
      - from: <ros name to be remapped>
        to: <ros name to remap to>
      - from:
        to:
        ...
  - name:
    type:
    remappings:
    ...

Examples

StealthRelay

jsk_topic_tools/StealthRelay is a node/nodelet that subscribes to ~input topic and republishes all incoming data to ~output topic like topic_tools/Relay but only if ~monitor_topic topic is subscribed by any other nodes.

When ~input and ~monitor_topic topic name point to the same topic, it looks that this node subscribes ~input topic only when other nodes also subscribes it, which is equivalent to subscribing without incrementing subscription counter. ~monitor_topic can be set by rosparam and is set to ~input by default.

Subscribing Topics

  • ~input (AnyMsg)

    Incoming topic to be relayed

Publishing Topics

  • ~output (AnyMsg, same type as ~input)

    Outgoing topic to publish on

Parameters

  • ~use_multithread_callback (bool, default: True)

    If true, initialize NodeHandle with multi threading.

  • ~queue_size (int, default: 1)

    Queue size for subscription of the incoming topic.

  • ~enable_monitor (bool, default: True)

    If enabled, monitoring feature is enabled, otherwise this nodelet behaves as same as Relay nodelet.

  • ~monitor_topic (string, default: ~input)

    Topic name to monitor.

  • ~monitor_rate (double, default: 1.0)

    Desired monitoring rate of subscribing messages of ~monitor_topic.

SynchronizedThrottle Nodelet

Description

This is a nodelet for throttling like topic_tools/throttle, but throttled topics are synchronized. Unlike topic_tools/throttle, this nodelet accepts parameters to specify input topics and rate for throttling.

Parameters
  • ~topics (String[], required)

    Input topics to be synchronized and throttled.

Warning

This nodelet uses message_filters for message synchronization. message_filters limits a number of input topics to 8 at maximum.

  • ~suffix (string, default: throttled)

    Suffix for advertised throttled topics.

  • ~update_rate (Double, default: 1.0)

    A rate for throttling messages. If this parameter is 0.0, no message is published.

  • ~use_wall_time (Bool, default: false)

    Use wall time for throttling timer if enabled.

  • ~use_multithread_callback (Bool, default: true)

    Use multithreaded node handle if enabled.

  • ~approximate_sync (Bool, default: false)

    Use approximate synchronization policy if enabled, otherwise messages are published only when they are strictly synchronized.

  • queue_size (Int, default: 100)

    Size of subscription queue.

boolean_node.py

What is this?

A node that takes bool values and returns the results of the boolean operation such as or, and, not and xor.

For example, this node can be used to merge the results of a node that outputs whether the robot is speaking in English or Japanese.

Subscribing Topics

Input is prepared for the ~number_of_input. A number suffix is added to the ~input. The suffixes start with 1. If ~number_of_input equals 2, subscribing topic names are ~input1 and ~input2. In the case of not operation, only ~input1 is subscribed.

  • ~input{%d} (AnyMsg)

    input value.

Publishing Topics

  • ~output/or (std_msgs/Bool)

    The result of the or operation.

  • ~output/and (std_msgs/Bool)

    The result of the and operation.

  • ~output/not (std_msgs/Bool)

    The result of the not operation.

  • ~output/xor (std_msgs/Bool)

    The result of the xor operation.

Parameters

  • ~import (List[str], Default: [], Optional)

    List of Python modules to import and use in ~input{%d}_condition expression. For commodity rospy and numpy modules are imported by default.

  • ~input{%d}_condition (String, Default: m.data)

    Returning bool value condition using the given Python expression. The Python expression can access any of the Python builtins plus: topic (the topic of the message), m (the message) and t (time of message).

    For example, ~input1 topic is std_msgs/String and if you want to check whether a sentence is a hello, you can do the following.

    input1_condition: m.data == 'hello'
    

    If you want to check the frame id of the header, you can do the following.

    input1_condition: m.header.frame_id in ['base', 'base_link']
    

    The modules given to ~import can also be used.

    condition_0: 'numpy.linalg.norm([m.wrench.force.x, m.wrench.force.y, m.wrench.force.z]) &lt; 10.0'
    

    Note that this condition is evaluated each time a topic is published. For example, a condition that checks whether a certain topic has arrived within one second look like this.

    input1_condition: "(rospy.Time.now() - t).to_sec() &lt; 1.0"
    

    Use escape sequence when using the following symbols <(&lt;), >(&gt;), &(&amp;), ‘(&apos;) and “(&quot;) in launch file.

  • ~rate (Int, Default: 100)

    Publishing rate [Hz].

  • ~number_of_input (Int, Default: 2)

    Number of input. ~number_of_input should be greater than 0.

Example

$ roslaunch jsk_topic_tools sample_boolean_node.launch

The outputs of a simple Boolean operation are as follows.

$ rostopic echo /robotsound/is_speaking -n1
data: True
---
$ rostopic echo /robotsound_jp/is_speaking -n1
data: False
---
$ rostopic echo /is_speaking -n1  # or
data: True
---
$ rostopic echo /both_are_speaking -n1  # and
data: False
---
$ rostopic echo /either_one_is_speaking -n1  # xor
data: True
---

In sample_boolean_node.launch, there is a description that gives input_condition as follows.

<node name="boolean_node_checking_conditions"
      pkg="jsk_topic_tools" type="boolean_node.py"
      clear_params="true" >
  <remap from="~input1" to="/image1" />
  <remap from="~input2" to="/image2" />
  <remap from="~input3" to="/chatter" />
  <rosparam>
    number_of_input: 3
    input1_condition: "'base' in m.header.frame_id"
    input2_condition: "'base' in m.header.frame_id"
    input3_condition: m.data == 'hello'
  </rosparam>
</node>

The output results when using the condition are as follows.

$ rostopic echo /image1 -n1
header:
  seq: 15029
  stamp:
    secs: 0
    nsecs:         0
  frame_id: "base"
height: 0
width: 0
encoding: ''
is_bigendian: 0
step: 0
data: []
---
$ rostopic echo /image2 -n1
header:
  seq: 32445
  stamp:
    secs: 0
    nsecs:         0
  frame_id: "base_link"
height: 0
width: 0
encoding: ''
is_bigendian: 0
step: 0
data: []
---
$ rostopic echo /chatter -n1
data: "hello"
---
$ rostopic echo /boolean_node_checking_conditions/output/and -n1
data: True
---
$ rostopic echo /boolean_node_checking_conditions/output/not -n1
data: False
---
$ rostopic echo /boolean_node_checking_conditions/output/or -n1
data: True
---
$ rostopic echo /boolean_node_checking_conditions/output/xor -n1
data: True
---

is_synchronized

_images/is_synchronized.png

What is this?

Tool to check if specified topics are ‘synchronized’ or not. ‘synchronized’ means timestamps completely match with ‘Exact’ synchronization policy (default). With ‘Approximate’ policy (with --approximate-sync option), it means the timestamps’ difference falls within ‘slop’ (default 0.1 seconds).

Usage

usage: is_synchronized [-h] [-t TIMEOUT] [-q QUEUE_SIZE] [-a] [--slop SLOP]
                       topics [topics ...]

positional arguments:
  topics                topics which should be synchronized

optional arguments:
  -h, --help            show this help message and exit
  -t TIMEOUT, --timeout TIMEOUT
                        Timeout for the test of synchronization
  -q QUEUE_SIZE, --queue-size QUEUE_SIZE
                        Size of queue for the synchronization
  -a, --approximate-sync
                        Flag to use approximate synchronization
  --slop SLOP           Allowed time delta in approximate synchronization

Example

$ rosrun jsk_topic_tools is_synchronized /mask_image/mask /mask_image/output/camera_info
****************** Test Condition ******************
timeout: 5 seconds
queue_size: 100
topics:
  - /mask_image/mask [sensor_msgs/Image]
  - /mask_image/output/camera_info [sensor_msgs/CameraInfo]
****************************************************
listening these topics for at most 5 seconds in rostime
synchronized in 1.0 seconds
these topics are: 'synchronized'

$ rosrun jsk_topic_tools is_synchronized /mask_image/mask /raw_image_rgb/image_color
****************** Test Condition ******************
timeout: 5 seconds
queue_size: 100
topics:
  - /mask_image/mask [sensor_msgs/Image]
  - /raw_image_rgb/image_color [sensor_msgs/Image]
****************************************************
listening these topics for at most 5 seconds in rostime
timeout for 5 seconds
these topics are: 'not synchronized'

pose_stamped_publisher.py

Publish static geometry_msgs/PoseStamped.

Usage: pose_stamped_publisher.py x y z roll pitch yaw from_frame rate

rostopic_connection_list

Description

Tool to check rostopic connection with different hosts.

Usage

$ rosrun jsk_topic_tools rostopic_connection_list --help
usage: rostopic_connection_list [-h] [--subscriber-host SUBSCRIBER_HOST]
                                [--publisher-host PUBLISHER_HOST]
                                [--publisher-host-sort] [--include-rosout]
                                [--show-nodes]

optional arguments:
  -h, --help            show this help message and exit
  --subscriber-host SUBSCRIBER_HOST, -s SUBSCRIBER_HOST
                        Subscriber hostname: (default: all)
  --publisher-host PUBLISHER_HOST, -p PUBLISHER_HOST
                        Publisher hostname: (default: all)
  --publisher-host-sort
                        Sort by publisher host name or not (default: False)
  --include-rosout      Include /rosout topic or not: (default: False)
  --show-nodes          Show node names or not: (default: False)

Example

Show all connection
$ rosrun jsk_topic_tools rostopic_connection_list
Subscriber host: 133.11.216.168
    133.11.216.211 -> /pr1040/wan0/transmit -> 133.11.216.168
    133.11.216.211 -> /pr1040/wan0/receive -> 133.11.216.168
    133.11.216.211 -> /tf -> 133.11.216.168
    133.11.216.211 -> /joint_states -> 133.11.216.168
    133.11.216.211 -> /tf_static -> 133.11.216.168
    pr1040 -> /tf -> 133.11.216.168
    pr1040s -> /audio -> 133.11.216.168
    pr1040s -> /battery/server2 -> 133.11.216.168
    pr1040s -> /kinect_head/rgb/image_rect_color/compressed -> 133.11.216.168
    pr1040s -> /tf -> 133.11.216.168
Subscriber host: 133.11.216.211
    pr1040 -> /l_arm_controller/follow_joint_trajectory/goal -> 133.11.216.211
    pr1040 -> /l_gripper_sensor_controller/event_detector -> 133.11.216.211
    pr1040 -> /robotsound_jp/cancel -> 133.11.216.211
...
...
(long lines)
Specify subscriber and publisher host name

You can specify subscriber host and publisher host by -s and -p.

$ rosrun jsk_topic_tools rostopic_connection_list -s 133.11.216.168 -p 133.11.216.211
Subscriber host: 133.11.216.168
    133.11.216.211 -> /pr1040/wan0/transmit -> 133.11.216.168
    133.11.216.211 -> /pr1040/wan0/receive -> 133.11.216.168
    133.11.216.211 -> /tf -> 133.11.216.168
    133.11.216.211 -> /joint_states -> 133.11.216.168
    133.11.216.211 -> /tf_static -> 133.11.216.168
Sort by publisher host name

You can sort by publisher host name with --publisher-host-sort.

$ rosrun jsk_topic_tools rostopic_connection_list --publisher-host-sort
Publisher host: 133.11.216.211
    133.11.216.211 -> /pr1040/wan0/transmit -> 133.11.216.168
    133.11.216.211 -> /pr1040/wan0/receive -> 133.11.216.168
    133.11.216.211 -> /tf -> 133.11.216.168
    133.11.216.211 -> /joint_states -> 133.11.216.168
    133.11.216.211 -> /tf_static -> 133.11.216.168
...
...
(long lines)
Show nodes

--show-nodes shows all node names, too.

$ rosrun jsk_topic_tools rostopic_connection_list --show-nodes
Subscriber host: 133.11.216.168
    133.11.216.211 -> /pr1040/wan0/transmit -> 133.11.216.168
        Publisher nodes:
            /network_status
        Subscriber nodes:
            /network_states_logger
    133.11.216.211 -> /pr1040/wan0/receive -> 133.11.216.168
        Publisher nodes:
            /network_status
        Subscriber nodes:
            /network_states_logger
    133.11.216.211 -> /tf -> 133.11.216.168
        Publisher nodes:
            /robot_state_publisher
            /robot_pose_ekf
            /realtime_loop
        Subscriber nodes:
            /base_transform_logger
            /map_transform_logger
...
...
(long lines)

static_tf_republisher.py

What is this?

Node to republish /tf_static from a rosbag file

Usage

` rosrun jsk_topic_tools static_tf_republisher.py _file:=<absolute file path to a rosbag file> `

or

` rosrun jsk_topic_tools static_tf_republisher.py <file path to a rosbag file> `

Sample

` roslaunch jsk_topic_tools sample_static_tf_republisher.launch `

Parameters

  • ~file (String)

    Absolute file path to a rosbag file. Positional argument is prioritized over this parameters.

  • ~mode_static (Bool, default: True)

    If set to True, static transforms in a rosbag file are published to /tf_static. Otherwise, they are published to /tf.

  • ~publish_rate (Float, default: 10)

    Publishing rate of /tf if ~mode_static is set to False.

synchronize_republish.py

What is this?

Node to republish multiple topics with exact/approximate synchronization.

Subscribing Topics

This is assigned by ~topics rosparam.

Publishing Topics

  • ~pub_{0>2}

    {0>2} represents the index of the topic assigned by ~topics rosparam, for example ~pub_00, ~pub_11.

Parameters

  • ~topics (List of string, Required)

    Topics to synchronize.

  • ~approximate_sync (Bool, Default: false)

    If true, approximate synchronization is used for synchoronizing assigned topics.

  • ~queue_size (Integer, Default: 100)

    Queue length for subscribing topics.

  • ~slop (Double, Default: 0.1)

    Allowable misalignment time between the subscribing topics.

tf_to_pose.py

What is this?

Tool to convert /tf to geometry_msgs::PoseStamped.

Subscribing Topics

  • /tf (tf2_msgs/TFMessage)

    Transformation.

Parameters

  • src_frame, dst_frame (String, required)

    Frames to compute transform to get the relative pose.

  • rate (Float, default: 1.)

    Publishing rate [Hz].

Example

rosrun tf static_tf_transform 0 0 1 0 0 0 base_link head_link 100
rosrun jsk_topic_tools tf_to_pose.py _src_frame:=base_link _dst_frame:=head_link
rostopic echo /tf_to_pose/output

tf_to_transform.py

What is this?

Specific TransformStamped publisher. You specify parent_frame_id and child_frame_id, and this node publish geometry_msgs::TransformStamped. You can define –duration (default=0.1).

Difference from tf_to_pose.py

TransformStamped msg carries parent_frame_id and child_frame_id. Otherwise, PoseStamped msg only carries parent_frame_id.

Usage

Command Line
$ rosrun jsk_topic_tools tf_to_transform.py -h
usage: tf_to_transform.py [-h] [--duration DURATION]
                          [parent_frame_id] [child_frame_id]

positional arguments:
  parent_frame_id       parent frame id
  child_frame_id        child frame id

optional arguments:
  -h, --help            show this help message and exit
  --duration DURATION, -d DURATION
                        Duration [s]: default=1.0
Param
  • ~parent_frame_id (String)

    Parent frame id

  • ~child_frame_id (String)

    Child frame id

  • ~duration (Float, default=1.0)

    Duration

Example

$ rosrun jsk_topic_tools transform_publisher.py /base /right_gripper_vacuum_pad_base -d 2.0

$ rostopic echo /transform_publisher/output
header:
  seq: 1
  stamp:
    secs: 1479108976
    nsecs: 799304962
  frame_id: /base
child_frame_id: /right_gripper_vacuum_pad_base
transform:
  translation:
    x: 0.614187621295
    y: -0.70974742075
    z: 0.332638443526
  rotation:
    x: 0.0231768305754
    y: 0.764117456951
    z: -0.0773262537191
    w: 0.640006247621
---
header:
  seq: 2
  stamp:
    secs: 1479108978
    nsecs: 799195051
  frame_id: /base
child_frame_id: /right_gripper_vacuum_pad_base
transform:
  translation:
    x: 0.61417389684
    y: -0.709704671921
    z: 0.332801975644
  rotation:
    x: 0.0237198976862
    y: 0.764003459868
    z: -0.0768511001916
    w: 0.640179653038
---

transform_wrench.py

_images/transform_wrench.jpg

What is this?

Convert WrenchStamped topic with respect to ~target_frame_id.

Subscribing Topics
  • ~input (geometry_msgs/WrenchStamped)

    Input wrench stamped message.

Publishing Topics
  • ~output

    Transformed WrenchStamped topic with respect to ~target_frame_id.

Parameters
  • ~target_frame_id (String, required)

    Reference frame of wrench.

  • ~duration_timeout (Float, default: 0.05)

    Duration of timeout for lookup transform.

Example
roslaunch jsk_topic_tools sample_transform_wrench.launch launch_robot_model:=true gui:=true

ConnectionBasedNodelet (C++)

WARNING

This base-class is being deprecated and replaced by nodelet_topic_tools::NodeletLazy in nodelet_topic_tools.

Description

This class is a base-class which can start subscribing topics if published topics are subscribed by the other node. This is abstruct class.

Note

Each subclass of this class must call onInitPostProcess in the last line onInit.

Parameter

  • ~use_multithread_callback (Bool, default: true):

If true, node use getMTNodeHandle and getMTPrivateNodeHandle for getting NodeHandle. MTNodeHandle generates threads for processing its callback function.

If false, node use getNodeHandle and getPrivateNodeHandle. This is default behavior of normal node (not nodelet).

Please see nodelet

  • ~always_subscribe (Bool, default: false):

    Subscribes topics even if there is no subscribers of advertised topics if true.

  • ~verbose_connection (Bool, default: false):

    Show verbose log message on topic connection

  • ~no_warn_on_init_post_process (Bool, default: false):

    Never warn if onInitPostProcess method is not yet called.

DiagnosticNodelet (C++)

Description

This class is a subclass of ConnectionBasedNodelet. Instances of this class can publish diagnostics messages. This is an abstruct class.

Note

Each subclass of this class is required to call vital_checker_->poke() on all callback functions so that this class can check the health of the functionality of the nodelet.

Publishing Topic

  • ~diagnostics (diagnostic_msgs::DiagnosticArray):

    Diagnostic messages

Parameter

  • ~vital_rate (Double, default: 1.0):

    Rate to determine if the nodelet is in health. If the rate that the callback functions is below this parameter, error messages are displayed on diagnostics.

  • /diagnostic_nodelet/use_warn or ~use_warn (Bool, default: False):

    If this parameter is enabled, diagnostic messages on failure is displayed on WARN level instead of ERROR level. /diagnostic_nodelet/use_warn affects every nodelets that inherits this class, but it still can be overriden for each nodelet by setting ~use_warn parameter.

HzMeasureNodelet (C++)

Description

This node publishes hz of target topic and diagnostics.

User can specify ~warning_hz param.

If target hz is smaller than ~warning_hz, this node outputs diagnostics at WARN level (if ~use_warn is True) or ERROR level.

Subscribing Topic

  • ~input (AnyMsg):

    Target topic.

Publishing Topic

  • ~output (std_msgs::Float32):

    Target topic’s hz.

  • ~diagnostics (diagnostic_msgs::DiagnosticArray):

    Diagnostic messages.

Parameter

  • ~measure_time (Double, default: 1.0):

    Calculate hz from the number of topics received in time in ~measure_time.

  • ~message_num (Int, default: -1):

    Calculate hz from the arrival times of ~message_num topics. Note that if this value is less than 0 or not set, ~measure_time will be used.

  • ~warning_hz (Double, default: -1):

    If target hz is smaller than ~warning_hz, this node outputs diagnostics at WARN level (if ~use_warn is True) or ERROR level.

  • ~use_warn (Bool, default: False):

    If this parameter is enabled, diagnostic messages on failure is displayed on WARN level instead of ERROR level.

ConnectionBasedTransport (Python)

Description

This class is a base-class which can start subscribing topics if published topics are subscribed by the other node. This is abstruct class.

Users inherit this class and define publisher by calling the self.advertise function. The return value of self.advertise is the Publisher class. User should execute publish in callback function.

For Expert

When publish is executed, it is judged that this node is running normally, and published diagnostics becomes OK level. However, if the publisher is subscribed but the publish function is not called, the node is not working properly and diagnostics will be at the ERROR level.

Some users may executepublish at any time (eg rospy.Timer). In that case, by executing the self.poke function in the callback function, the state of diagnostics will be OK level without executing publish.

Parameter

  • ~always_subscribe (Bool, default: false):

    Subscribes topics even if there is no subscribers of advertised topics if true.

  • ~enable_vital_check (Bool, default: true):

    If this value is true, /diagnostics will be published and the status of whether the topic has been published will be output from this node.

  • ~vital_rate (Double, default: 1.0):

    Rate to determine if the nodelet is in health. If the rate that the callback functions is below this parameter, error messages are displayed on diagnostics. This value is valid only if ~enable_vital_check is true.

  • /diagnostic_nodelet/use_warn or ~use_warn (Bool, default: False):

    If this parameter is enabled, diagnostic messages on failure is displayed on WARN level instead of ERROR level. /diagnostic_nodelet/use_warn affects every nodelets that inherits this class, but it still can be overriden for each nodelet by setting ~use_warn parameter.

Publishing Topic

  • /diagnostics (diagnostic_msgs.DiagnosticArray):

    Diagnostic messages. Required if ~enable_vital_check:=true

How does it behaves?

# terminal 1:
$ roslaunch jsk_topic_tools test_connection_based_transport.test

# terminal 2:
$ rostopic echo /simple_image_transport/output

# terminal 3:
$ rostopic info /simple_image_transport/output
Type: sensor_msgs/Image

Publishers:
 * /simple_image_transport (http://133.11.216.160:42481/)

Subscribers:
* /rostopic_137980_1496651422064 (http://133.11.216.160:38414/)

# terminal 2:
$ ^C  # cancel

# terminal 3:
$ rostopic info /simple_image_transport/output
Type: sensor_msgs/Image

Publishers:
 * /simple_image_transport (http://133.11.216.160:42481/)

Subscribers: None

How to use it?

See jsk_topic_tool/sample/simple_image_transport.py to how to use it.

import rospy

from sensor_msgs.msg import Image

from jsk_topic_tools import ConnectionBasedTransport


class SimpleImageTransport(ConnectionBasedTransport):
    def __init__(self):
        super(SimpleImageTransport, self).__init__()
        self._pub = self.advertise('~output', Image, queue_size=1)

    def subscribe(self):
        self.sub_img = rospy.Subscriber('~input', Image, self._process)

    def unsubscribe(self):
        self.sub_img.unregister()

    def _process(self, img_msg):
        self._pub.publish(img_msg)


if __name__ == '__main__':
    rospy.init_node('sample_image_transport')
    img_trans = SimpleImageTransport()
    rospy.spin()

Checking the node status by diagnostics

You can check diagnostics by setting ~enable_vital_check to true.

# terminal 1:
$ roslaunch jsk_topic_tools sample_connection_based_transport.launch

# terminal 2:
$ rostopic list
/diagnostics
/diagnostics_agg
/diagnostics_toplevel_state
/input
/input_dummy
/input_image
/mux/selected
/rosout
/rosout_agg
/simple_image_transport/output

# terminal 3:
$ rosrun rqt_robot_monitor rqt_robot_monitor

There is no one to subscribe to /simple_image_transport/output, so diagnostics is OK.

# terminal 4:
rostopic echo /simple_image_transport/output

If you subscribe to /simple_image_transport/output, it will change to the diagnostics message /simple_image_transport is running.

# terminal 5:
rosservice call /mux/select input_dummy

When changing input for simple_image_transport by mux, the error message will change to /simple_image_transport is not running.

You can check if the node is running correctly like these.

C++ API documentation

Please see rosdoc To generate documentation locally:

$ rosdoc_lite `rospack find jsk_topic_tools` -o doc

jsk_network_tools

This ROS package includes JSK network tools.

network_status.py

Publish network status

$ rostopic list
/ecublens/docker0/receive
/ecublens/docker0/receive_kbps
/ecublens/docker0/receive_mbps
/ecublens/docker0/transmit
/ecublens/docker0/transmit_kbps
/ecublens/docker0/transmit_mbps
/ecublens/eno1/receive
/ecublens/eno1/receive_kbps
/ecublens/eno1/receive_mbps
/ecublens/eno1/transmit
/ecublens/eno1/transmit_kbps
/ecublens/eno1/transmit_mbps
/ecublens/eno2/receive
/ecublens/eno2/receive_kbps
/ecublens/eno2/receive_mbps
/ecublens/eno2/transmit
/ecublens/eno2/transmit_kbps
/ecublens/eno2/transmit_mbps
/ecublens/lo/receive
/ecublens/lo/receive_kbps
/ecublens/lo/receive_mbps
/ecublens/lo/transmit
/ecublens/lo/transmit_kbps
/ecublens/lo/transmit_mbps
/ecublens/nonlocal/receive
/ecublens/nonlocal/receive_kbps
/ecublens/nonlocal/receive_mbps
/ecublens/nonlocal/transmit
/ecublens/nonlocal/transmit_kbps
/ecublens/nonlocal/transmit_mbps

Publishing Topics

  • /<host name>/<interface name>/receive

    Amount of receiving data by the interface in bps

  • /<host name>/<interface name>/receive_kbps

    Amount of receiving data by the interface in Kbps

  • /<host name>/<interface name>/receive_mbps

    Amount of receiving data by the interface in Mbps

  • /<host name>/<interface name>/transmit

    Amount of transmitting data by the interface in bps

  • /<host name>/<interface name>/transmit_kbps

    Amount of transmitting data by the interface in Kbps

  • /<host name>/<interface name>/transmit_mbps

    Amount of transmitting data by the interface in Mbps

  • /<host name>/nonlocal/receive

    Amount of receiving data by the non-local interfaces in bps

  • /<host name>/nonlocal/receive_kbps

    Amount of receiving data by the non-local interfaces in Kbps

  • /<host name>/nonlocal/receive_mbps

    Amount of receiving data by the non-local interfaces in Mbps

  • /<host name>/nonlocal/transmit

    Amount of transmitting data by the non-local interfaces in bps

  • /<host name>/nonlocal/transmit_kbps

    Amount of transmitting data by the non-local interfaces in Kbps

  • /<host name>/nonlocal/transmit_mbps

    Amount of transmitting data by the non-local interfaces in Mbps

Parameters

  • ~hz (float, default: 10)

    Publish frequency

  • ~skip_interfaces (List of string, default: None)

    List of skipping interface names

Usage

rosrun jsk_network_tools network_status.py