ROS_INFO_STREAMでなぜか出力されない問題

by NigoroJr 0 Comments

とりあえず,以下のコードを見ていただきたい.

#include <ros/ros.h>

void get_params() {
    ros::NodeHandle np{"~"};
    float f;
    np.param("foobar", f, 4.2f);

    ROS_INFO_STREAM("exitting get_params with foobar == " << f);
}

int
main(int argc, char* argv[]) {
    ros::init(argc, argv, "sample_node");

    ROS_INFO_STREAM("before calling get_params");
    get_params();
    ROS_INFO_STREAM("after calling get_params");

    ros::spin();

    return 0;
}

一見なんら問題ないこのコードだが,実行するとおかしいことが起こる.

問題

コードを実行すると,出力が以下のようになる:

[ INFO] [/sample_node] [1536863298.820675562]: before calling get_params
[ INFO] [/sample_node] [1536863298.825877817]: exitting get_params with foobar == 42.42

最後の after calling get_params が出力されていない.

解決策

get_params に参照を投げるようにする.つまり,

#include <ros/ros.h>

void get_params(const ros::NodeHandle& np) {
    float f;
    np.param("foobar", f, 4.2f);

    ROS_INFO_STREAM("exitting get_params with foobar == " << f);
}

int
main(int argc, char* argv[]) {
    ros::init(argc, argv, "sample_node");

    auto np = ros::NodeHandle{"~"};
    ROS_INFO_STREAM("before calling get_params");
    get_params(np);
    ROS_INFO_STREAM("after calling get_params");

    ros::spin();

    return 0;
}

出力は以下のようになる:

[ INFO] [/sample_node] [1536863710.670982067]: before calling get_params
[ INFO] [/sample_node] [1536863710.672086878]: exitting get_params with foobar == 42.42
[ INFO] [/sample_node] [1536863710.672117960]: after calling get_params

なぜ起こるか?

正直,謎です.分かる方がいたら教えてください.おそらく ros::NodeHandle 内の参照カウンタ的なものの影響のような気がする.

No PyCharm completion for rospy

Premises

I have a version of ros_comm cloned from GitHub.

  • Ubuntu 16.04
  • ROS Lunar

Problem

In PyCharm Professional 2018.1.1, no completion for rospy was shown. The message said:

Cannot find reference 'init_node' in '__init__.py'

Screenshot of the error message

TL;DR

If $( rospack find rospy )/src exists, add it to PYTHONPATH.

Cause of the Problem

After sourcing setup.bash (and friends), PYTHONPATH points to /path/to/workspace/devel/lib/python2.7/dist-packages. Doing import rospy in the Python script uses the following __init__.py:

# -*- coding: utf-8 -*-
# generated from catkin/cmake/template/__init__.py.in
# keep symbol table as clean as possible by deleting all unnecessary symbols

from os import path as os_path
from sys import path as sys_path

from pkgutil import extend_path

__extended_path = "/home/naoki/ros/workspaces/lunar/hsas/src/ros_comm/clients/rospy/src".split(";")
for p in reversed(__extended_path):
    sys_path.insert(0, p)
    del p
del sys_path

__path__ = extend_path(__path__, __name__)
del extend_path

__execfiles = []
for p in __extended_path:
    src_init_file = os_path.join(p, __name__ + '.py')
    if os_path.isfile(src_init_file):
        __execfiles.append(src_init_file)
    else:
        src_init_file = os_path.join(p, __name__, '__init__.py')
        if os_path.isfile(src_init_file):
            __execfiles.append(src_init_file)
    del src_init_file
    del p
del os_path
del __extended_path

for __execfile in __execfiles:
    with open(__execfile, 'r') as __fh:
        exec(__fh.read())
    del __fh
    del __execfile
del __execfiles

The problem is that PyCharm expects __all__ to be populated in order for the completion to function correctly. That is done in /path/to/workspace/src/ros_comm/clients/rospy/src/rospy/__init__.py (i.e. $( rospack find rospy )/src/rospy).

Solution

Add $( rospack find rospy )/src to the front of PYTHONPATH if it exists. For rospy that’s installed with APT, there’s no src subdirectory (i.e. rospack find rospy gives you /opt/ros/DISTRO/share/rospy in which there is no src subdirectory).

if [[ -d $( rospack find rospy )/src ]]; then
    export PYTHONPATH="$( rospack find rospy )/src:$PYTHONPATH"
fi

After that if you start up PyCharm it should give you completion for rospy.

boost::asio::serial_port::read_someでEnd Of File Exceptionが出る際の対処法

boost::asio::serial_portread_some を使って
シリアルポートから読んだ際に,一瞬にしてEOF Exceptionが
投げられました.デバイスファイルのパスもボーレートも権限も
正しいはずなのになんでだろう??と思って調べたのでメモ.

what():  read_some: End of file

解決法1

stackoverflow.com/questions/45896414/boost-asio-serial-port-end-of-file

$ stty -F /dev/ttyUSB0 raw

解決法2

read_some の第2引数に boost::system::error_code を与えてやる.

auto port = boost::asio::serial_port{};
port.open("/dev/ttyUSB0");
port.set_option(boost::asio::serial_port_base::baud_rate(115200));
auto dest_ptr = get_dest_ptr();
auto dest_size = get_dest_size();
auto err_code = boost::system::error_code{};
port.read_some(boost::asio::buffer(&dest_ptr, dest_size), err_code);

ros_controlでControllerがロードできないときのためのメモ

ハマってめちゃくちゃ時間を無駄にして悔しかったので,メモ.

ロボットを定義するURDFのほうで,

<gazebo>
  <plugin name="gazebo_ros_control" filename="libgazebo_ros_control.so">
    <robotNamespace>/hogehoge</robotNamespace>
  </plugin>
</gazebo>

としたとします.

ネームスペースに関して注意しないといけないことが二つ:

YAMLをロードするときのネームスペースに注意

/hogehoge/my_hoge_controller/type: position_controllers... のように,ロボット名のネームスペースに入れないといけません.

YAMLで言うと,

hogehoge:
  my_hoge_controller:
    type: position_controllers/JointTrajectoryController
    # (省略)

としないといけません.

controller_manager を起動する際のネームスペースに注意

<node ns="hogehoge" name="my_hoge_controller_spawner" pkg="controller_manager" type="controller_manager" args="spawn my_hoge_controller" />

のように,ノードを hogehoge (ロボット名)ネームスペースで起動しないといけません.これに気付かずにハマりました…

個別に指定するよりも,

<group ns="hogehoge" >
  <rosparam command="load" file="YAMLへのパス" />
  <node name="my_hoge_controller_spawner" pkg="controller_manager" ... />
</group>

というふうに <group> に入れるのがいいかもしれませんね.

Ubuntu 16.04にfswatchを入れる

ファイルシステムの変更をモニタするのに便利なfswatch
macOSでは使っていたのですが,Ubuntuには入れていなかったなぁ
と思って入れてみたのでメモをしておきます.

PPAを使う

launchpad.net/~hadret/+archive/ubuntu/fswatch

$ sudo add-apt-repository ppa:hadret/fswatch
$ sudo apt-get update
$ sudo apt-get install fswatch

以上.

自分でコンパイルする

自前でコンパイルしたい場合は以下の依存関係をインストールしてやる
必要があります.

  • inotify-tools
  • automake
  • autopoint
  • texinfo

これらを入れれば何の問題もなく make install できるんですが,
私の環境では入っていなかったのでメモ.

Ubuntu 18.04なら

何もせずとも apt-get install fswatch で入るらしいです(未確認).

github.com/emcrisostomo/fswatch/issues/170

ROSのパッケージの開発をするときのTips

by NigoroJr 0 Comments

覚え書き.

launchファイルで一発起動できるようにする

書いて時間がたったときに,起動手順を覚えていない場合が多い.

開発時からパラメータ指定できるようにする

フレーム名とか特に,開発途中の段階ではハードコードしたくなるが,後からパラメータ化しようとしてもどこをどう変えればいいかがすぐに分からず,億劫になってパラメータ化せず,結局必要になったときにめんどくさいことになる.

StaticTransformBroadcasterで複数のTransformをbroadcastする

by NigoroJr 0 Comments

以前にもハマったことがある記憶があるので,メモ.

TF2にはStaticTransformBroadcasterというクラスがあり,TF2で追加された /tf_static というstatic transformをブロードキャストすることができます.使い方はこんな感じ:

import tf2_ros
from geometry_msgs.msg import TransformStamped

tf_sb = tf2_ros.StaticTransformBroadcaster()
tform = TransformStamped()
tform.header.frame_id = 'hoge'
# いろいろやる
tf_sb.sendTransform(tform)

ただ,一つのノードで複数のTransformをブロードキャストすると, rostopic echo /tf_static で最後の変換しか表示されません.

tf_sb.sendTransform(transform1)
tf_sb.sendTransform(transform2)
tf_sb.sendTransform(transform3)
# transform3しか使えない

どうやらStaticTransformBroadcasterは一つのTransformしか保持することができないらしいです.複数のTransformをブロードキャストしたいときは,まとめて送りましょう.

tforms = [transform1, transform2, transform3]
tf_sb.sendTransform(tforms)

ちなみにタプルを使うと Inbound TCP/IP connection failed: 'tuple' object has no attribute 'header' というエラーが出てダメな模様.リストを使いましょう.

複数クラスでStatic Transformを作るときは,結構めんどくさいです.TransformStampedを返すようにする等しないといけないみたいですね.

Ubuntu 16.04でBluetoothをONにできない際の対処法

by NigoroJr 0 Comments

何回か起こったので,メモ.

症状

unity-control-center の BluetoothでスライダをONにし,一旦メニューに戻ってからまたBluetoothに戻るとOFFになっている.つまり,BluetoothをONにできない.

Ubuntu 16.04で起こるっぽい?二つのマシンで同じ症状が確認された.以前はこのようなことはなかったのでアップデートした際に起こるようになってしまった模様.

環境

  • Ubuntu 16.04 (4.10.0-42-generic)
  • bluez 5.37-0ubuntu5.1

エラーメッセージ

$ sudo systemctl restart bluetooth.service
Job for bluetooth.service failed because the control process exited with error code. See "systemctl status bluetooth.service" and "journalctl -xe" for details.

というわけで,提案通り systemctl status bluetooth.servicejournalctl -xe の出力を見ましょう. journalctl -xe の出力は次の通り:

Feb 05 08:41:26 kyosen systemd[1]: Starting Bluetooth service...
-- Subject: Unit bluetooth.service has begun start-up
-- Defined-By: systemd
-- Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
--
-- Unit bluetooth.service has begun starting up.
Feb 05 08:41:26 kyosen systemd[12050]: bluetooth.service: Failed at step EXEC spawning /usr/lib/bluetooth/bluetoothd: Permission denied
-- Subject: Process /usr/lib/bluetooth/bluetoothd could not be executed
-- Defined-By: systemd
-- Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
--
-- The process /usr/lib/bluetooth/bluetoothd could not be executed and failed.
--
-- The error number returned by this process is 13.
Feb 05 08:41:26 kyosen systemd[1]: bluetooth.service: Main process exited, code=exited, status=203/EXEC
Feb 05 08:41:26 kyosen systemd[1]: Failed to start Bluetooth service.
-- Subject: Unit bluetooth.service has failed
-- Defined-By: systemd
-- Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
--
-- Unit bluetooth.service has failed.
--
-- The result is failed.

Failed at step EXEC spawning /usr/lib/bluetooth/bluetoothd: Permission denied とありますね.

$ ls -l /usr/lib/bluetooth/bluetoothd
-rw-r--r-- 1 root root 1.1M Sep 12 11:04 /usr/lib/bluetooth/bluetoothd

あっ……

$ sudo chmod 755 /usr/lib/bluetooth/bluetoothd

で無事に sudo systemctl start bluetooth.service できるようになりました.

なぜこうなったかは謎.

Using TF2 on with Python 3

by NigoroJr 0 Comments

ROS1 officially supports Python 2, but there are many official libraries that are written with compatibility for Python 3. TF2 is one of them, and it may be a good idea to start using Python 3 for simple applications that make use of TF2.

What’s Required

My Environment

  • Ubuntu 16.04
  • ROS Kinetic
  • Python 2.7.12 (system)
  • Python 3.5.2 (system)
  • Python 3.6.4 (installed with pyenv)

Steps

Note: You may want to create a different catkin workspace for this. Otherwise, you’ll probably need to recompile all the packages that depend on TF2 libraries.

  1. Install pyenv following the instructions in the URL above
  2. CONFIGURE_OPTS=--enable-shared pyenv install <version> to install the latest Python 3 with the shared libraries
  3. Download geometry2 and put it in your catkin workspace
  4. Go into your catkin workspace and run pyenv local <python version you installed>
  5. Run pyenv rehash and make sure python --version displays the right version
  6. Install dependencies with: pip install catkin_pkg pyyaml empy rospkg numpy
  7. Run catkin_make -DPYTHON_EXECUTABLE=$( pyenv prefix )/bin/python3 -DPYTHON_LIBRARY=$( pyenv prefix )/lib/libpython3.so -DPYTHON_VERSION=3
  8. In a Python 3 console, run import tf2_ros.

If you get the following error when running catkin_make, make sure that the executables you’re pointing to exists, and that they’re the right version.

When I forgot to specify -DPYTHON_EXECUTABLE so cmake couldn’t find the right Python interpreter,

CMake Error at /usr/share/cmake-3.5/Modules/FindPackageHandleStandardArgs.cmake:148 (message):
  Could NOT find PythonInterp: Found unsuitable version "2.7.12", but
  required is at least "3" (found /usr/bin/python)
Call Stack (most recent call first):
  /usr/share/cmake-3.5/Modules/FindPackageHandleStandardArgs.cmake:386 (_FPHSA_FAILURE_MESSAGE)
  /usr/share/cmake-3.5/Modules/FindPythonInterp.cmake:163 (FIND_PACKAGE_HANDLE_STANDARD_ARGS)
  /opt/ros/kinetic/share/catkin/cmake/python.cmake:8 (find_package)
  /opt/ros/kinetic/share/catkin/cmake/all.cmake:147 (include)
  /opt/ros/kinetic/share/catkin/cmake/catkinConfig.cmake:20 (include)
  CMakeLists.txt:52 (find_package)

I got this while compiling rviz because I didn’t specify -DPYTHON_LIBRARY.

CMake Error at /usr/share/cmake-3.5/Modules/FindPackageHandleStandardArgs.cmake:148 (message):
  Could NOT find PythonLibs: Found unsuitable version "2.7.12", but required
  is at least "3.6" (found
  /home/naoki/.pyenv/versions/3.6.4/lib/libpython3.so)

If you get the following error in the Python console, suspect that you’re not using the right Python version:

>>> import tf2_ros
Cannot load geometry_msgs moduleTraceback (most recent call last):
  File "<frozen importlib._bootstrap>", line 969, in _find_and_load
  File "<frozen importlib._bootstrap>", line 958, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 673, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 665, in exec_module
  File "<frozen importlib._bootstrap>", line 222, in _call_with_frames_removed
  File "/opt/ros/kinetic/lib/python2.7/dist-packages/rospy/__init__.py", line 49, in <module>
    from .client import spin, myargv, init_node, \
  File "/opt/ros/kinetic/lib/python2.7/dist-packages/rospy/client.py", line 52, in <module>
    import roslib
  File "/opt/ros/kinetic/lib/python2.7/dist-packages/roslib/__init__.py", line 50, in <module>
    from roslib.launcher import load_manifest
  File "/opt/ros/kinetic/lib/python2.7/dist-packages/roslib/launcher.py", line 42, in <module>
    import rospkg
ImportError: No module named 'rospkg'

Result

Python 3.6.4 (default, Jan 21 2018, 19:20:10)
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import rospy
>>> import tf2_ros
>>> from geometry_msgs.msg import TransformStamped
>>> rospy.init_node('sample')
>>> static_tf = TransformStamped()
>>> tf_sb = tf2_ros.StaticTransformBroadcaster()
>>> static_tf.header.stamp = rospy.Time.now()
>>> static_tf.header.frame_id = 'base_link'
>>> static_tf.child_frame_id = 'laser'
>>> static_tf.transform.rotation.w = 1.0
>>> tf_sb.sendTransform(static_tf)
>>>

And that’s how you use TF with Python 3!

References

mbedでLチカができるようになった話

組み込みのHello World的存在である,LEDをチカチカさせるプログラム,所謂Lチカを正常に動かすことができるようになった話です.

LPC1768とgcc4mbedを使っています.

テスト用に以下のLチカプログラムを書きました.
これ以上簡単なプログラムはないというぐらいです.

#include "mbed.h"

DigitalOut myled(LED1);

int
main() {
    while (1) {
        myled = 1;
        wait(0.1);
        myled = 0;
        wait(0.1);
    }
}

gcc4mbedをインストールして, make deploy を走らせると……

チカチカの間隔が長い!!

0.1秒ではなく,1秒間隔になります.

0.1のところを変えても,やはり指定した秒数の10倍の間隔になります.

原因

mbed OS 5用のバイナリだと,こうなるみたいです.もともとLPC1768はmbed 2用のバイナリじゃないといけないらしく,それ用にしたらうまくいきました.

2017-10-21追記: ファームウェアをアップデートし,mbed OS 5にすることでも解決しました.RTOSが使えるようになって便利になりました.下記の解決方法より,ファームアップデートのほうがおすすめです.

解決方法

gcc4mbedの設定用環境変数 MBED_OS_ENABLE を変更する.

export MBED_OS_ENABLE=0

使うデバイスのスペックをちゃんと知っておかないと,こういうことが起こるんですね.