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を使えるようになりました。


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

ーー追記ーー
 
この記事の内容はすぐやめたので、ライブラリ変わってもいいならbluepyで構築した記事があるので飛んでください
ubuntu16でpythonのbluetooth開発環境を構築2 - ロボット、電子工作、IoT、AIなどの開発記録
 
ーーーーーー

今回はpyBluezとgattlibを入れました。
python2.7と3.4の人はすぐインストールができるけど、それ以外の人はちょっと面倒な感じでした。

環境

ubuntu16.04
python3.5.2

pyBlueZインストール

sudo apt install python3-dev libbluetooth3-dev

low Energyの人は

sudo pip install  pybluez\[ble\]

そうじゃない人は

pip install pybluez

pyBlueZインストール

依存関係インストール

sudo apt install libglib2.0 libboost-python-dev libboost-thread-dev

次に”リポジトリをダウンロードする”をクリックしてzipで保存する
OscarAcena / pygattlib / Downloads — Bitbucket

以下手順
・解凍
・setup.pyを開き、22行目boost_python-py34を自分の環境に合わせる(今回は35)
・src/Makefileを開き12行目のboost_python-py34を自分の環境に合わせる(今回は35)
・端末で make PYTHON_VER=3
・続いて sudo python3 setup.py install
・一応確認  sudo pip3 install gattlib

以上です

参考

ありがとうございます
python-gattlibのインストール方法 - Qiita

RealSenseSDK2で距離マップと画像の座標を一致した状態で取得する

D415やD435でrealsenseSDK2を使い距離と画像を同時取得しようと別々に処理かけると座標と見える領域にズレが生じます。
距離情報と画像情報を使って処理させるにはこのズレを一致させないといけません。

環境

ubuntu16.04 kernel 4.4.0-130-generic
opencv3.4

画像と距離情報の取得

例えば以下のページでenableして画像と距離情報を取得しているのは、ズレが生じた状態です。
librealsense/getting_started_with_openCV.md at master · IntelRealSense/librealsense · GitHub


座標系を一致した状態で取得

サンプルにあるDNNから編集しました。

#include <librealsense2/rs.hpp>
#include "cv-helpers.hpp"
#include <opencv2/opencv.hpp>   // Include OpenCV API
#include <iostream>
#include <stdio.h>
#include <stdlib.h>

using namespace cv;
using namespace std;
using namespace rs2;
const size_t inWidth      = 640;
const size_t inHeight     = 480;
const float WHRatio       = inWidth / (float)inHeight;

int main(int argc, char** argv) try
{

    // Start streaming from Intel RealSense Camera
    pipeline pipe;
    auto config = pipe.start();
    auto profile = config.get_stream(RS2_STREAM_COLOR)
                         .as<video_stream_profile>();
    rs2::align align_to(RS2_STREAM_COLOR);

    Size cropSize;
    if (profile.width() / (float)profile.height() > WHRatio)
    {
        cropSize = Size(static_cast<int>(profile.height() * WHRatio),
                        profile.height());
    }
    else
    {
        cropSize = Size(profile.width(),
                        static_cast<int>(profile.width() / WHRatio));
    }

    Rect crop(Point((profile.width() - cropSize.width) / 2,
                    (profile.height() - cropSize.height) / 2),
              cropSize);

    const auto window_name = "Display Image";
    namedWindow(window_name, WINDOW_AUTOSIZE);

    while (cvGetWindowHandle(window_name))
    {
        // Wait for the next set of frames
        auto data = pipe.wait_for_frames();
        // Make sure the frames are spatially aligned
        data = align_to.process(data);

        auto color_frame = data.get_color_frame();
        auto depth_frame = data.get_depth_frame();

        // If we only received new depth frame, 
        // but the color did not update, continue
        static int last_frame_number = 0;
        if (color_frame.get_frame_number() == last_frame_number) continue;
        last_frame_number = color_frame.get_frame_number();

        // Convert RealSense frame to OpenCV matrix:
        auto color_mat = frame_to_mat(color_frame);
        auto depth_mat = depth_frame_to_meters(pipe, depth_frame);
        
        imshow(window_name, color_mat);
        imshow("img", depth_mat);
        char key = waitKey( 5 );   

    }
}catch (const rs2::error & e)
{
    std::cerr << "RealSense error calling " << e.get_failed_function() << "(" << e.get_failed_args() << "):\n    " << e.what() << std::endl;
    return EXIT_FAILURE;
}
catch (const std::exception& e)
{
    std::cerr << e.what() << std::endl;
    return EXIT_FAILURE;
}

python,opencvで任意の大きさの面積だけを抽出する

検索してもあんまり出てこなかったりして、右往左往してなんとか書きました。
でももっと効率の良い書き方があると思いますので知っていたら教えてください、、、

環境

ubuntu16.04
opencv3.4
python3.5

プログラム
import cv2
import numpy as np

frame = cv2.imread("img.png")
height = frame.shape[0]
width = frame.shape[1]

img_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
#2値化
thresh = 40
max_pixel = 255
ret, img_dst = cv2.threshold(img_gray,
                             thresh,
                             max_pixel,
                             cv2.THRESH_BINARY)
#指定領域面積のみ抽出                             
dst = np.zeros((height, width, 1), np.uint8)
connectivity = 4
min_area=100
max_area=10000
output = cv2.connectedComponentsWithStats(img_dst, connectivity, cv2.CV_32S)
for i in range(output[0]):
    if output[2][i][4] >= min_area and output[2][i][4] <= max_area:
        cv2.rectangle(dst, (output[2][i][0], output[2][i][1]), (
            output[2][i][0] + output[2][i][2], output[2][i][1] + output[2][i][3]), (255, 255, 255), -1)
res = cv2.bitwise_and(dst,img_dst)


cv2.imshow("gray", img_dst)
cv2.imshow("frame", frame)
cv2.imshow("result", res)

k = cv2.waitKey(0)


cv2.destroyAllWindows()