LoginSignup
7
2

More than 5 years have passed since last update.

SAP S/4HANAのデータをiPhoneでAR表示してみた(2/2)

Last updated at Posted at 2019-01-15

商品をiPhoneのカメラで写すと、SAP S/4HANAから取得した在庫情報がARで浮かび上がるアプリを作ってみました。この記事ではデータ取得〜AR実装の詳細手順を紹介します。
ar.gif
(※ この記事は SAP Advent Calendar 2018 の12月15日分の記事として執筆しています)

構築手順

大きく下記の流れで構築しています。
1. SAP S/4HANA上でデータ取得処理(OData)を実装
2. SDK for iOS AssistantでXcodeプロジェクトを生成
3. XcodeでAR機能を追加実装

今回は3のトピックを書きます。

※トピック1~2は前回の記事↓を参照。
https://qiita.com/zukahira/items/c97f49f211a70dc1b555

3. XcodeでAR機能を追加実装する

前回の記事にて、S4HANAとデータ連携を行うXcodeプロジェクトがSDK for iOSにより自動生成しました。今回は自動生成されたXcodeプロジェクトを改造する形でAR機能を実装していきます。

Storyboardを追加する

まずプロジェクトのメインディレクトリ配下に"App"という名前のフォルダを作ります。今回新たに追加実装する資源はこのフォルダに入れることにします。
最初にストーリーボードを作ります。Appフォルダを右クリック>[New File]からストーリーボードを選択して追加します。今回は"MyStoryboard"と名付けます。
スクリーンショット 2018-12-31 22.29.20.png
右上の[Library]ボタンを押下し、View Controllerをストーリーボード上にドラッグして配置します。
スクリーンショット 2018-12-31 22.29.44.png
スクリーンショット 2018-12-31 22.30.05.png
次にSceneKit Viewを配置します。右上の[Library]ボタンから、[ARKit SceneKit View]をストーリーボードのView Controller上にドラッグします。
スクリーンショット 2018-12-31 22.30.23.png
配置したScene ViewをView Controllerいっぱいに広げます。次にデバイスの画面の大きさに依存してViewがズレないよう、右下のボタンからConstraintを追加します。View Controllerからの距離を0にして[Add 4 Vonstraints]を押下しましょう。
スクリーンショット 2018-12-31 22.30.51.png

Sceneファイルを追加する

Appフォルダを右クリック>[New File]から[SpriteKit Scene]を選択して追加します。今回は"Scene.sks"と名前をつけます。
スクリーンショット 2018-12-31 22.31.10.png

Swiftファイルを追加する

Appフォルダを右クリック>[New File]から[Cocoa Touch Class]を選択して追加します。
スクリーンショット 2018-12-31 22.31.30.png
名前を"Scene"、[Subclass of]にはSKSceneを指定します。
スクリーンショット 2018-12-31 22.31.51.png
次にView Controller用のSwiftファイルを追加します。Appフォルダを右クリック>[New File]から[Cocoa Touch Class]を選択して追加します。
スクリーンショット 2018-12-31 22.32.21.png
今回は名前を"MyViewController"とします。[Subclass of]にはUIViewControllerを指定します。
スクリーンショット 2018-12-31 22.32.38.png
Storyboardでクラスを指定してView Controllerと紐付けます。
スクリーンショット 2019-01-02 17.25.59.png

認識用画像イメージを準備する

今回はARKitのRecognizing Imagesを利用して、画像イメージがカメラで検出された際にAR空間上に3Dオブジェクトを配置する動きを実装します。

まず認識用の画像イメージファイルを準備します。Recognizing Images用のイメージ画像をAssetsフォルダに配置します。[+]ボタンから[New AR Resouce Group]を選択してフォルダを作成します。
スクリーンショット 2018-12-31 22.32.58.png
認識用画像ファイルをドラッグ&ドロップして登録します。データ紐付けのため、Image名にS4HANA上の品目コードを設定しておきます。また認識されるモノの実際のサイズも忘れずに設定しておきます。
スクリーンショット 2018-12-31 22.53.38.png

plistを更新する

今回はカメラを使用するため、plistにてPrivacy - Camera Usage Descriptionを設定しておきます。アプリ初回起動時にカメラの使用許可を聞かれる際、メッセージとして表示されるものです。
これが意外と重要で、iOS10からはこの記述がないとアプリが強制終了してしまうようです。詳しくはこちら
スクリーンショット 2018-12-31 22.33.38.png

初期表示Storyboardを変更する

SDKで自動生成されたデフォルトコードでは、Main.storyboardが初期表示されるものとして指定されているため、今回作成したStoryboardを指定するように変更します。

作成したView ControllerのIdentify情報にStoryboardID(今回は"App")を指定しておきます。
スクリーンショット 2019-01-02 4.35.28.png
次にAppDelegate.Swiftを書き換えます。デフォルトコードを下記のように書き換え、今回作成したStoryboardを指定します。

AppDelegate.swift

    private func setRootViewController() {
        DispatchQueue.main.async {

            //デフォルトコード→コメントアウト
            //let splitViewController = UIStoryboard(name: "Main", bundle: Bundle.main).instantiateViewController(withIdentifier: "MainSplitViewController") as! UISplitViewController
            //splitViewController.delegate = self
            //splitViewController.modalPresentationStyle = .currentContext
            //splitViewController.preferredDisplayMode = .allVisible

            //今回作成したStoryboardを指定
            let viewController = UIStoryboard(name: "MyStoryboard", bundle: Bundle.main).instantiateViewController(withIdentifier: "App")
            self.window!.rootViewController = viewController

        }
    }

セッション開始処理を実装する

ここから、メインのView Controller(MyViewController.swift)の実装をしていきます。
まず、StoryboardからSceneViewをOutlet接続します。
スクリーンショット 2018-12-31 22.34.26.png

今回の実装で使用するフレームワークをインポートします。

MyViewController.swift
import ARKit
import SAPFiori
import SAPOData

次にセッション開始メソッドを実装します。

MyViewController.swift
    //method:セッション開始処理
    func startSession(){

        //ToastMessageを出力
        FUIToastMessage.show(
            message: "商品をスキャンしてください",
            icon: FUIIconLibrary.map.legend.zoomExtent.withRenderingMode(.alwaysTemplate),
            inView: sceneView,
            withDuration: 3.0,
            maxNumberOfLines: 1)

        //sceneViewの設定
        sceneView.delegate = self
        sceneView.showsStatistics = false
        let scene = SCNScene()
        sceneView.scene = scene

        //ImageDetection用の画像ファイル読込
        let referenceImages = ARReferenceImage.referenceImages(inGroupNamed: "AR Resources", bundle: nil)
        let configuration = ARWorldTrackingConfiguration()
        configuration.detectionImages = referenceImages

        //sceneViewのセッション開始
        sceneView.session.run(configuration, options: [.resetTracking, .removeExistingAnchors])

    }

データ取得処理を実装します。
(※簡単のため、今回は初期処理で一括取得するようにしています。)

MyViewController.swift

    //在庫情報格納用変数
    var stockInfos = [StockInfo]()

    //method:在庫情報の取得処理
    func fetchStockInfoSet(_ completionHandler: @escaping () -> Void) {

        //AppDelegate
        let appDelegate = UIApplication.shared.delegate as! AppDelegate

        //クエリの作成
        let query = DataQuery().selectAll()
        do {
            //クエリ実行
            appDelegate.ytest001SRVEntities!.fetchStockInfoSet(matching: query) { StockInfoSet, error in
                if error == nil {
                    print("在庫情報の取得成功!")
                    self.stockInfos = StockInfoSet!
                } else {
                    print("在庫情報の取得失敗!だっふんだ!")
                }
                completionHandler()
            }
        }
    }

初期処理(viewDidLoad)で在庫情報の取得→セッション開始を行うよう下記のように実装します。

MyViewController.swift
    override func viewDidLoad() {
        super.viewDidLoad()
        //在庫情報の取得処理
        self.fetchStockInfoSet(){
            //セッション開始処理
            self.startSession()
        }
    }

画像イメージ認識時処理を実装する

前準備として3Dオブジェクトのための赤色・青色のイメージ画像を準備しておきます。これらは3Dオブジェクト(球体)の表面に表示される画像になります。
スクリーンショット 2018-12-31 22.50.01.png

ARSCNViewのDelegateメソッドに画像イメージ認識時の処理を実装します。

MyViewController.swift
    //method:画像認識時の処理
    func renderer(_ renderer: SCNSceneRenderer, nodeFor anchor: ARAnchor) -> SCNNode? {
        let node = SCNNode()
        if let imageAnchor = anchor as? ARImageAnchor {
            //ノード作成処理
            let markNode = getMoonNode(imageName: imageAnchor.referenceImage.name!)
            node.name = imageAnchor.referenceImage.name
            node.addChildNode(markNode)
        }
        return node
    }

    //method:ノード作成処理
    func getMoonNode(imageName: String) -> SCNNode {
        // 3Dオブジェクト(球体)の生成
        let sphere = SCNSphere(radius: 0.02)
        let material = SCNMaterial()
        let intStock = stockInfos.filter { $0.matnr == imageName }[0].quan
        if (intStock?.intValue())! < 5
        {
            //店舗在庫の数が5個よりも少なかったら🔴の球体を生成
            material.diffuse.contents = UIImage(named: "moon_red.jpg")
        }else{
            //店舗在庫の数が5個以上だったら🔵の球体を生成
            material.diffuse.contents = UIImage(named: "moon_blue.jpg")
        }
        sphere.materials = [material]
        let node = SCNNode()
        node.position = SCNVector3(0.0, 0.0, 0.03)
        node.geometry = sphere
        sceneView.scene.rootNode.addChildNode(node)
        return node
    }

動作確認

実装は完了です。左上のビルドボタンを押してXcodeプロジェクトの動作確認をしましょう。
スクリーンショット 2018-12-31 22.49.37.png

iPhoneで実行してみると、こういう感じになります。
daffunda2.GIF
S4の在庫情報(前回ブログ参照)と比較してみると、在庫が5個以上の品目に青球、在庫が5個より少ない品目に赤球が表示されている事が確認できます。
data.png

まとめ

今回はSCP SDK for iOSを使用し、S4HANAの情報をARで表示する簡単なアプリを作ってみました。基幹システムでは長年UI/UXが課題と言われがちでしたが、SDK for iOSを利用することでiOSの最新のUI/UXの技術を簡単に利用する事ができるようになります。モバイル化や、それに伴うUI/UXの変革は業務システムのデジタルトランスフォーメーションを推進する上でとても重要な要素となります。ARもどんな業務変革に応用できるか考えていけたら面白いですね。

7
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
2