Ubuntu16.04にROS kineticインストールとD435iでSLAMのサンプル動作まで

自分の作業メモです
 

リアルセンスのドライバアップデート

書き込みexeをダウンロードするために下記リンクに行き、左枠にあるダウンロードをクリック
Download Windows* Device Firmware Update Tool for Intel® RealSense™ D400 Product Family
次にファームウェアの最新をダウンロードしてくる
Downloads for Intel® RealSense™ Depth Camera D435i

1, D435iを接続する
2, ダウンロードした両方のファイルを解凍し、同じフォルダに入れる
3, intel-realsense-dfu.exeを起動
4, [2][Enter]を押して現在の接続されたカメラとFWバージョンを確認(4だとすべてのカメラを確認できる)
5, [1][Enter]を押して書き込みモードにする
6, 再度[1]を押す
7, 相対パスの[.\Signed_Image_UVC_5_12_3_0.bin]を記入(適宜バージョン書き換え)
8, 書き込みが終わると何かキーを押せと言われるので何か押す
9, [2][Enter]を押して現在の接続されたカメラとFWバージョンを確認(4だとすべてのカメラを確認できる)
バージョンが書き換わったことを確認して終わり
 

リアルセンスインストール

自分のカーネルバージョンを確認する

 2020/4/29現在
  Ubuntu LTSカーネル4.4、4.8、4.10、4.13、4.15、4.18 * 5.0 *および5.3 *をサポートしています。

uname -r

 サポート対象かを確認する
 

パッケージのインストール

 サーバーの公開鍵を登録

sudo apt-key adv --keyserver keys.gnupg.net --recv-key F6E65AC044F831AC80A06380C8B3A55A6F3EFCDE || sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-key F6E65AC044F831AC80A06380C8B3A55A6F3EFCDE
リストに追加
sudo add-apt-repository "deb http://realsense-hw-public.s3.amazonaws.com/Debian/apt-repo xenial main" -u

 もし「AppStream cache update completed, but some metadata was ignored due to errors.」が出たら
 ここを参考にする
 Ubuntu 16.04 LTSの“AppStream cache update completed, but some metadata was ignored due to errors.”を直す : りんご便り

ライブラリンストール
sudo apt-get install librealsense2-dkms=1.3.1-0ubuntu3
sudo apt install librealsense2-utils

 

ROS kineticインストール

(一応上から入れていけばリアルセンスが動作することを確認してますが、本当はリアルセンスのライブラリを最初に入れないといけないかも?) 

まずsources.listを設定

 sudo sh -c 'echo "deb http://packages.ros.org/ros/ubuntu $(lsb_release -sc) main" > /etc/apt/sources.list.d/ros-latest.list' 

つぎにキー設定

sudo apt-key adv --keyserver 'hkp://keyserver.ubuntu.com:80' --recv-key C1CF6E31E6BADE8868B172B4F42ED6FBAB17C654

アップデートして最新に

sudo apt-get update

とりあえずrosのパッケージがインストール可能か見てみる

apt-cache search ros-kinetic

デスクトップフルインストール:(推奨):
 (ROS、rqt、rviz、ロボット汎用ライブラリ、2D / 3Dシミュレータ、ナビゲーション、2D / 3D知覚)

sudo apt-get install ros-kinetic-desktop-full

fullじゃなくてもいいならこちら
(デスクトップインストール: ROS、rqt、rviz、およびロボット汎用ライブラリ
 sudo apt-get install ros-kinetic-desktop

ROS初期化

sudo rosdep init
rosdep update

環境設定

echo "source /opt/ros/kinetic/setup.bash" >> ~/.bashrc
source ~/.bashrc

パッケージをビルドするための依存関係

sudo apt install python-rosdep python-rosinstall python-rosinstall-generator python-wstool build-essential
roscore

で実行できたらok

リアルセンスでSLAMする準備

sudo apt-get install ros-kinetic-realsense2-camera

imu_filter_madgwick:

sudo apt install ros-kinetic-imu-filter-madgwick

rtabmap_ros:

sudo apt install ros-kinetic-rtabmap-ros

robot_localization:

sudo apt install ros-kinetic-robot-localization

D435iを接続して起動確認

roslaunch realsense2_camera opensource_tracking.launch

画面が起動して表示開始するか確認




「参考」
SLAM with D435i · IntelRealSense/realsense-ros Wiki · GitHub

GitHub - IntelRealSense/realsense-ros: Intel(R) RealSense(TM) ROS Wrapper for D400 series, SR300 Camera and T265 Tracking Module

pythonで起動させたスレッドを殺す

pythonでサブプロセスから起動させた子を停止させて殺します。
色々調べた結果、呼んだ時のIDを指定して止めることにしました。

環境

Ubuntu 16.04
python 3.5.2

プログラム

[thread_test.py]

# -*- coding:utf8 -*-
import  time
import subprocess
from subprocess import Popen
import os
import signal

cmd = "python thread_test_child.py"
proc = subprocess.Popen("exec " + cmd, stdout=subprocess.PIPE, shell=True)
print( "process id = %s" % proc.pid )
print(proc.stdout.readline())
os.killpg(os.getpgid(proc.pid), signal.SIGTERM)

呼び出す子プロセス

[thread_test_child.py]

print("====")

↓結果↓

process id = 22818
b'====\n'
Terminated

終わり

raspberrypi3のbluetoothライブラリを最新にする

(2019/3/1時点での記事です)
ラスベリーパイ3でbluetoothの通信をしている時にちょっと不具合等が起きたので、最新のライブラリに更新しました。
使っているのはblueZになります。

環境

Raspberrypi3B raspbian 4.14.79-v7+
 

ライブラリダウンロード

ここから最新ver.確認してダウンロード
www.bluez.org

(2019/3/1時点での最新は5.50)

解凍からインストールまで

tar xvf bluez-5.50.tar.xz
cd bluez-5.50
sudo apt update
sudo apt install -y libusb-dev libdbus-1-dev libglib2.0-dev libudev-dev libical-dev libreadline-dev
./configure --prefix=/usr --mandir=/usr/share/man --sysconfdir=/etc --localstatedir=/var --enable-experimental --enable-midi 
make
sudo make install
sudo reboot
sudo cp /usr/libexec/bluetooth/bluetoothd /usr/lib/bluetooth
 
bluetoothctl -v
bluetoothd --version

下2つのコマンドを打つと5.50のバージョンが出てくると思います。

終わり

pythonでスレッドを再起動させる

pythonでマルチスレッドを使っている時にスレッドがエラーで停止したときに再起動させて復活させる。

環境

python 3.5.2

プログラム

 サブスレッドで÷0をして意図的にエラーをして、それをメインが監視して落ちていたら再起動
 ここでは監視としてメインとスレッドの時間を比較して監視する

import threading, time

global_lock = threading.Lock()   # LOCK OBJECT
global_time = 0
            
class sub_while(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)

    def run(self):
        global global_time
        time_cnt=0
        
        while True:
            global_lock.acquire()
            time_cnt = time_cnt+1
            global_time = int(time.time())
            global_lock.release()
            
            print("sub_thread:",int(time.time()))
            
            if(time_cnt >= 5):
                #error
                val = 100/0
            time.sleep(1)
    
if __name__ == "__main__": 
    global global_time
    
    thread1 = sub_while()
    thread1.start()

    #再起動閾値時間
    threshold_time =5
    while True:
        print("main_time:",int(time.time()))
        print("diff_time:",int(time.time()) - global_time)

        global_lock.acquire()
        #スレッド監視
        if(int(time.time()) - global_time > threshold_time):
            print("-- thread restart --")
            thread1 = sub_while()
            thread1.start()
        global_lock.release()

        time.sleep(1)        

結果

sub_thread: 1543545253
main_time: 1543545253
diff_time: 0
main_time: 1543545254
sub_thread: 1543545254
diff_time: 0
main_time: 1543545255
sub_thread: 1543545255
diff_time: 0
main_time: 1543545256
sub_thread: 1543545256
diff_time: 0
main_time: 1543545257
diff_time: 0
sub_thread: 1543545257
Exception in thread Thread-1:
Traceback (most recent call last):
  File "/usr/lib/python3.5/threading.py", line 914, in _bootstrap_inner
    self.run()
  File "threadtest2.py", line 27, in run
    val = 100/0
ZeroDivisionError: division by zero

main_time: 1543545258
diff_time: 1
main_time: 1543545259
diff_time: 2
main_time: 1543545260
diff_time: 3
main_time: 1543545261
diff_time: 4
main_time: 1543545262
diff_time: 5
main_time: 1543545263
diff_time: 6
-- thread restart --
sub_thread: 1543545263
main_time: 1543545264
diff_time: 0
sub_thread: 1543545264
main_time: 1543545265
diff_time: 1
sub_thread: 1543545265
main_time: 1543545266
diff_time: 1
sub_thread: 1543545266
main_time: 1543545267
diff_time: 1
sub_thread: 1543545267
Exception in thread Thread-2:
Traceback (most recent call last):
  File "/usr/lib/python3.5/threading.py", line 914, in _bootstrap_inner
    self.run()
  File "threadtest2.py", line 27, in run
    val = 100/0
ZeroDivisionError: division by zero

main_time: 1543545268
diff_time: 1
main_time: 1543545269
diff_time: 2

 
以上。

ubuntuでpythonのbluetooth開発環境を構築3

bluepyでプログラムを作っていましたがDelegateやNotificationの部分できちんと動作しなかったところがあるので、またライブラリを変更します

今回使ったのはこちら
github.com

環境

ubuntu16.04
python2.7

RaspberryPi3 B+ でも確認
(Linux raspberrypi.local 4.14.71-v7+ #1145 SMP Fri Sep 21 15:38:35 BST 2018 armv7l GNU/Linux)(STRETCH)

pythonは2系で動かします

Adafruit_Python_BluefruitLEインストール

sudo apt-get update
sudo apt-get -y install libusb-dev libdbus-1-dev libglib2.0-dev libudev-dev libical-dev libreadline-dev
git clone https://github.com/adafruit/Adafruit_Python_BluefruitLE
cd Adafruit_Python_BluefruitLE/
sudo python2 setup.py install

ここまでは公式通りにインストール
しかし、ここからbluez-5.33を公式通りにインストールしたらエラーが出たため5.37を入れます

cd ~
wget http://www.kernel.org/pub/linux/bluetooth/bluez-5.37.tar.xz
tar xvf bluez-5.37.tar.xz
cd bluez-5.37
./configure
make
sudo make install
sudo systemctl start bluetooth
sudo systemctl enable bluetooth

lowEnergy有効化

sudo nano /lib/systemd/system/bluetooth.service
9行目を
ExecStart=/usr/local/libexec/bluetooth/bluetoothd  
から
ExecStart=/usr/local/libexec/bluetooth/bluetoothd    --experimental  
に修正
sudo systemctl daemon-reload
sudo systemctl restart bluetooth

そしたらサンプルプログラムを動かします。
手持ちが前回同様blenano2なのでそれを使いました。
(プログラムはこちら
blenano2は電源入れておいて、
examples/low_level.pyを編集します

# Example of low level interaction with a BLE UART device that has an RX and TX
# characteristic for receiving and sending data.  This doesn't use any service
# implementation and instead just manipulates the services and characteristics
# on a device.  See the uart_service.py example for a simpler UART service
# example that uses a high level service implementation.
# Author: Tony DiCola
import logging
import time
import uuid
import struct
import binascii
import Adafruit_BluefruitLE


# Enable debug output.
#logging.basicConfig(level=logging.DEBUG)

# Define service and characteristic UUIDs used by the UART service.
UART_SERVICE_UUID = uuid.UUID('713d0000-503e-4c75-ba94-3148f18d941e')
#TX_CHAR_UUID      = uuid.UUID('6E400002-B5A3-F393-E0A9-E50E24DCCA9E')
RX_CHAR_UUID      = uuid.UUID('713d0001-503e-4c75-ba94-3148f18d941e')

# Get the BLE provider for the current platform.
ble = Adafruit_BluefruitLE.get_provider()


# Main function implements the program logic so it can run in a background
# thread.  Most platforms require the main thread to handle GUI events and other
# asyncronous events like BLE actions.  All of the threading logic is taken care
# of automatically though and you just need to provide a main function that uses
# the BLE provider.
def main():
    # Clear any cached data because both bluez and CoreBluetooth have issues with
    # caching data and it going stale.
    ble.clear_cached_data()

    # Get the first available BLE network adapter and make sure it's powered on.
    adapter = ble.get_default_adapter()
    adapter.power_on()
    print('Using adapter: {0}'.format(adapter.name))

    # Disconnect any currently connected UART devices.  Good for cleaning up and
    # starting from a fresh state.
    print('Disconnecting any connected UART devices...')
    ble.disconnect_devices([UART_SERVICE_UUID])

    # Scan for UART devices.
    print('Searching for UART device...')
    try:
        adapter.start_scan()
        # Search for the first UART device found (will time out after 60 seconds
        # but you can specify an optional timeout_sec parameter to change it).
        device = ble.find_device(service_uuids=[UART_SERVICE_UUID])
        if device is None:
            raise RuntimeError('Failed to find UART device!')
    finally:
        # Make sure scanning is stopped before exiting.
        adapter.stop_scan()

    print('Connecting to device...')
    device.connect()  # Will time out after 60 seconds, specify timeout_sec parameter
                      # to change the timeout.

    # Once connected do everything else in a try/finally to make sure the device
    # is disconnected when done.
    try:
        # Wait for service discovery to complete for at least the specified
        # service and characteristic UUID lists.  Will time out after 60 seconds
        # (specify timeout_sec parameter to override).
        print('Discovering services...')
        device.discover([UART_SERVICE_UUID], [ RX_CHAR_UUID])#TX_CHAR_UUID

        # Find the UART service and its characteristics.
        uart = device.find_service(UART_SERVICE_UUID)
        rx = uart.find_characteristic(RX_CHAR_UUID)
        #tx = uart.find_characteristic(TX_CHAR_UUID)

        # Write a string to the TX characteristic.
        #print('Sending message to device...')
        #tx.write_value('Hello world!\r\n')

        # Function to receive RX characteristic changes.  Note that this will
        # be called on a different thread so be careful to make sure state that
        # the function changes is thread safe.  Use queue or other thread-safe
        # primitives to send data to other threads.
        def received(data):
            #print('Received: {0}'.format((data)))
            print(binascii.b2a_hex(data))

        # Turn on notification of RX characteristics using the callback above.
        print('Subscribing to RX characteristic changes...')
        rx.start_notify(received)

        # Now just wait for 30 seconds to receive data.
        print('Waiting 60 seconds to receive data from the device...')
        time.sleep(60)
    finally:
        # Make sure device is disconnected on exit.
        device.disconnect()


# Initialize the BLE system.  MUST be called before other BLE calls!
ble.initialize()

# Start the mainloop to process BLE events, and run the provided function in
# a background thread.  When the provided main function stops running, returns
# an integer status code, or throws an error the program will exit.
ble.run_mainloop_with(main)

python2で実行すると

Using adapter: astina-System-Product-Name
Disconnecting any connected UART devices...
Searching for UART device...
Connecting to device...
Discovering services...
Subscribing to RX characteristic changes...
Waiting 60 seconds to receive data from the device...
0102030000
0102030000
0102030000

みたいな感じでbluetooth経由で受信したデータが表示されます。(表示した受信データはblenano2のプログラムをちょっといじったので違います)

ちなみにDiscovering services...で止まってしまう場合は内部のbluetooth設定とかで止まっている可能性があります。
その場合は手動でbluetoothをオンオフしたりPCを再起動させたほうがいいです。
またRaspberryPi3 B+でも確認できました。

以上です。

ubuntu16でpythonのbluetooth開発環境を構築2

前回やったのはその後エラーで大変だったので、ちょっとやり直し。

環境

ubuntu16.04
python3.5.2

bluepyインストール

bluepy · PyPI
↑まず、ここからダウンロードしておく
2018/10/26現在最新は1.2.0

cd
sudo apt-get install libglib2.0-dev
tar -xzvf IanHarvey-bluepy-v-1.1.4-0-g117ac3d.tar.gz
cd IanHarvey-bluepy-117ac3d/
sudo python3 setup.py build
sudo python3 setup.py install

・インストール成功しているか確認

cd IanHarvey-bluepy-v-1.1.4-0-g117ac3d/bluepy
python scanner.py 
  Traceback (most recent call last):
    File "scanner.py", line 18, in <module>
      scanner.scan(10.0, passive=True)
    File "/usr/local/lib/python3.5/dist-packages/bluepy-1.1.4-py3.5.egg/bluepy/btle.py", line 679, in scan
      self.start(passive=passive)
    File "/usr/local/lib/python3.5/dist-packages/bluepy-1.1.4-py3.5.egg/bluepy/btle.py", line 617, in start
      self._mgmtCmd("le on")
    File "/usr/local/lib/python3.5/dist-packages/bluepy-1.1.4-py3.5.egg/bluepy/btle.py", line 276, in _mgmtCmd
      "Failed to execute mgmt cmd '%s'" % (cmd))
  bluepy.btle.BTLEException: Failed to execute mgmt cmd 'le on'

エラーが出る(今になって思うとこの時bluetoothドングル挿してなかったかも...)
また、2行目のfrom __future__ import print_functionは消しておく

bluetoothの確認
(ドングルさして確認)

sudo /usr/local/bin/blescan -i=0
Scanning for devices...
    Device (new): **:**:**:**:**:** (random), -62 dBm (not connectable)
	Complete 16b Services: <****>
	16b Service Data: <****0000000000000000000000000000000000000000>
	Manufacturer: <***********>

確認できた

・権限付与
また、調べてるとbluepy-helperでエラーが出てる人が多かったのでこちらも対処

sudo setcap 'cap_net_raw,cap_net_admin+eip' bluepy-helper

・bluepyが使えるか確認

python scanner.py 
Scanning for devices...
    Device (new): d2:18:5c:a9:20:33 (random), -43 dBm 
	Flags: <06>
	Complete Local Name: 'MyBlePeripheral'
	Complete 128b Services: <1e948df1483194ba754c3e5000003d71>

ちなみに見つかったのはredbearのblenano2(プログラムはこちら

以上。pythonbluetoothを使えるようになりました。