iPhoneのセンサーデータをUbuntuPCで取得してROSで使おうとした話

# 背景
iPhoneのセンサーデータを使ってマニピュレータを動かせるのでは？と思いついたのが発端
調査していると以下の記事を発見しました

https://pietrocolombo.medium.com/use-iphone-as-imu-in-ros-2b3afbc50184

https://github.com/pietrocolombo/imu_from_ios_sensorlog

これは使えるのでは？と思い，試してみることにしたのですが，意外にハマって半日くらい消費したのでメモを共有します！

なお，こちらの記事はROS（Robot Operating System）に関する知識を有している方向けです．もしこちらに関して学びたい方は[チュートリアル](http://wiki.ros.org/ROS/Tutorials)などをご参照ください！

# 実行環境
1. センサーデータを送る側
    - iPhone 8
        - iOS version 16.3.1
        - Sim有: Rakuten Mobile

1. センサーデータを受け取る側
    - PC　CPUやGPUの性能は省略
        - Ubuntu 20.04
        - ROS Noetic

3. センサーデータをやり取りするためのネットワーク
    自分の家のWifiがいいと思います！iPhoneとPCを同じネットワーク（よくわからない方は同じルーター）に接続してください．


# 事前準備
この記事を試すにはiOS用有料アプリ[SensorLog]が必要です．少しお高いですが，興味がある方はぜひお試しください！

http://sensorlog.berndthomas.net/

https://apps.apple.com/jp/app/sensorlog/id388014573


# 環境構築
### iPhone側の設定
iPhoneにSensorLogをインストール
設定を開いて[Webサイト](https://pietrocolombo.medium.com/use-iphone-as-imu-in-ros-2b3afbc50184)の例通りに設定を変えていきます

自分の設定もおいておくので参考にしてください！IPアドレス（青く隠しているところ）のところはつないだネットワークのIPが自動で設定されます．
![IMG_0185.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1633039/7c291422-6a11-c1cf-3604-db4b398be4d7.jpeg)
![IMG_0186.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1633039/3da0a495-54cf-4ae0-c209-372ba7ab4051.jpeg)
![IMG_0187.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1633039/a527c878-5368-c539-6811-36940dc8f2a6.png)
![IMG_0188.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1633039/0fe0f36b-815f-49d2-ed21-24e0cd04f015.png)
![IMG_0189.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1633039/753bcb66-d545-2bd3-6944-b4a40dede6a2.png)

### Ubuntu側
まずはROSのワークスペースにgithubのパッケージをインストールします．
```
cd your/path/to/ros_ws
cd src
git clone https://github.com/pietrocolombo/imu_from_ios_sensorlog.git
```
続いてコードを少し修正します．
`imu_from_ros_sensorlog_node/src/imu_from_ros_sensorlog_node.cpp`の26行目以降を以下のように修正します．

修正前
```imu_from_ros_sensorlog_node.cpp
# line 26 - 40
    ros::NodeHandle nh;

    sensor_msgs::Imu msg_imu;
    int port, maxline;
    std::string ip, frame_id;

    // param
    nh.param("ip", ip, std::string("192.168.0.60"));
    nh.param("port", port, 12000);
    nh.param("maxline", maxline, 4096);
    nh.param("frame_id", frame_id, std::string("imu_iphone"));

    std::cout << "Params ---" << "ip:" << ip << " port:" << port << std::endl; 
    
    imu_pub = nh.advertise<sensor_msgs::Imu>("imu_iphone", 1);
```
修正後
```imu_from_ros_sensorlog_node.cpp
# line 26 - 41
    ros::NodeHandle nh;
    ros::NodeHandle pnh("~");

    sensor_msgs::Imu msg_imu;
    int port, maxline;
    std::string ip, frame_id;

    // param
    pnh.getParam("ip", ip);
    pnh.getParam("port", port);
    pnh.getParam("maxline", maxline);
    pnh.getParam("frame_id", frame_id);

    std::cout << "Params ---" << "ip:" << ip << " port:" << port << std::endl; 
    
    imu_pub = nh.advertise<sensor_msgs::Imu>("imu_iphone", 1);
```

更に，`imu_from_ros_sensorlog_node/launch/imu_from_ios_sensorlog.launch`のパラメータを修正します．
IPアドレスとPortの番号を，SensorLogの設定画面で表示されたIP/Portに設定します．

デフォルト
```imu_from_ios_sensorlog.launch
<launch>
    <arg name="topic" default="imu_iphone"/>

    <node pkg="imu_from_ios_sensorlog" type="imu_from_ios_sensorlog_node" name="imu_from_ios_sensorlog_node" output="screen">
      
      <param name="ip" value="192.168.0.60"/>　
      <param name="port" value="12000"/>
      <param name="maxline" value="4096"/>
      <param name="frame_id" value="imu_iphone"/>

      <remap from="imu_iphone" to="$(arg topic)" />
    
    </node>
</launch>
```
変更後
```imu_from_ios_sensorlog.launch
<launch>
    <arg name="topic" default="imu_iphone"/>
    <node pkg="imu_from_ios_sensorlog" type="imu_from_ios_sensorlog_node" name="imu_from_ios_sensorlog_node" output="screen">
      <param name="ip" value="your ip address"/>
      <param name="port" value="your port number"/>
      <param name="maxline" value="4096"/>
      <param name="frame_id" value="imu_iphone"/>
      <remap from="imu_iphone" to="$(arg topic)" />
    </node>
</launch>
```

変更できたらビルドします．
```
cd path/to/your/ros_ws
catkin build # or catkin_make
```

一旦これで準備完了です！

# いざ試す
始める前にiPhoneとUbuntuPCを同じネットワークに接続してください.
その後,iPhone側の設定で,Cellular通信をオフにします（何故かこれをしないと私の環境では動きませんでした　どなたか理由わかる方いたら教えてください）.


設定のCellularから
![IMG_0191 (1).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1633039/792f47c0-b474-3f8e-9cf3-cb5eee2e4a9b.jpeg)


Cellular Dataを
![IMG_0193.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1633039/7c59cc5b-0166-7141-b66f-8ba968e6f512.jpeg)

オフに
![IMG_0194 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1633039/f8f6c07f-cd0f-fc1a-0ecc-f800d98adecf.png)


その後SensorLogを起動した状態でUbuntuPCでROSノードを起動します．
```
cd path/to/your/ros_ws
source devel/setup.bash
roslaunch imu_from_ios_sensorlog imu_from_ios_sensorlog.launch 
```

接続がうまく行くとSensorLogでこんな感じのメッセージが出ます
![IMG_0196.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1633039/fb8aad8d-f561-3276-1b90-542ae7cd93c3.jpeg)

これで接続完了です．
アプリの左下の録画ボタンを押すとデータが送信されます．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1633039/d68c3f40-6185-b698-5338-d3bdd4389ec2.png)
([https://pietrocolombo.medium.com/use-iphone-as-imu-in-ros-2b3afbc50184](https://pietrocolombo.medium.com/use-iphone-as-imu-in-ros-2b3afbc50184)から拝借)

echoするとこんな感じ
https://drive.google.com/file/d/1cme3RZ9zOkC0kLcheaMLVp3kUJFnnRFJ/view?usp=sharing

RVIZに表示させてみるとおいているだけなのにブレがすんごい
https://drive.google.com/file/d/1jX3mC94_m5bI4OQ-JPkGRhPYiWcE4X3H/view?usp=sharing


意外に大変でしたが以上です！　IMUはフィルタかけて使わないと無理そうですね...。