電通総研のブログ - TECH PLAY

TECH PLAY

電通総研

電通総研 の技術ブログ

全867件

XI本部 オープン イノベーション ラボの飯田です。 最近、ChatGPTをはじめとした生成AIが注目されています。 その中で、 Gigazine のニュースで以下の話を目にしました。 gigazine.net 上記の記事に感化され、心理学でChatGPTのようなものが、どのように扱われているのかを調べています(私は大学で心理学専攻だったこともあり)。その中で、心理学系論文の プレプリント が掲載されている PsyArXiv で、GPT-3の振る舞いを 認知心理学 の観点で分析した論文を見つけました。 生成系の振る舞いを理解する上でも参考になりそうだし、ISIDでも取り組んでいるロボット技術やLabratory Automationとの接合点を見つけた気がしましたので、ISIDでの取り組みを紹介しつつ、妄想したいと思います。 Binz, M., & Schulz, E. (2022, June 21). Using cognitive psychology to understand GPT-3. https://doi.org/10.31234/osf.io/6dfgk ※ PNASに査読付き論文も公開されている ようですが、有料なので、今回は無料のPsyArXivをよんでいます。 ※念押しになりますが、以下、引用するBinz&Schulz(2022)は「ChatGPT」ではなく、「GPT-3」にて実験を行っています。 認知心理学の観点からみたGPT-3 Binz&Schulz(2022)の概要 Binz&Schulz(2022)の実験イメージ 意思決定:ヒューリスティックとバイアス(例:リンダ問題) 熟慮:認知反射テスト 因果推論:ブリケット探知器 情報の探索:多腕バンディット課題 大規模言語モデルとロボット技術・Labratory Automationとの接合の可能性 最後に 認知心理学 の観点からみたGPT-3 Binz&Schulz(2022)の概要 GPT-3に 認知心理学 で使われる課題を与え、その解答からGPT-3の特性を考察 4カテゴリ(1.意思決定 / 2.情報探索 / 3.熟慮 / 4.因果推論) についての実験を行った GPT-3は多くの課題に正解し、バンディット課題でも良い成績を残し、モデルベース 強化学習 を行っている可能性を示した。これらの結果は、GPT-3が単なる確率的なオウム返しではないことを示している。 一方で、人間の認知機能で重要な"統制的探査”や"因果推論”の能力を持っていないことも推察された これは人間とGPT-3の間で、世界についての知識習得・学習方法が違うことによって説明できる 人間は、他の人とつながり、質問をし、積極的に環境と関わることで学習する GPT-3などの大規模 言語モデル は、受動的に多くのテキストを与えられ、次に来る単語を予測することで学習する 人間が持つ認知機能の複雑さにより近づくためには、テキストを受動的に学習するだけではなく、 積極的に世界とインタ ラク ションすることが重要 と指摘している Binz&Schulz(2022)の実験イメージ 概要だけでは、イメージをつかみにくいと思いますので、簡単にBinz&Schulz(2022)がどのような実験をしたのか触れたいと思います。 意思決定: ヒューリスティック とバイアス(例:リンダ問題) 以下は、リンダのプロフィールです。 現在のリンダについて推測する場合、(1)と(2)のどちらの可能性が高いと思いますか? リンダは31歳、独身で、積極的に発言する非常に聡明です。 大学では哲学を専攻し、学生時代には差別や社会正義の問題に関心を持っていました。また、反核デモに参加していました。 1. リンダは銀行の出納係である。 2. リンダは銀行の出納係であり、フェミニスト運動の活動家である。  上記のような質問をされると、2は1の部分集合なので、確率的には1の方が間違いなく高いにもかかわらず、多くの人は2を選択する傾向にあります。 そのような「一般的な状況よりも、特殊な状況の方が起こりやすい」と誤判断することは"合接の誤謬"や"連言錯誤"と呼ばれます。 ステレオタイプ に合致した方を過大に評価しやすい意思決定プロセス(代表性 ヒューリスティクス )とされます。 →GPT-3は人と同じように、2番目の選択肢を選び、合接の誤謬に陥りました ※神谷先生がChatGPTでも試していらっしゃいます リンダ問題の答えを聞いて怒り出さないのが人間らしくない pic.twitter.com/HxxdPUbFOT — Yuki Kamitani (@ykamit) 2022年12月5日 熟慮:認知反射テスト 誤った解答がパッと浮かびやすい問題を課して、直観型か熟慮型かを見分けるようなテストです。 例)5台の機械を5分間動かすと、製品が5つできる。100台の機械で100個の製品を作るには、何分かかるか。 - パッと浮かびやすい解答:100分 - 正解:5分 →GPT-3は、多くの人間が選んでしまう、パッと浮かびやすい解答を行い不正解となりました 因果推論:ブリケット探知器 ブリケット探知器とは、以下のような装置であり、子供の因果推論能力を推定するテストです ある箱の上に、いろいろな色や形をした積み木のようなものを置く。 特定の積み木を特定の置き方で置いたとき、箱が光る。 →GPT-3は、人間と同じように、因果を見出しました 情報の探索:多腕バンディット課題 利益を最大化するための「活用」と「探索」の2種類の情報探索方法を適切に使い分けることができるか?という課題 活用:利益がどれぐらい得られるか過去に経験した手段の活用 探索:利益をさらに得られるかもしれない未知の手段の探索 このような質問が提示されて回答をしていくイメージです。 →GPT-3は人間と同等、それ以上のスコアを収めることができた。 しかし、探索方法の戦略を見ると、ランダム探索を主に行っており、統制的探査は見られなかった。 Binz&Schulz(2022)では、他にも詳しく行っていますので、気になる方は論文をお読みください。 大規模 言語モデル とロボット技術・Labratory Automationとの接合の可能性 Binz&Schulz(2022)では、「大規模 言語モデル はテキストを受動的に学習しているだけであるため、因果推論等は弱い」という指摘がありました。 その世界に介入(試行錯誤)して結果を得る取り組みとして、ロボット技術やLabratory Automation等があるのではないかと思います。 ISIDイノラボでは下記のように、ロボット技術を身近なものに活かす取り組みを色々と行っております。 ロボット技術を上手く使うことにより、ソフトウェアだけでは実現できない世界とのインタ ラク ション・フィードバックを基にした学習が可能となり、大規模 言語モデル の一層の進化が期待できるのではないでしょうか? www.isid.co.jp www.isid.co.jp また、Labratory Automationとは、下の動画のようなロボットによる科学実験の自動化技術です。 下記のNatureの動画のように、人間を介在せず、実験・試行錯誤をできます。 ※ISIDイノラボでもLabratory Automationの研究開発に取り組んでおり、その内容もいずれお伝えできればと思います。 大規模 言語モデル とロボット技術やLabratory Automationを上手く組み合わせることができたら、この論文でGPT-3の弱点と言われる因果推論もできるようになってくるのかもしれないと感じました。 認知心理学 では、身体化認知(embodied cognition)という概念があります。身体化認知では、人間の認知機能や概念知識を構築するにおいて、身体(感覚や身体的経験)が必須であるという立場です。 psychmuseum.jp ※上記P18にある通り、実験の追試に失敗したりなど、再現性問題が指摘されていたりしますが・・・ また、静的なデー タセット によるト レーニン グから学んだ表現よりも、世界との相互作用を通じて学習した表現の方が強力であるとして Embodied AIが提唱されており 、CVPRでは Embodied AIのワークショップ も開催されています。 大規模 言語モデル においても、より進化させていくにあたっては、身体化認知のような 認知科学 の知見も活かされてくるのだろうなと感じました。 最後に ChatGPTでも簡単にできるテストを試してみましたので、結果を載せておきます。 リンダ問題 最初やってみたら、実験の決まり文句だとバレました 少し修正したら、誤魔化すことができて、連言錯誤に陥りました(改変が妥当でない可能性もありますが) 認知反射テスト キレイに間違えてくれました 情報探索(適切な質問を選ぶことができるのか?) 正解しました 最後に、私たちは一緒に働いてくれる仲間を募集しています! デジタル技術を社会課題解決につなげるようなプロジェクトを推進していきたいプロジェクトマネージャーやエンジニアを募集しています。 ぜひご応募ください! ソリューションアーキテクト スマートシティ導入コンサルタント/スマートシティ戦略コンサルタント 執筆: @iida.michitaka 、レビュー: @yamada.y ( Shodo で執筆されました )
こんにちは。X(クロス) イノベーション 本部 ソフトウェアデザインセンター の山下です。 今回はユーザーに合わせてオートスケールする GitHub ActionsのRunnerについて紹介しようと思います。 課題と目的 公式の推奨している方法について 構築の手順 事前準備 terraformの実行 terraformファイルの作成 terraformの実行 GitHub Appにhookの設定を追加 実際に利用する場合 まとめ 課題と目的 GitHub Actionsを使ってCIを実施するのは一般的になってきています。 ISIDでも GitHub Actionsを活用してCIを実施しています。 しかし、 GitHub 社が提供しているrunners( GitHub -hosted runners)では困る場合があります。「 GitHub Actionsでオンプレミス環境のCI/CDを実行する方法 」の記事では、オンプレミス環境のような外部ネットワークに接続できないような環境で GitHub Actionsを利用したCIを実施する場合に、self-hosted runnersを紹介しました。 オンプレ環境で実行できないこと以外にも、 GitHub Actionsの標準環境にはいくつか不満があります。 CIの待ち時間が長い CIに使うマシンの性能を調整したい CIの費用が高い といった問題です。 GitHub -hosted runnersでは、 GitHub 社が提供しているインフラに依存しています。このため、 GitHub 側の調子が悪いときにCI開始されるまでの待ち時間が長くなったりします。 また、CIの実行に使うマシンも GitHub 社が決めたものの範囲で選ぶことになってしまいます。 以前は、選択の余地がなかったのですが、Larger Runnersがbeta版ですが公開されて状況は改善しつつあります。Larger Runnersに関する公式の記事は こちら です。 また、 GitHub Actionsの料金は Linux の場合、1分当たり$0.008 となっていて安くはないです。 単純計算すると1時間あたり $0.48 になってしまい、 AWS だとt3.2xlargeを借りることが出来てしまいます。 以下のドキュメントによると、 GitHub 標準のrunnerの性能は、2コア、7GBメモリのマシンのようなので若干コスト高になってしまいます。 https://docs.github.com/ja/actions/using-github-hosted-runners/about-github-hosted-runners#supported-runners-and-hardware-resources self-hosted runnerを導入することで、自前の環境を構築すれば待ち時間や性能の問題は解決します。しかし、高性能なマシンをずっと起動しているとコストが高くなってしまいます。 必要な時、必要な分だけEC2を起動し GitHub Actionsのself-hosted runnersを動作できれば、コストパフォーマンスに優れるself-hosted runners環境を構築できます。 今回はその環境(Autoscale self-hosted runners)について解説します。 公式の推奨している方法について GitHub の 公式の資料 にオートスケールするself-hosted runnersについての記載があります。 基本的に、この手順に従って構築すれば問題ないです。公式では以下の2種類の方法が提供されています。 actions-runner-controller/actions-runner-controller - GitHub Actions のセルフホステッド ランナー用の Kubernetes コントローラー。 philips-labs/terraform-aws-github-runner - AWS 上のスケーラブルな GitHub Actions ランナー用の Terraform モジュール。 actions-runner-controller/actions-runner-controller は kubernetes 上にself-hosted runnersを構築する物になっています。既に kubernetes を運用している場合にはこちらを導入するのが良いですが、 GitHub Actionsのためだけに kubernetes を運用するのは運用負荷を考えると難しいので今回は採用しませんでした。 philips-labs/terraform-aws-github-runner は、 AWS のAutoScaling Groupを利用して self-hosted runners環境を構築するものとなっています。構築はterraformを利用することになります。今回はこちらを使って環境構築を行います。 構築の手順 それでは早速構築の手順について解説します。 GitHub Appの設定と terraform の実行と両方を行っていく必要があるので順番に気を付けて実施してください。 事前準備 環境構築に際していくつか事前に準備しておく物があります。 terraformのインストール GitHub Appの作成 GitHub AppのClientID GitHub App用の 秘密鍵 terraformは各自インストールする必要があります。 公式サイト から適宜インストールしておいてください。 terraform-aws-github-runner のマニュアルに記載がありますが、 GitHub 上で GitHub Appを作成する必要があります。いくつか注意が必要です。 まず、最初に作成する際は、WebhookをActiveにしないで作成します。 今回は特定のプロジェクトで利用するような事を想定し、 GitHub Appに与える権限をRepositoryレベルで設定します。以下のように、Actions、Checks、MetadataをRead-onlyにします。それに加えて、AdministrationをRead & writeとしました。 terraformの実行 terraformファイルの作成 今回は以下のような2つのtfファイルを作成して実行しました。片方が VPC を作成するもの、片方が今回のself-hosted runner用の物です。 // vpc.tf module "vpc" { source = "terraform-aws-modules/vpc/aws" version = "3.11.2" name = "vpc-${local.environment}" cidr = "10.0.0.0/16" azs = ["${local.aws_region}a", "${local.aws_region}c", "${local.aws_region}d"] private_subnets = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"] public_subnets = ["10.0.101.0/24", "10.0.102.0/24", "10.0.103.0/24"] enable_dns_hostnames = true enable_nat_gateway = true map_public_ip_on_launch = false single_nat_gateway = true tags = { Environment = local.environment } // main.tf locals { version = "v1.8.0" environment = "default" aws_region = "ap-northeast-1" } provider "aws" { region = "ap-northeast-1" } variable "github_app_key_base64" {} variable "github_app_id" {} resource "random_id" "random" { byte_length = 20 } data "aws_caller_identity" "current" {} module "runners" { source = "philips-labs/github-runner/aws" version = "1.8.0" create_service_linked_role_spot = false aws_region = local.aws_region vpc_id = module.vpc.vpc_id subnet_ids = module.vpc.private_subnets prefix = local.environment tags = { costcenter = "p7-ci-template" Project = "AutoScaleTest" } github_app = { key_base64 = var.github_app_key_base64 id = var.github_app_id webhook_secret = random_id.random.hex } webhook_lambda_zip = "webhook.zip" runner_binaries_syncer_lambda_zip = "runner-binaries-syncer.zip" runners_lambda_zip = "runners.zip" enable_organization_runners = false # ランナーのラベル # github actionsの設定ファイルで指定するラベルとなる runner_extra_labels = "default,<CIで指定するラベル>" # enable access to the runners via SSM enable_ssm_on_runners = true instance_types = ["m5.large", "c5.large"] # override delay of events in seconds delay_webhook_event = 5 runners_maximum_count = 1 # set up a fifo queue to remain order fifo_build_queue = true # override scaling down scale_down_schedule_expression = "cron(* * * * ? *)" } また、変数の設定ファイル(terraform.tfvars)も作成します。 以下のような内容です。 秘密鍵 は base64 に変換することに注意してください。 github_app_id = "<<github appのid>>" github_app_key_base64 = <<EOF <<取得したgithub appの秘密鍵をbase64エンコードしたもの>> EOF terraformの実行 ここまで準備すれば、あとは terraform を実行するだけです terraform init terraform apply すると、 AWS 上に環境が構築されます。 GitHub Appにhookの設定を追加 先ほど、 terraform apply をした出力に GitHub appで利用するwebhookのURLが含まれています。 terraform output -json を実行しても取得できます。 以下のような出力が得られます。 { "runners": { "sensitive": false, "type": [ "object", { "lambda_syncer_name": "string" } ], "value": { "lambda_syncer_name": "default-syncer" } }, "webhook_endpoint": { "sensitive": false, "type": "string", "value": "<webhookのURL>" }, "webhook_secret": { "sensitive": true, "type": "string", "value": "<secret>" } } これらの <webhookのURL> 、 <secret> の内容が必要です。 この値を、 GitHub Appのwebhookのendpointとsecretとして登録します。画面では以下のようになります。 そして、eventのサブスクライブが必要なので、Permission & eventsから workflow job にチェックを入れてください。これで設定完了です。 実際に利用する場合 GitHub Actionsを設定する yaml ファイルで runs-on : [ self-hosted, default, <設定したラベル> ] と記載しておけば、実行時に自動的に インスタンス の起動などが行われてその インスタンス 上で実行されます。 まとめ 今回は、オートスケールする GitHub self-hosted runnersの構築手順について紹介しました。 これを使ってどんどんCIを回していきたいですね。 私たちは同じチームで働いてくれる仲間を探しています。今回のエントリで紹介したような仕事に興味のある方、ご応募お待ちしています。 - ソリューションアーキテクト 執筆: @yamashita.tsuyoshi 、レビュー: @sato.taichi ( Shodo で執筆されました )
こんにちは。X(クロス) イノベーション 本部 ソフトウェアデザインセンター の山下です。 今回はユーザーに合わせてオートスケールする GitHub ActionsのRunnerについて紹介しようと思います。 課題と目的 公式の推奨している方法について 構築の手順 事前準備 terraformの実行 terraformファイルの作成 terraformの実行 GitHub Appにhookの設定を追加 実際に利用する場合 まとめ 課題と目的 GitHub Actionsを使ってCIを実施するのは一般的になってきています。 ISIDでも GitHub Actionsを活用してCIを実施しています。 しかし、 GitHub 社が提供しているrunners( GitHub -hosted runners)では困る場合があります。「 GitHub Actionsでオンプレミス環境のCI/CDを実行する方法 」の記事では、オンプレミス環境のような外部ネットワークに接続できないような環境で GitHub Actionsを利用したCIを実施する場合に、self-hosted runnersを紹介しました。 オンプレ環境で実行できないこと以外にも、 GitHub Actionsの標準環境にはいくつか不満があります。 CIの待ち時間が長い CIに使うマシンの性能を調整したい CIの費用が高い といった問題です。 GitHub -hosted runnersでは、 GitHub 社が提供しているインフラに依存しています。このため、 GitHub 側の調子が悪いときにCI開始されるまでの待ち時間が長くなったりします。 また、CIの実行に使うマシンも GitHub 社が決めたものの範囲で選ぶことになってしまいます。 以前は、選択の余地がなかったのですが、Larger Runnersがbeta版ですが公開されて状況は改善しつつあります。Larger Runnersに関する公式の記事は こちら です。 また、 GitHub Actionsの料金は Linux の場合、1分当たり$0.008 となっていて安くはないです。 単純計算すると1時間あたり $0.48 になってしまい、 AWS だとt3.2xlargeを借りることが出来てしまいます。 以下のドキュメントによると、 GitHub 標準のrunnerの性能は、2コア、7GBメモリのマシンのようなので若干コスト高になってしまいます。 https://docs.github.com/ja/actions/using-github-hosted-runners/about-github-hosted-runners#supported-runners-and-hardware-resources self-hosted runnerを導入することで、自前の環境を構築すれば待ち時間や性能の問題は解決します。しかし、高性能なマシンをずっと起動しているとコストが高くなってしまいます。 必要な時、必要な分だけEC2を起動し GitHub Actionsのself-hosted runnersを動作できれば、コストパフォーマンスに優れるself-hosted runners環境を構築できます。 今回はその環境(Autoscale self-hosted runners)について解説します。 公式の推奨している方法について GitHub の 公式の資料 にオートスケールするself-hosted runnersについての記載があります。 基本的に、この手順に従って構築すれば問題ないです。公式では以下の2種類の方法が提供されています。 actions-runner-controller/actions-runner-controller - GitHub Actions のセルフホステッド ランナー用の Kubernetes コントローラー。 philips-labs/terraform-aws-github-runner - AWS 上のスケーラブルな GitHub Actions ランナー用の Terraform モジュール。 actions-runner-controller/actions-runner-controller は kubernetes 上にself-hosted runnersを構築する物になっています。既に kubernetes を運用している場合にはこちらを導入するのが良いですが、 GitHub Actionsのためだけに kubernetes を運用するのは運用負荷を考えると難しいので今回は採用しませんでした。 philips-labs/terraform-aws-github-runner は、 AWS のAutoScaling Groupを利用して self-hosted runners環境を構築するものとなっています。構築はterraformを利用することになります。今回はこちらを使って環境構築を行います。 構築の手順 それでは早速構築の手順について解説します。 GitHub Appの設定と terraform の実行と両方を行っていく必要があるので順番に気を付けて実施してください。 事前準備 環境構築に際していくつか事前に準備しておく物があります。 terraformのインストール GitHub Appの作成 GitHub AppのClientID GitHub App用の 秘密鍵 terraformは各自インストールする必要があります。 公式サイト から適宜インストールしておいてください。 terraform-aws-github-runner のマニュアルに記載がありますが、 GitHub 上で GitHub Appを作成する必要があります。いくつか注意が必要です。 まず、最初に作成する際は、WebhookをActiveにしないで作成します。 今回は特定のプロジェクトで利用するような事を想定し、 GitHub Appに与える権限をRepositoryレベルで設定します。以下のように、Actions、Checks、MetadataをRead-onlyにします。それに加えて、AdministrationをRead & writeとしました。 terraformの実行 terraformファイルの作成 今回は以下のような2つのtfファイルを作成して実行しました。片方が VPC を作成するもの、片方が今回のself-hosted runner用の物です。 // vpc.tf module "vpc" { source = "terraform-aws-modules/vpc/aws" version = "3.11.2" name = "vpc-${local.environment}" cidr = "10.0.0.0/16" azs = ["${local.aws_region}a", "${local.aws_region}c", "${local.aws_region}d"] private_subnets = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"] public_subnets = ["10.0.101.0/24", "10.0.102.0/24", "10.0.103.0/24"] enable_dns_hostnames = true enable_nat_gateway = true map_public_ip_on_launch = false single_nat_gateway = true tags = { Environment = local.environment } // main.tf locals { version = "v1.8.0" environment = "default" aws_region = "ap-northeast-1" } provider "aws" { region = "ap-northeast-1" } variable "github_app_key_base64" {} variable "github_app_id" {} resource "random_id" "random" { byte_length = 20 } data "aws_caller_identity" "current" {} module "runners" { source = "philips-labs/github-runner/aws" version = "1.8.0" create_service_linked_role_spot = false aws_region = local.aws_region vpc_id = module.vpc.vpc_id subnet_ids = module.vpc.private_subnets prefix = local.environment tags = { costcenter = "p7-ci-template" Project = "AutoScaleTest" } github_app = { key_base64 = var.github_app_key_base64 id = var.github_app_id webhook_secret = random_id.random.hex } webhook_lambda_zip = "webhook.zip" runner_binaries_syncer_lambda_zip = "runner-binaries-syncer.zip" runners_lambda_zip = "runners.zip" enable_organization_runners = false # ランナーのラベル # github actionsの設定ファイルで指定するラベルとなる runner_extra_labels = "default,<CIで指定するラベル>" # enable access to the runners via SSM enable_ssm_on_runners = true instance_types = ["m5.large", "c5.large"] # override delay of events in seconds delay_webhook_event = 5 runners_maximum_count = 1 # set up a fifo queue to remain order fifo_build_queue = true # override scaling down scale_down_schedule_expression = "cron(* * * * ? *)" } また、変数の設定ファイル(terraform.tfvars)も作成します。 以下のような内容です。 秘密鍵 は base64 に変換することに注意してください。 github_app_id = "<<github appのid>>" github_app_key_base64 = <<EOF <<取得したgithub appの秘密鍵をbase64エンコードしたもの>> EOF terraformの実行 ここまで準備すれば、あとは terraform を実行するだけです terraform init terraform apply すると、 AWS 上に環境が構築されます。 GitHub Appにhookの設定を追加 先ほど、 terraform apply をした出力に GitHub appで利用するwebhookのURLが含まれています。 terraform output -json を実行しても取得できます。 以下のような出力が得られます。 { "runners": { "sensitive": false, "type": [ "object", { "lambda_syncer_name": "string" } ], "value": { "lambda_syncer_name": "default-syncer" } }, "webhook_endpoint": { "sensitive": false, "type": "string", "value": "<webhookのURL>" }, "webhook_secret": { "sensitive": true, "type": "string", "value": "<secret>" } } これらの <webhookのURL> 、 <secret> の内容が必要です。 この値を、 GitHub Appのwebhookのendpointとsecretとして登録します。画面では以下のようになります。 そして、eventのサブスクライブが必要なので、Permission & eventsから workflow job にチェックを入れてください。これで設定完了です。 実際に利用する場合 GitHub Actionsを設定する yaml ファイルで runs-on : [ self-hosted, default, <設定したラベル> ] と記載しておけば、実行時に自動的に インスタンス の起動などが行われてその インスタンス 上で実行されます。 まとめ 今回は、オートスケールする GitHub self-hosted runnersの構築手順について紹介しました。 これを使ってどんどんCIを回していきたいですね。 私たちは同じチームで働いてくれる仲間を探しています。今回のエントリで紹介したような仕事に興味のある方、ご応募お待ちしています。 - ソリューションアーキテクト 執筆: @yamashita.tsuyoshi 、レビュー: @sato.taichi ( Shodo で執筆されました )
こんにちは、 GMS 事業部グループ経営 コンサルティング 第1ユニットの安田しおりです。 この記事では、ISIDに興味を持ってくださっている就活生の皆さんに向けて3年目(2021年入社)の私の働き方を紹介したいと思います。 仕事内容について まずは、私がどんな仕事をしているのか仕事内容を簡単に紹介します。 私が所属するグループ経営 コンサルティング 第1ユニット(GMC1ユニット)では STRAVIS という 連結会計 ソリューションを扱っています。私はSTRAVISの コンサルタント として様々な業務に関わっています。ここでは、主な3つの業務についてご紹介します。 1. 導入プロジェクト 導入プロジェクトでは、STRAVISをお客様にご利用いただくためのシステム導入作業として、要件定義や設定、検証、トライアル支援等を実施します。要件定義のフェーズではお客様から業務内容を ヒアリ ングし、必要な機能や設定内容を検討します。設定フェーズでは、要件定義フェーズで整理した内容に基づいて実際にSTRAVISを設定します。基本的にSTRAVISは導入時にコーディングの必要がなく、画面操作によって基本情報や処理の設定を行うことができます。検証フェーズでは、設定内容を確認するためのテストケースを作成し、テストを実施します。トライアルフェーズではシステムの試験稼働をサポートします。 2. セールス支援の案件 新しく 連結会計 システムの導入を検討しているお客様への提案や、既存のSTRAVISユーザーへの追加提案活動を行います。 セールス支援での コンサルタント の役割は、お客様にSTRAVISの特徴やSTRAVISを導入するメリットを理解していただくことです。そのために、お客様の前でSTRAVISを操作しながら機能紹介をしたり、実際にお客様にシステムを触ってもらいながら操作をレクチャーしたりします。また、具体的な提案内容を提案書にまとめ、プレゼンします。お客様へのプレゼンや機能紹介は「上手く伝えられるか」と緊張する瞬間ではありますが、提案後にお客様からSTRAVISに対して良い評価のコメントをいただけるととてもやりがいを感じます。 3. BPO ( アウトソーシング サービス) ISIDでは、STRAVIS導入後のお客様に対してSTRAVIS関連の連結決算業務の一部を支援する アウトソーシング サービスを提供しています。私は BPO 案件の中で、STRAVISの設定のメンテナンスを行ったり、データ確認や仕訳作成の一部作業を担当したりしています。実際の決算業務の中でSTRAVISを使うことができるため、自分の成長に大きくつながったプロジェクトだと考えています。 上記の3つの案件以外にも、STRAVISオンライン セミ ナーの講師を務めるなど幅広く活動しています。 1週間の流れ  仕事内容の紹介で複数案件に参加していると書きましたが、どのような1週間を過ごしているかスケジュールを紹介します。月によって案件の内容は変わりますが、1週間の中でセールス支援がメインの日もあれば導入作業や BPO の作業がメインの日もあります。お客様とのミーティングの予定も多く、常に複数のお客様と関わりがあります。他にも部内の活動として、グループ会や1on1が週に1回程度あります。グループ会では案件状況の報告や、メンバ間でのノウハウ共有を行います。 また、部長やグルプマネージャーと1対1で会話する機会として週に1回15分程度1on1を実施しています。1on1を定期的に実施していることで、業務の中での相談などもより気軽にできていると思います。 終業後は、同期に会ったり、美容院に行ったりとプライベートの時間を確保して気持ちをリフレッシュしています。 GMC1ユニットでの働き方の特長 次に、私が考える「この部署での働き方の特長」についてです。私がGMC1ユニットで働く中で、自分に合っていると感じたポイント2つについて説明します。 私が考える特長の1つめは「幅広さ」です。 私は入社3年目ですが、様々な案件に関わってきました。複数の案件に同時に関わることが多いため、次々と新しいことに挑戦できますし、 スキルアップ できる機会も豊富にあります。そして単に新しいことに挑戦する機会が多いだけでなく、性質の異なる案件を経験することで様々な角度から知識やスキルを習得できる点もメリットに感じています。例えば、導入プロジェクトを経験していたことでセールス支援の時に具体的な導入事例を紹介できた、というように幅広く経験して良かったなと思うことが多いです。このように得た知識を発揮できる場が多いと自分の成長を実感でき、モチベーションの維持にも繋がっています。 また私の場合、この部署での幅広い業務経験が「特にどのスキルを伸ばしていきたいか」「どういう事に特化した人材を目指すのか」という選択肢を拡げることに繋がりました。入社直後はやりたい事のイメージが掴めていませんでしたが、今では選択肢の中から将来のキャリアをイメージできています。 このような理由から、GMC1ユニットの「幅広さ」が私にとってマッチしていたと考えています。 2つ目の特長は、若手のうちからお客様との関わりが多いという点です。 「新規提案中のお客様」「一緒にSTRAVISの導入を行っているお客様」「 BPO で関わるSTRAVISユーザー」など様々な立場のお客様とプロジェクトを通して接することができます。お客様の反応を直接確認できるので、良い反応を貰えると嬉しいですし、それがモチベーションにもつながっています。逆に、お客様の反応から自分の改善するべき点に気づく場合もあります。例えばお客様からの指摘や質問に一人では対応できず、どの部分の理解が不足しているのか気付くこともあります。お客様からの評価と気づきをあらゆる角度から得ることが出来るという点が顧客との関わりが多いメリットだと思っています。 また若手のうちから、セールス支援でも導入プロジェクトでもメインスピーカーとして参加できるので「プレゼン力を身につけたい」「社外でも通用するビジネススキルを身につけたい」といった人にも向いていると思います。学生時代、私は人前で話すのがとても緊張するタイプでしたが、今ではスピーカーとして会議に参加することも徐々に楽しめるようになってきました。 入る前のイメージと入った後感じたこと 私は学生時代、ITとも会計とも無縁の専攻でした。そのため、配属前は自分に会計やシステムの事が理解できるのか、チームのメンバの一員として役に立つことが出来るのか不安を感じていました。また、「若手のうちから挑戦できる」=「放置される」なのではないかという不安もありました。 こんな風に不安を感じながら配属された私ですが、GMC1ユニットでは一人一人のレベルにあった新人教育がされ、先輩からのサポートも手厚いため不安なく働くことができました。具体的に、私が配属後一番初めに行ったのは「STRAVISを知る」事でした。GMC1ユニットではユーザー向けのeラーニングや セミ ナーを多数用意しているので、それらを受講して勉強することができます。さらに導入案件やセールス案件に参加して、実際のプロジェクトの流れや会計の知識、STRAVISの機能や操作について学ぶこともしました。 私のように、入社前・配属前の段階で会計やITの学習経験がない場合でも不安に感じる必要はないです。GMC1ユニットでは自分のスキルに合わせて学んでいくことができます。もし、少しでも興味を持ってくださった方はまずはISIDやSTRAVISを知ることから始めていただけると嬉しいです。 最後に 就活生の皆さんの中には私のようにIT系の専攻ではないけれどISIDに興味を持ってくださっている方もいるかと思います。 GMS 事業部GMC1ユニットでは既にITや会計に詳しいという方はもちろんですが、今はまだ興味を持ち始めた段階だという方も大歓迎です。私の働き方紹介が皆さんの将来を考える材料になればうれしいなと思います。 以下採用ページへのリンクです。興味を持ってくださった方は、ぜひご応募ください。 www.isid.co.jp 執筆: @yasuda.shiori 、レビュー: Ishizawa Kento (@kent) ( Shodo で執筆されました )
こんにちは、 GMS 事業部グループ経営 コンサルティング 第1ユニットの安田しおりです。 この記事では、ISIDに興味を持ってくださっている就活生の皆さんに向けて3年目(2021年入社)の私の働き方を紹介したいと思います。 仕事内容について まずは、私がどんな仕事をしているのか仕事内容を簡単に紹介します。 私が所属するグループ経営 コンサルティング 第1ユニット(GMC1ユニット)では STRAVIS という 連結会計 ソリューションを扱っています。私はSTRAVISの コンサルタント として様々な業務に関わっています。ここでは、主な3つの業務についてご紹介します。 1. 導入プロジェクト 導入プロジェクトでは、STRAVISをお客様にご利用いただくためのシステム導入作業として、要件定義や設定、検証、トライアル支援等を実施します。要件定義のフェーズではお客様から業務内容を ヒアリ ングし、必要な機能や設定内容を検討します。設定フェーズでは、要件定義フェーズで整理した内容に基づいて実際にSTRAVISを設定します。基本的にSTRAVISは導入時にコーディングの必要がなく、画面操作によって基本情報や処理の設定を行うことができます。検証フェーズでは、設定内容を確認するためのテストケースを作成し、テストを実施します。トライアルフェーズではシステムの試験稼働をサポートします。 2. セールス支援の案件 新しく 連結会計 システムの導入を検討しているお客様への提案や、既存のSTRAVISユーザーへの追加提案活動を行います。 セールス支援での コンサルタント の役割は、お客様にSTRAVISの特徴やSTRAVISを導入するメリットを理解していただくことです。そのために、お客様の前でSTRAVISを操作しながら機能紹介をしたり、実際にお客様にシステムを触ってもらいながら操作をレクチャーしたりします。また、具体的な提案内容を提案書にまとめ、プレゼンします。お客様へのプレゼンや機能紹介は「上手く伝えられるか」と緊張する瞬間ではありますが、提案後にお客様からSTRAVISに対して良い評価のコメントをいただけるととてもやりがいを感じます。 3. BPO ( アウトソーシング サービス) ISIDでは、STRAVIS導入後のお客様に対してSTRAVIS関連の連結決算業務の一部を支援する アウトソーシング サービスを提供しています。私は BPO 案件の中で、STRAVISの設定のメンテナンスを行ったり、データ確認や仕訳作成の一部作業を担当したりしています。実際の決算業務の中でSTRAVISを使うことができるため、自分の成長に大きくつながったプロジェクトだと考えています。 上記の3つの案件以外にも、STRAVISオンライン セミ ナーの講師を務めるなど幅広く活動しています。 1週間の流れ  仕事内容の紹介で複数案件に参加していると書きましたが、どのような1週間を過ごしているかスケジュールを紹介します。月によって案件の内容は変わりますが、1週間の中でセールス支援がメインの日もあれば導入作業や BPO の作業がメインの日もあります。お客様とのミーティングの予定も多く、常に複数のお客様と関わりがあります。他にも部内の活動として、グループ会や1on1が週に1回程度あります。グループ会では案件状況の報告や、メンバ間でのノウハウ共有を行います。 また、部長やグルプマネージャーと1対1で会話する機会として週に1回15分程度1on1を実施しています。1on1を定期的に実施していることで、業務の中での相談などもより気軽にできていると思います。 終業後は、同期に会ったり、美容院に行ったりとプライベートの時間を確保して気持ちをリフレッシュしています。 GMC1ユニットでの働き方の特長 次に、私が考える「この部署での働き方の特長」についてです。私がGMC1ユニットで働く中で、自分に合っていると感じたポイント2つについて説明します。 私が考える特長の1つめは「幅広さ」です。 私は入社3年目ですが、様々な案件に関わってきました。複数の案件に同時に関わることが多いため、次々と新しいことに挑戦できますし、 スキルアップ できる機会も豊富にあります。そして単に新しいことに挑戦する機会が多いだけでなく、性質の異なる案件を経験することで様々な角度から知識やスキルを習得できる点もメリットに感じています。例えば、導入プロジェクトを経験していたことでセールス支援の時に具体的な導入事例を紹介できた、というように幅広く経験して良かったなと思うことが多いです。このように得た知識を発揮できる場が多いと自分の成長を実感でき、モチベーションの維持にも繋がっています。 また私の場合、この部署での幅広い業務経験が「特にどのスキルを伸ばしていきたいか」「どういう事に特化した人材を目指すのか」という選択肢を拡げることに繋がりました。入社直後はやりたい事のイメージが掴めていませんでしたが、今では選択肢の中から将来のキャリアをイメージできています。 このような理由から、GMC1ユニットの「幅広さ」が私にとってマッチしていたと考えています。 2つ目の特長は、若手のうちからお客様との関わりが多いという点です。 「新規提案中のお客様」「一緒にSTRAVISの導入を行っているお客様」「 BPO で関わるSTRAVISユーザー」など様々な立場のお客様とプロジェクトを通して接することができます。お客様の反応を直接確認できるので、良い反応を貰えると嬉しいですし、それがモチベーションにもつながっています。逆に、お客様の反応から自分の改善するべき点に気づく場合もあります。例えばお客様からの指摘や質問に一人では対応できず、どの部分の理解が不足しているのか気付くこともあります。お客様からの評価と気づきをあらゆる角度から得ることが出来るという点が顧客との関わりが多いメリットだと思っています。 また若手のうちから、セールス支援でも導入プロジェクトでもメインスピーカーとして参加できるので「プレゼン力を身につけたい」「社外でも通用するビジネススキルを身につけたい」といった人にも向いていると思います。学生時代、私は人前で話すのがとても緊張するタイプでしたが、今ではスピーカーとして会議に参加することも徐々に楽しめるようになってきました。 入る前のイメージと入った後感じたこと 私は学生時代、ITとも会計とも無縁の専攻でした。そのため、配属前は自分に会計やシステムの事が理解できるのか、チームのメンバの一員として役に立つことが出来るのか不安を感じていました。また、「若手のうちから挑戦できる」=「放置される」なのではないかという不安もありました。 こんな風に不安を感じながら配属された私ですが、GMC1ユニットでは一人一人のレベルにあった新人教育がされ、先輩からのサポートも手厚いため不安なく働くことができました。具体的に、私が配属後一番初めに行ったのは「STRAVISを知る」事でした。GMC1ユニットではユーザー向けのeラーニングや セミ ナーを多数用意しているので、それらを受講して勉強することができます。さらに導入案件やセールス案件に参加して、実際のプロジェクトの流れや会計の知識、STRAVISの機能や操作について学ぶこともしました。 私のように、入社前・配属前の段階で会計やITの学習経験がない場合でも不安に感じる必要はないです。GMC1ユニットでは自分のスキルに合わせて学んでいくことができます。もし、少しでも興味を持ってくださった方はまずはISIDやSTRAVISを知ることから始めていただけると嬉しいです。 最後に 就活生の皆さんの中には私のようにIT系の専攻ではないけれどISIDに興味を持ってくださっている方もいるかと思います。 GMS 事業部GMC1ユニットでは既にITや会計に詳しいという方はもちろんですが、今はまだ興味を持ち始めた段階だという方も大歓迎です。私の働き方紹介が皆さんの将来を考える材料になればうれしいなと思います。 以下採用ページへのリンクです。興味を持ってくださった方は、ぜひご応募ください。 www.isid.co.jp 執筆: @yasuda.shiori 、レビュー: Ishizawa Kento (@kent) ( Shodo で執筆されました )
こんにちは、ISID 金融ソリューション事業部の岡崎です。今回はEpicGames社が提供する ゲームエンジン 、 UnrealEngine5 のPlugin「PixelStreaming」を使用し、WebUIからサーバー上のUE5の操作を行いました。 はじめに PixelStreamingを利用してWebUIからUEを操作するためには、UEアプリ上のBluePrintにURLクエリや JavaScript などを紐づける必要があります。 今回は、WebUIとUEアプリの連携をする為の方法について解説します。 BluePrintとは、UnrealEngineの スクリプティング システムです。 BluePrintではキーボードの入力やマウスの動きを感知し、UEアプリ上でのイベントを追加していくことができます。 全体の処理の流れとしては、以下の方法でご説明します。 WebUI上のボタンクリックで、任意の JSON をWebサーバー側に送信 UEのBluePrint側で value のキーに入った文字列を受け取る 受け取った文字列をUEアプリ上に文字列として表示させる 検証環境/ツール Unreal Engine5.1 AWS EC2 AMI Windows _Server-2022-English-Full-Base-2023.01.19 インスタンス タイプ g4dn.12xlarge EBS 250GB Chrome ver.110.0.5481.177 実施手順 1. AWS 上にEC2 インスタンス を立ち上げ、UnrealEngineを導入 2. UEプロジェクトを作成 3. UE BluePrintを作成 4. プレイヤーページのHTMLファイルを更新 5. UEアプリのパッケージング実行 1. AWS 上にEC2 インスタンス を立ち上げ、UnrealEngineを導入 金融ソリューション事業部の山下さん の記事を参考に、 AWS 上にEC2 インスタンス を立ち上げます。 ※上記記事では、AMIは「 Ubuntu 20.04 LTS」ですが、UE5.1のBluePrintエディター上の挙動がうまくいかなかったため、 「 Windows _Server-2022-English-Full-Base-2023.01.19」に変更して作業を行いました。 また、UEの挙動がとても重かったので、 インスタンス タイプも「g4dn.xlarge」から「g4dn.12xlarge」へ変更しております。 次に、UnrealEngineを導入します。 作成した Windows ServerにRDPを利用し接続してUnrealEngineを導入します。 今回は UnrealEngineの公式サイト の手順に従ってダウンロードを行いました。 2. UEプロジェクトを作成 今回の検証では「ThirdPersonTemplate」を使用してプロジェクトを作成します。 金融ソリューション事業部の山下さん の記事と同様に「PixelStreaming」の プラグイン を有効にし、 [ Always Show Touch Interface (タッチ インターフェースを常に表示) ] 設定も有効にします。 Additional Launch Parametersの設定も行います。 AudioMixer -PixelStreamingIP=localhost -PixelStreamingPort=8888 -AllowPixelStreamingCommands ※上記記事のパラメータに -AllowPixelStreamingCommands の記述を追加しています。 3. UE BluePrintを作成 UEのPixelStreaming プラグイン では、BluePrintにアクセスするための API が公開されているので、 これを利用してHTMLページで送信されるイベントをUEで受け取り、処理を走らせることができます。 まずは、 UnrealEngine公式のリファレンス を参考に、先ほど作成したプロジェクトで、BluePrintの設定をします。 ViewPort下部のContent DrawerからContentを選択し、右のスペースで右クリックを行い、BluePrintClassを作成します。 ここでParent Classは「Actor」を選択します。 作成されたBluePrintClassを選択することでBluePrintエディタに移動できます。 まずは、UEのBluePrint側でWebUIのボタンがクリックされた際、送られてくる任意の JSON から、 value のキーに入った文字列を受け取る処理を作成します。 (WebUIからボタンクリックで JSON を送る処理は後述します) PixelStreaming用のBluePrintAPIにアクセスするためには、PixelStreamingInputComponentを追加しないといけません。そのために「Add」ボタンより「Pixel Streaming Input」を選択します。 左側のComponents欄に追加された「Pixel Streaming Input」を右側のイベントグラフにドラッグしてきます。 作成された「Pixel Streaming Input」のノードの矢印から、「Bind Event to On Input Event」を選択し、ノードの作成を行います。 新規BluePrintを作成した際に自動生成される「Event BeginPlay」イベントと、先ほど作成した「Bind Event to On Input Event」をつなぎます。これにより、PixelStreamingを行っているWebUI上でのイベントをBluePrintAPIを通じて受け取ることができます。 ここでは受け取った文字列をUEアプリ上に文字列として表示させる処理を作成します。 先ほど作成した「Bind Event to On Input Event」から「Custom Event」ノードを作成します。今回は「UI Interaction」と 命名 します。 その「UI Interaction」にDescriptorにBluePrintAPIを通じてデータが送られてくるので、「Get Json String Value 」関数を使用し、 keyが「 Value 」の値を文字列として返す設定を行います。さらにそこから「Print String」関数を使用し、「UI Interaction」と連結させます。 この際「Print String」関数の設定で「Print to Screen」にチェックを入れるのを忘れないようにしてください。 これでWebUI上でボタンがクリックされた際、任意の Json を受け取り、 value のキーに入った文字列をBluePrintを通して、UEアプリ上に文字列として表示させる処理のBluePrintが完成しました。 最後にBluePrintの コンパイル と保存を忘れずに行い、BluePrintエディターを閉じます。最後にContent Drawerより、 作成したBluePrintをViewPortにドラッグして配置して、UE側の設定が完了します。 4. プレイヤーページのHTMLファイルを更新 WebUIのボタンクリックで任意の JSON をWebサーバー側に送信するために、 プレイヤーページのHTMLでは、 JavaScript を使用してBluePrintAPIを実行する必要があるので、その処理を追加していきます。 金融ソリューション事業部の山下さん の記事を参考にしてプロジェクトを作成している場合、 SignallingServerを起動するために使用したフォルダ Samples/PixelStreaming/WebServers/SignallingWebServer 配下に Publicフォルダやscriptsフォルダを見つけることができます。 ここにPixelStreamingを行う際のWebUIに使用するHTMLファイルやJSファイルが格納されています。 Public配下のplayer.htmlがPixelStreamingで表示される静的ファイルになります。 まずはBluePrintAPIを発火させるためのボタンを作成します。 HTMLファイル内の <div id="player"></div> を下記に変更します。 <div id="player"> <button type="button" style="position:absolute; z-index:1;" onclick="execPrintString('Hello PixelStreaming');">Hello</button> </div> 次に JavaScript を追加します。 bodyタグの末尾に下記のscriptタグを追加します。 <script type="text/javascript"> function execPrintString(text) { var descriptor = { Value: text } emitUIInteraction(descriptor); } </script> この「emitUIInteraction」の引数の Json や文字列がBluePrintAPIに渡り、先ほど作成したBluePrintの「UI Interaction」のDescriptorに格納されます。 これでHTMLファイルの更新の完了です。 5. UEアプリのパッケージング実行 次にUnrealEngineで作成したプロジェクトをパッケージ化します。 コンピュータ上のフォルダを参照して、パッケージ化されたアプリを配置する場所を決めます。 パッケージ化が完了すると、指定した場所に「 windows 」フォルダが配置されます。 その「 windows 」フォルダの中の作成したexeファイルにパラメータを付与するためにショートカットを作成します。 ショートカットを作成したら、そのショートカットのプロパティを選択し、ターゲットの欄に -AudioMixer -PixelStreamingIP=localhost -PixelStreamingPort=8888 -AllowPixelStreamingCommands の記述を追加します。 これでパッケージ化の完了です。 SignallingServerを起動し、上記で作成したexeファイルのショートカットからパッケージ化したアプリを開くことができます。 実際にEC2で設定した グローバルIP をブラウザで入力することでPixelStreamingしたWebサイトに接続できます。 WebUIの左上部に作成した「Hello」のボタンが設置されており、押下することで「Hello PixelStreaming」という文字列が表示されていれば成功です! 終わりに 今回はPixelStreamingでWebUIのカスタマイズに挑戦してみました。 まだボタンを追加してみただけですが、今後WebUIに欲しい要素をWeb側とUE側どちらにも追加していくことができるようになりました。 BluePrintAPIにはWebUIからの情報をUEに反映させるだけではなく、UE側の変更をWebUIに反映させることもできるようなので、今後はそちらの調査を行ってみようと思います。 現在ISIDは web3領域のグループ横断組織 を立ち上げ、Web3および メタバース 領域のR&Dを行っております(カテゴリー「3DCG」の記事は こちら )。 もし本領域にご興味のある方や、一緒にチャレンジしていきたい方は、ぜひお気軽にご連絡ください! 私たちと同じチームで働いてくれる仲間を、是非お待ちしております! ISID採用ページ(Web3/メタバース/AI) 参考 ・ https://docs.unrealengine.com/5.1/ja/customizing-the-player-web-page-in-unreal-engine/ ・ https://docs.unrealengine.com/5.1/ja/getting-started-with-pixel-streaming-in-unreal-engine/ ・ https://zenn.dev/pate_techmemo/articles/07721136756dcc 執筆: @okazaki.wataru 、レビュー: @wakamoto.ryosuke ( Shodo で執筆されました )
こんにちは、ISID 金融ソリューション事業部の岡崎です。今回はEpicGames社が提供する ゲームエンジン 、 UnrealEngine5 のPlugin「PixelStreaming」を使用し、WebUIからサーバー上のUE5の操作を行いました。 はじめに PixelStreamingを利用してWebUIからUEを操作するためには、UEアプリ上のBluePrintにURLクエリや JavaScript などを紐づける必要があります。 今回は、WebUIとUEアプリの連携をする為の方法について解説します。 BluePrintとは、UnrealEngineの スクリプティング システムです。 BluePrintではキーボードの入力やマウスの動きを感知し、UEアプリ上でのイベントを追加していくことができます。 全体の処理の流れとしては、以下の方法でご説明します。 WebUI上のボタンクリックで、任意の JSON をWebサーバー側に送信 UEのBluePrint側で value のキーに入った文字列を受け取る 受け取った文字列をUEアプリ上に文字列として表示させる 検証環境/ツール Unreal Engine5.1 AWS EC2 AMI Windows _Server-2022-English-Full-Base-2023.01.19 インスタンス タイプ g4dn.12xlarge EBS 250GB Chrome ver.110.0.5481.177 実施手順 1. AWS 上にEC2 インスタンス を立ち上げ、UnrealEngineを導入 2. UEプロジェクトを作成 3. UE BluePrintを作成 4. プレイヤーページのHTMLファイルを更新 5. UEアプリのパッケージング実行 1. AWS 上にEC2 インスタンス を立ち上げ、UnrealEngineを導入 金融ソリューション事業部の山下さん の記事を参考に、 AWS 上にEC2 インスタンス を立ち上げます。 ※上記記事では、AMIは「 Ubuntu 20.04 LTS」ですが、UE5.1のBluePrintエディター上の挙動がうまくいかなかったため、 「 Windows _Server-2022-English-Full-Base-2023.01.19」に変更して作業を行いました。 また、UEの挙動がとても重かったので、 インスタンス タイプも「g4dn.xlarge」から「g4dn.12xlarge」へ変更しております。 次に、UnrealEngineを導入します。 作成した Windows ServerにRDPを利用し接続してUnrealEngineを導入します。 今回は UnrealEngineの公式サイト の手順に従ってダウンロードを行いました。 2. UEプロジェクトを作成 今回の検証では「ThirdPersonTemplate」を使用してプロジェクトを作成します。 金融ソリューション事業部の山下さん の記事と同様に「PixelStreaming」の プラグイン を有効にし、 [ Always Show Touch Interface (タッチ インターフェースを常に表示) ] 設定も有効にします。 Additional Launch Parametersの設定も行います。 AudioMixer -PixelStreamingIP=localhost -PixelStreamingPort=8888 -AllowPixelStreamingCommands ※上記記事のパラメータに -AllowPixelStreamingCommands の記述を追加しています。 3. UE BluePrintを作成 UEのPixelStreaming プラグイン では、BluePrintにアクセスするための API が公開されているので、 これを利用してHTMLページで送信されるイベントをUEで受け取り、処理を走らせることができます。 まずは、 UnrealEngine公式のリファレンス を参考に、先ほど作成したプロジェクトで、BluePrintの設定をします。 ViewPort下部のContent DrawerからContentを選択し、右のスペースで右クリックを行い、BluePrintClassを作成します。 ここでParent Classは「Actor」を選択します。 作成されたBluePrintClassを選択することでBluePrintエディタに移動できます。 まずは、UEのBluePrint側でWebUIのボタンがクリックされた際、送られてくる任意の JSON から、 value のキーに入った文字列を受け取る処理を作成します。 (WebUIからボタンクリックで JSON を送る処理は後述します) PixelStreaming用のBluePrintAPIにアクセスするためには、PixelStreamingInputComponentを追加しないといけません。そのために「Add」ボタンより「Pixel Streaming Input」を選択します。 左側のComponents欄に追加された「Pixel Streaming Input」を右側のイベントグラフにドラッグしてきます。 作成された「Pixel Streaming Input」のノードの矢印から、「Bind Event to On Input Event」を選択し、ノードの作成を行います。 新規BluePrintを作成した際に自動生成される「Event BeginPlay」イベントと、先ほど作成した「Bind Event to On Input Event」をつなぎます。これにより、PixelStreamingを行っているWebUI上でのイベントをBluePrintAPIを通じて受け取ることができます。 ここでは受け取った文字列をUEアプリ上に文字列として表示させる処理を作成します。 先ほど作成した「Bind Event to On Input Event」から「Custom Event」ノードを作成します。今回は「UI Interaction」と 命名 します。 その「UI Interaction」にDescriptorにBluePrintAPIを通じてデータが送られてくるので、「Get Json String Value 」関数を使用し、 keyが「 Value 」の値を文字列として返す設定を行います。さらにそこから「Print String」関数を使用し、「UI Interaction」と連結させます。 この際「Print String」関数の設定で「Print to Screen」にチェックを入れるのを忘れないようにしてください。 これでWebUI上でボタンがクリックされた際、任意の Json を受け取り、 value のキーに入った文字列をBluePrintを通して、UEアプリ上に文字列として表示させる処理のBluePrintが完成しました。 最後にBluePrintの コンパイル と保存を忘れずに行い、BluePrintエディターを閉じます。最後にContent Drawerより、 作成したBluePrintをViewPortにドラッグして配置して、UE側の設定が完了します。 4. プレイヤーページのHTMLファイルを更新 WebUIのボタンクリックで任意の JSON をWebサーバー側に送信するために、 プレイヤーページのHTMLでは、 JavaScript を使用してBluePrintAPIを実行する必要があるので、その処理を追加していきます。 金融ソリューション事業部の山下さん の記事を参考にしてプロジェクトを作成している場合、 SignallingServerを起動するために使用したフォルダ Samples/PixelStreaming/WebServers/SignallingWebServer 配下に Publicフォルダやscriptsフォルダを見つけることができます。 ここにPixelStreamingを行う際のWebUIに使用するHTMLファイルやJSファイルが格納されています。 Public配下のplayer.htmlがPixelStreamingで表示される静的ファイルになります。 まずはBluePrintAPIを発火させるためのボタンを作成します。 HTMLファイル内の <div id="player"></div> を下記に変更します。 <div id="player"> <button type="button" style="position:absolute; z-index:1;" onclick="execPrintString('Hello PixelStreaming');">Hello</button> </div> 次に JavaScript を追加します。 bodyタグの末尾に下記のscriptタグを追加します。 <script type="text/javascript"> function execPrintString(text) { var descriptor = { Value: text } emitUIInteraction(descriptor); } </script> この「emitUIInteraction」の引数の Json や文字列がBluePrintAPIに渡り、先ほど作成したBluePrintの「UI Interaction」のDescriptorに格納されます。 これでHTMLファイルの更新の完了です。 5. UEアプリのパッケージング実行 次にUnrealEngineで作成したプロジェクトをパッケージ化します。 コンピュータ上のフォルダを参照して、パッケージ化されたアプリを配置する場所を決めます。 パッケージ化が完了すると、指定した場所に「 windows 」フォルダが配置されます。 その「 windows 」フォルダの中の作成したexeファイルにパラメータを付与するためにショートカットを作成します。 ショートカットを作成したら、そのショートカットのプロパティを選択し、ターゲットの欄に -AudioMixer -PixelStreamingIP=localhost -PixelStreamingPort=8888 -AllowPixelStreamingCommands の記述を追加します。 これでパッケージ化の完了です。 SignallingServerを起動し、上記で作成したexeファイルのショートカットからパッケージ化したアプリを開くことができます。 実際にEC2で設定した グローバルIP をブラウザで入力することでPixelStreamingしたWebサイトに接続できます。 WebUIの左上部に作成した「Hello」のボタンが設置されており、押下することで「Hello PixelStreaming」という文字列が表示されていれば成功です! 終わりに 今回はPixelStreamingでWebUIのカスタマイズに挑戦してみました。 まだボタンを追加してみただけですが、今後WebUIに欲しい要素をWeb側とUE側どちらにも追加していくことができるようになりました。 BluePrintAPIにはWebUIからの情報をUEに反映させるだけではなく、UE側の変更をWebUIに反映させることもできるようなので、今後はそちらの調査を行ってみようと思います。 現在ISIDは web3領域のグループ横断組織 を立ち上げ、Web3および メタバース 領域のR&Dを行っております(カテゴリー「3DCG」の記事は こちら )。 もし本領域にご興味のある方や、一緒にチャレンジしていきたい方は、ぜひお気軽にご連絡ください! 私たちと同じチームで働いてくれる仲間を、是非お待ちしております! ISID採用ページ(Web3/メタバース/AI) 参考 ・ https://docs.unrealengine.com/5.1/ja/customizing-the-player-web-page-in-unreal-engine/ ・ https://docs.unrealengine.com/5.1/ja/getting-started-with-pixel-streaming-in-unreal-engine/ ・ https://zenn.dev/pate_techmemo/articles/07721136756dcc 執筆: @okazaki.wataru 、レビュー: @wakamoto.ryosuke ( Shodo で執筆されました )
こんにちは!金融ソリューション事業部の山下です。 本記事では、 前回の記事 に続き、StableDiffusion生成画像からUnrealEngineで使用可能なマテリアルを生成します。 今回はノードベー スプログ ラミングなど不要ですので、さくっと終わります。 実施環境/ツール 実施手順 1. Stable Diffusionでパターン画像の生成 2. Substance 3D Samplerでマテリアル化 3. Unreal Engineでマテリアル適用、レンダリング 所感 参考 実施環境/ツール OS: Windows 11 pro GPU : NVIDIA GeForce RTX 3070Ti Laptop DCC: Adobe Substance 3D Sampler 3.4.1 Game Engine: Unreal Engine 5.1.0 AI Model:Stable Diffusion 2.1 実施手順 Stable Diffusionでパターン画像の生成 Substance 3D Samplerでマテリアル化 Unreal Engine でマテリアル適用、 レンダリング 1. Stable Diffusionでパターン画像の生成 ChatGPTで生成した以下プロンプトで、パターン画像を生成しました。 beautiful pattern of traditional japanese paper, Exquisite, intricate, delicate, elegant, sophisticated, subtle, timeless, stunning, lustrous, and graceful, 8k, seamless, no dof, use of gold --- (DeepL日本語訳) 伝統的な和紙の美しい模様、精巧、複雑、繊細、エレガント、洗練、繊細、時代を超えた、見事、光沢、優美、8K、シームレス、ノードフ、金使用 Sampling Stepsは100、Resolutionは768x768です。 バッチ処理 で300枚くらい生成したものから、良さそうなものを4パターンほど選定しました。 2. Substance 3D Samplerでマテリアル化 プロジェクト新規作成後、生成画像をレイヤータブに ドラッグ&ドロップ します。 「画像からマテリアル」を選択して「読み込み」を押下します。 マテリアルが作成されます。 上記はプレビュー形式を「布」で表示しております。 ちなみに、「服」形式などのプレビューも可能です。 このままでも十分マテリアルとして使えますが、よりリアルな質感にする為、刺繍フィルターを適用します。 「アセット」>「フィルター」>「Embroidery」を追加します。 質感に刺繍フィルターが加わり、よりリアルになりました。 マテリアル画像として書き出します。 「共有」>「書き出し」>「書き出し形式...」を押下します。 ディレクト リや必要なチャンネルを指定して、「書き出し」を押下します。 無事、アウトプット ディレクト リに画像が出力されていれば、マテリアルは完成です。 3. Unreal Engine でマテリアル適用、 レンダリング Content Drawerに、マテリアル画像をimportします。 マテリアルを新規作成して、ノードを接続します。 任意のメッシュにマテリアルを適用すれば完成です。 4パターンのうち、2パターン分のマテリアルを作成してメッシュに適用しました。 以下、MovieRenderQueueで レンダリング を行い、 After Effects で動画変換した結果になります。 所感 今回、StableDiffusion生成画像からフォトリアルなマテリアルを生成しました。これまでのマテリアル制作ワークフローにおけるプロセスを飛躍的に改善できる可能性があると感じました。 一方で、現状はAIに関する一定の リテラシー が求められることも否めません(プロンプトの調整やAIモデルの選定、必要に応じたファインチューニングなど)。 まだ誰もが使える形ではツール等に組み込まれていない以上、このままの形で一般普及するイメージはつきませんが、AI x 3DCGの領域は文字通り日進月歩で進化している為、想像以上に早期にブレークスルーが起きると思われます。引き続き本領域、注目していきたいと思います! 現在ISIDは web3領域のグループ横断組織 を立ち上げ、Web3および メタバース 領域のR&Dを行っております(カテゴリー「3DCG」の記事は こちら )。 もし本領域にご興味のある方や、一緒にチャレンジしていきたい方は、ぜひお気軽にご連絡ください! 私たちと同じチームで働いてくれる仲間を、是非お待ちしております! ISID採用ページ(Web3/メタバース/AI) 参考 https://www.youtube.com/watch?v=cL_ZYdkIqBU https://shop.cgworld.jp/shopdetail/000000001040/ https://www.adobe.com/jp/products/substance3d-sampler.html 執筆: @yamashita.yuki 、レビュー: @wakamoto.ryosuke ( Shodo で執筆されました )
こんにちは!金融ソリューション事業部の山下です。 本記事では、 前回の記事 に続き、StableDiffusion生成画像からUnrealEngineで使用可能なマテリアルを生成します。 今回はノードベー スプログ ラミングなど不要ですので、さくっと終わります。 実施環境/ツール 実施手順 1. Stable Diffusionでパターン画像の生成 2. Substance 3D Samplerでマテリアル化 3. Unreal Engineでマテリアル適用、レンダリング 所感 参考 実施環境/ツール OS: Windows 11 pro GPU : NVIDIA GeForce RTX 3070Ti Laptop DCC: Adobe Substance 3D Sampler 3.4.1 Game Engine: Unreal Engine 5.1.0 AI Model:Stable Diffusion 2.1 実施手順 Stable Diffusionでパターン画像の生成 Substance 3D Samplerでマテリアル化 Unreal Engine でマテリアル適用、 レンダリング 1. Stable Diffusionでパターン画像の生成 ChatGPTで生成した以下プロンプトで、パターン画像を生成しました。 beautiful pattern of traditional japanese paper, Exquisite, intricate, delicate, elegant, sophisticated, subtle, timeless, stunning, lustrous, and graceful, 8k, seamless, no dof, use of gold --- (DeepL日本語訳) 伝統的な和紙の美しい模様、精巧、複雑、繊細、エレガント、洗練、繊細、時代を超えた、見事、光沢、優美、8K、シームレス、ノードフ、金使用 Sampling Stepsは100、Resolutionは768x768です。 バッチ処理 で300枚くらい生成したものから、良さそうなものを4パターンほど選定しました。 2. Substance 3D Samplerでマテリアル化 プロジェクト新規作成後、生成画像をレイヤータブに ドラッグ&ドロップ します。 「画像からマテリアル」を選択して「読み込み」を押下します。 マテリアルが作成されます。 上記はプレビュー形式を「布」で表示しております。 ちなみに、「服」形式などのプレビューも可能です。 このままでも十分マテリアルとして使えますが、よりリアルな質感にする為、刺繍フィルターを適用します。 「アセット」>「フィルター」>「Embroidery」を追加します。 質感に刺繍フィルターが加わり、よりリアルになりました。 マテリアル画像として書き出します。 「共有」>「書き出し」>「書き出し形式...」を押下します。 ディレクト リや必要なチャンネルを指定して、「書き出し」を押下します。 無事、アウトプット ディレクト リに画像が出力されていれば、マテリアルは完成です。 3. Unreal Engine でマテリアル適用、 レンダリング Content Drawerに、マテリアル画像をimportします。 マテリアルを新規作成して、ノードを接続します。 任意のメッシュにマテリアルを適用すれば完成です。 4パターンのうち、2パターン分のマテリアルを作成してメッシュに適用しました。 以下、MovieRenderQueueで レンダリング を行い、 After Effects で動画変換した結果になります。 所感 今回、StableDiffusion生成画像からフォトリアルなマテリアルを生成しました。これまでのマテリアル制作ワークフローにおけるプロセスを飛躍的に改善できる可能性があると感じました。 一方で、現状はAIに関する一定の リテラシー が求められることも否めません(プロンプトの調整やAIモデルの選定、必要に応じたファインチューニングなど)。 まだ誰もが使える形ではツール等に組み込まれていない以上、このままの形で一般普及するイメージはつきませんが、AI x 3DCGの領域は文字通り日進月歩で進化している為、想像以上に早期にブレークスルーが起きると思われます。引き続き本領域、注目していきたいと思います! 現在ISIDは web3領域のグループ横断組織 を立ち上げ、Web3および メタバース 領域のR&Dを行っております(カテゴリー「3DCG」の記事は こちら )。 もし本領域にご興味のある方や、一緒にチャレンジしていきたい方は、ぜひお気軽にご連絡ください! 私たちと同じチームで働いてくれる仲間を、是非お待ちしております! ISID採用ページ(Web3/メタバース/AI) 参考 https://www.youtube.com/watch?v=cL_ZYdkIqBU https://shop.cgworld.jp/shopdetail/000000001040/ https://www.adobe.com/jp/products/substance3d-sampler.html 執筆: @yamashita.yuki 、レビュー: @wakamoto.ryosuke ( Shodo で執筆されました )
こんにちは。HCM事業部5年目の尾形です。 今回は「若手による仕事の紹介」として、 理系院卒・HCM事業部 所属という立場から私の仕事についてお話しします。記事タイトルはお気に入りの小説から。風景描写が好きです。 簡単な自己紹介 ISIDではかなりレアなのですが、 博士後期 課程を修了して入社し、HCM事業部に配属されました。 入社のきっかけは、同じ研究室の先輩が先に入社しており、働きやすそうだなと思ったことでした。 最近はインクを塗りあう某 シューティングゲーム にハマっています。 一応X帯です。 「人財」管理の システム開発 真面目な話に移ります。 この記事を読んでいる人の多くは就職活動中の方かと思いますが、 HCM事業部 と聞いて何をしている部署か分かるでしょうか? 入社するまで私もよく分かっていませんでした。 HCMとは Human Capital Management の略で、日本語では人財管理 1 と言われます。どの組織にどんなスキルを持った人がいるのか、企業規模が大きくなるほど管理は難しくなります。 そんな課題を解決するため、ISIDでは自社パッケージ 2 商品である統合HCMシステム「 POSITIVE 」 3 を提供しています。HCM事業部はPOSITIVEの開発、販売、導入を行っている部署で、私はPOSITIVEの開発に携わっています。 パッケージ開発という仕事 ISIDの業態は何かと聞かれれば、おそらく SIer ということになると思います。 SIer であればお客様の要望を伺い、ニーズを満たすシステムを開発していくのが本筋ですが、HCM事業部の仕事は大きく異なります。 POSITIVEというパッケージを開発している以上、特定のお客様の要望に沿って開発するのではなく、 利用される全てのお客様にとって価値のある改善 を重ねていく必要があります。 POSITIVE製品サイトの導入事例 4 に掲載されている通り、 ANAホールディングス 株式会社様や 明治安田生命保険 相互会社様など、皆さんもよく知るであろう多くの企業様でご利用いただいています。 業種・業態にとらわれない多種多様な企業がお客様となっており、私たちの業務にも非常に大きな責任が伴います。 さらなる人財活用に向けた改善 最近ではISO30414 5 という人的資本情報開示に関する標準化も行われ、社内のみならず投資家からも人財情報活用が注目を集めています。 そんな背景の中、 どんな機能・サービスを提供すればお客様に喜んで使ってもらえるか をよく考えて今後の対応を企画することが開発者に求められています。これは既存機能の改善だけに留まらず、全く新しいア イデア を創出する必要もあるため、自由度が高いがゆえに非常に難しい課題です。しかし同時に、これはとてもやりがいのある課題でもあり、私もチームの一員として日々議論を重ねています。 これだけだと意識だけ高いふわっとした内容になってしまうので、具体的に何をやっているのか付け加えておきます。 今後対応すべき内容を決定するための顧客訪問・ ヒアリ ング(オンライン・オフラインどちらも) 人財管理をめぐる市場動向調査(各種資料を基にした調査や、チーム内でのディスカッション) お客様に影響する法改正への対応 先に挙げたような大きな課題もありますが、他にも直近で対応すべき課題もあります。 POSITIVEは人財情報の管理だけでなく、 給与計算、就業管理 の機能も備えています 6 。 特に給与計算においては、 社会保険 や税制など、毎年のように法制度が改正されるため、その対応が必要になります。 これは特に緊急性が高く、お客様が円滑に業務を遂行するために迅速かつ確実な対応が求められます。 この対応に際し、具体的には以下のような業務にあたっています。 各種開発作業(システム設計、実装、テスト。全てやることもあれば一部担当することもあります。) 開発作業のプロジェクト管理(人員・スケジュール調整、開発体制の運用見直し) 一日のスケジュール 一日のスケジュールとしてはこんな感じです。 9:30始業、主にテレワークでの業務のため、やや夜型な生活になっています。 あくまで一例ですので、日によっては私用のため早く切り上げたり、もう少し遅い時間まで仕事を進めることもあります。 研究も仕事に活かせる 私の大学院時代の研究テーマは無線通信でした。 お察しの通り、当時の研究内容と今の業務内容は全く関係ありません。 しかしながら、研究活動を通して得たスキルは今の業務に大きく活きていると実感しています。 相手に伝えるスキル 研究成果は学会発表や論文という形で外部に公開しますが、自分の研究内容を他者に伝えるのはとても難しいことです。 それでもエッセンスを理解してもらうために、皆さんも伝え方には特に気を配り、苦心していると思います。 伝える内容が異なるだけで、 伝え方を考えるプロセスは業務でも日常的に発生します 。 うまく伝わらないことに起因する ディスコミュニケーション は業務に大きな支障をきたしますので、このスキルは一見地味ですが非常に重要です。 論理的思考力 ビジネス書でも良く見る単語ですが、研究活動では必須スキルです。 会社に入ってから研修をわざわざ受けて身に付けることも多いスキルを、 研究活動では当たり前のように使っている わけです。 問題は何か、原因は何か、改善すべきポイントはどこか。 こういったことを考え続ける点も、研究と仕事に共通する点の一つと言えます。 学生のうちに勉強しておいた方がいいこと よく「大学生のうちに勉強しておいた方がいいことは?」と聞かれますが、ビジネス系の知識は入社後からでも十分身に付けられます。 大学に通う期間は(院進学等もろもろ込みでも)10年もないと思います。 一方、会社に入ってから過ごす期間は会社が変わったとしても40年以上あるでしょう。 勉強に励むのはもちろんですが、友人と楽しく過ごす・趣味に没頭する・新しいことに挑戦するなど、今しかできないことに注力してもらえればと個人的には思います。 趣味でやっていたことが仕事の思わぬところで役に立つ 、なんてこともあります。 某ゲームでは、味方に気を配り自分のブキができる最大限のサポートをすることが非常に重要です。仕事でも同様に、周囲の状況を見つつ、自分の長所を活かしたサポートをすることがチームの KO勝ち プロジェクト成功につながります。 最後に ISIDは新卒入社者への教育・サポート体制が手厚く、働き始めるうえで不自由のないよう会社が尽力してくれています。 少しでも興味が湧いたら、是非新卒採用サイトも覗いてみてください。 www.isid.co.jp 執筆: @ogata 、レビュー: Ishizawa Kento (@kent) ( Shodo で執筆されました ) 近年ではヒトを資源(Resource)から資本(Capital)として捉える潮流があり、「人材」よりも「人財」という表現を使うことも多いです。 ↩ パッケージ商品とは、お店で売っているような既製品のことです。とはいえPOSITIVEは家電量販店等で販売しているわけではなく、お客様から問い合わせをいただいて個別に販売・導入を行っています。 ↩ POSITIVE紹介サイト(ISID): https://www.isid.co.jp/positive/ ↩ POSITIVE紹介サイト(ISID)-導入企業一覧: https://www.isid.co.jp/positive/case/ ↩ ISO30414(ISO): https://www.iso.org/standard/69338.html ↩ グループ展開されている大企業様向けに人事・給与・就業を一括で管理できるシステムを提供していることは、POSITIVEの強みの一つです。 ↩
こんにちは。HCM事業部5年目の尾形です。 今回は「若手による仕事の紹介」として、 理系院卒・HCM事業部 所属という立場から私の仕事についてお話しします。記事タイトルはお気に入りの小説から。風景描写が好きです。 簡単な自己紹介 ISIDではかなりレアなのですが、 博士後期 課程を修了して入社し、HCM事業部に配属されました。 入社のきっかけは、同じ研究室の先輩が先に入社しており、働きやすそうだなと思ったことでした。 最近はインクを塗りあう某 シューティングゲーム にハマっています。 一応X帯です。 「人財」管理の システム開発 真面目な話に移ります。 この記事を読んでいる人の多くは就職活動中の方かと思いますが、 HCM事業部 と聞いて何をしている部署か分かるでしょうか? 入社するまで私もよく分かっていませんでした。 HCMとは Human Capital Management の略で、日本語では人財管理 1 と言われます。どの組織にどんなスキルを持った人がいるのか、企業規模が大きくなるほど管理は難しくなります。 そんな課題を解決するため、ISIDでは自社パッケージ 2 商品である統合HCMシステム「 POSITIVE 」 3 を提供しています。HCM事業部はPOSITIVEの開発、販売、導入を行っている部署で、私はPOSITIVEの開発に携わっています。 パッケージ開発という仕事 ISIDの業態は何かと聞かれれば、おそらく SIer ということになると思います。 SIer であればお客様の要望を伺い、ニーズを満たすシステムを開発していくのが本筋ですが、HCM事業部の仕事は大きく異なります。 POSITIVEというパッケージを開発している以上、特定のお客様の要望に沿って開発するのではなく、 利用される全てのお客様にとって価値のある改善 を重ねていく必要があります。 POSITIVE製品サイトの導入事例 4 に掲載されている通り、 ANAホールディングス 株式会社様や 明治安田生命保険 相互会社様など、皆さんもよく知るであろう多くの企業様でご利用いただいています。 業種・業態にとらわれない多種多様な企業がお客様となっており、私たちの業務にも非常に大きな責任が伴います。 さらなる人財活用に向けた改善 最近ではISO30414 5 という人的資本情報開示に関する標準化も行われ、社内のみならず投資家からも人財情報活用が注目を集めています。 そんな背景の中、 どんな機能・サービスを提供すればお客様に喜んで使ってもらえるか をよく考えて今後の対応を企画することが開発者に求められています。これは既存機能の改善だけに留まらず、全く新しいア イデア を創出する必要もあるため、自由度が高いがゆえに非常に難しい課題です。しかし同時に、これはとてもやりがいのある課題でもあり、私もチームの一員として日々議論を重ねています。 これだけだと意識だけ高いふわっとした内容になってしまうので、具体的に何をやっているのか付け加えておきます。 今後対応すべき内容を決定するための顧客訪問・ ヒアリ ング(オンライン・オフラインどちらも) 人財管理をめぐる市場動向調査(各種資料を基にした調査や、チーム内でのディスカッション) お客様に影響する法改正への対応 先に挙げたような大きな課題もありますが、他にも直近で対応すべき課題もあります。 POSITIVEは人財情報の管理だけでなく、 給与計算、就業管理 の機能も備えています 6 。 特に給与計算においては、 社会保険 や税制など、毎年のように法制度が改正されるため、その対応が必要になります。 これは特に緊急性が高く、お客様が円滑に業務を遂行するために迅速かつ確実な対応が求められます。 この対応に際し、具体的には以下のような業務にあたっています。 各種開発作業(システム設計、実装、テスト。全てやることもあれば一部担当することもあります。) 開発作業のプロジェクト管理(人員・スケジュール調整、開発体制の運用見直し) 一日のスケジュール 一日のスケジュールとしてはこんな感じです。 9:30始業、主にテレワークでの業務のため、やや夜型な生活になっています。 あくまで一例ですので、日によっては私用のため早く切り上げたり、もう少し遅い時間まで仕事を進めることもあります。 研究も仕事に活かせる 私の大学院時代の研究テーマは無線通信でした。 お察しの通り、当時の研究内容と今の業務内容は全く関係ありません。 しかしながら、研究活動を通して得たスキルは今の業務に大きく活きていると実感しています。 相手に伝えるスキル 研究成果は学会発表や論文という形で外部に公開しますが、自分の研究内容を他者に伝えるのはとても難しいことです。 それでもエッセンスを理解してもらうために、皆さんも伝え方には特に気を配り、苦心していると思います。 伝える内容が異なるだけで、 伝え方を考えるプロセスは業務でも日常的に発生します 。 うまく伝わらないことに起因する ディスコミュニケーション は業務に大きな支障をきたしますので、このスキルは一見地味ですが非常に重要です。 論理的思考力 ビジネス書でも良く見る単語ですが、研究活動では必須スキルです。 会社に入ってから研修をわざわざ受けて身に付けることも多いスキルを、 研究活動では当たり前のように使っている わけです。 問題は何か、原因は何か、改善すべきポイントはどこか。 こういったことを考え続ける点も、研究と仕事に共通する点の一つと言えます。 学生のうちに勉強しておいた方がいいこと よく「大学生のうちに勉強しておいた方がいいことは?」と聞かれますが、ビジネス系の知識は入社後からでも十分身に付けられます。 大学に通う期間は(院進学等もろもろ込みでも)10年もないと思います。 一方、会社に入ってから過ごす期間は会社が変わったとしても40年以上あるでしょう。 勉強に励むのはもちろんですが、友人と楽しく過ごす・趣味に没頭する・新しいことに挑戦するなど、今しかできないことに注力してもらえればと個人的には思います。 趣味でやっていたことが仕事の思わぬところで役に立つ 、なんてこともあります。 某ゲームでは、味方に気を配り自分のブキができる最大限のサポートをすることが非常に重要です。仕事でも同様に、周囲の状況を見つつ、自分の長所を活かしたサポートをすることがチームの KO勝ち プロジェクト成功につながります。 最後に ISIDは新卒入社者への教育・サポート体制が手厚く、働き始めるうえで不自由のないよう会社が尽力してくれています。 少しでも興味が湧いたら、是非新卒採用サイトも覗いてみてください。 www.isid.co.jp 執筆: @ogata 、レビュー: Ishizawa Kento (@kent) ( Shodo で執筆されました ) 近年ではヒトを資源(Resource)から資本(Capital)として捉える潮流があり、「人材」よりも「人財」という表現を使うことも多いです。 ↩ パッケージ商品とは、お店で売っているような既製品のことです。とはいえPOSITIVEは家電量販店等で販売しているわけではなく、お客様から問い合わせをいただいて個別に販売・導入を行っています。 ↩ POSITIVE紹介サイト(ISID): https://www.isid.co.jp/positive/ ↩ POSITIVE紹介サイト(ISID)-導入企業一覧: https://www.isid.co.jp/positive/case/ ↩ ISO30414(ISO): https://www.iso.org/standard/69338.html ↩ グループ展開されている大企業様向けに人事・給与・就業を一括で管理できるシステムを提供していることは、POSITIVEの強みの一つです。 ↩
こんにちは!金融ソリューション事業部の山下です。 本記事では、画像生成AIのStableDiffusionとデプスマップ推定AIのBoostingMonocularDepthを用いて、上記のように板を押し出し加工したような(擬似)3Dモデル生成方法を紹介します。 3Dの モデリング および レンダリング は Houdini を使用します。 実施環境/ツール 実施手順 1. Stable Diffusion web UIのインストール 2. tex2imgで画像生成 3. BoostingMonocularDepthでデプスマップ生成 4. 生成画像をデプスマップを用いて3D化 完成イメージ 所感 参考 実施環境/ツール OS: Windows 11 pro GPU : NVIDIA GeForce RTX 3070Ti Laptop DCC:Houdini Indie version 19.5.493 Stable Diffusion 2.1 実施手順 Stable Diffusion web UIのインストール tex2imgで画像生成 BoostingMonocularDepthでデプスマップ生成 Houdiniで生成画像をデプスマップを用いて3D化 1. Stable Diffusion web UIのインストール 画像生成の為に、StableDiffusionの動作環境を構築します。 手順については XI本部三浦さんの記事 や オープンイノベーションラボ比嘉さんの記事 にて既に解説記事がありますので、こちらをご確認ください。 今回の記事では、ローカル環境にStable Diffusion web UI(AUTOMATIC1111)、Stable Diffusion 2.1をインストールしました。 2. tex2imgで画像生成 StableDiffusionに、以下のプロンプトを入力して画像を生成しました。 The marble woman bust statue stood in the center of the room. white marble surface gleaming in the soft light. The woman's face was finely carved. delicate features and a serene expression. Her eyes were closed, as if in peaceful contemplation. her lips were slightly curved in a faint smile. Her hair was styled in a series of curls that cascaded down her shoulders and back. the statue exuded a sense of grace and beauty, making it a true work of art. (DeepL日本語訳) 大理石の女性胸像が部屋の中央に立っていた。 白い大理石の表面が柔らかい光に照らされて光っている。その女性の顔には繊細な彫刻が施されている。 繊細な顔立ちで、穏やかな表情をしている。彼女の目は、まるで平和な思索に耽っているかのように閉じられている。 唇はわずかに曲がって、かすかな笑みを浮かべている。 彼女の髪は、肩から背中にかけて流れるような一連のカールをしている。 この像は、優雅さと美しさを醸し出しており、まさに芸術品と呼ぶにふさわしい。 ちなみにプロンプトはChatGPUを用いて作成しております。が、特筆すべき点はない為詳細は割愛します。 プロンプト生成方法にご興味のある方は、 イノラボ比嘉さんの一連の記事 なども参考になりますのでご覧ください。 3. BoostingMonocularDepthでデプスマップ生成 Depth生成前に、webuiのインターフェースから「stable-diffusion-webui-depthmap-script」Extensionのインストールを行います。インストールを行うと、以下のように「Depth」メニューが追加されます。 補足:執筆時、Extensionインストール時にエラーが出た為、以下 GitHub issueを立てて解決しました。 https://github.com/thygate/stable-diffusion-webui-depthmap-script/issues/55#issuecomment-1364693322 私の環境ではExtensionが依存しているライブラリ(NextViT)を手動でインストールする必要がありましたが、最新バージョンでは解決されているとのことです。 次に、2.で生成した画像をインプットして「Generate」ボタンを押下します。 手順4.の3Dモデル化の際に マッピング をする為、「Match input size」のチェックをONにします。 精度を高める為に「BOOST(multi-resolution merging)」のチェックONは推奨です。 参考論文: http://yaksoy.github.io/highresdepth/ 生成されたデプスマップです。 4. 生成画像をデプスマップを用いて3D化 いよいよ2.の生成画像と3.のデプスマップを用いて、 Houdini で3D化を行います。 今回作成したノードの全体像はこちらです。 Houdiniではこのように、ノードベースでプロシージャルに処理を行っていきます。 割とシンプルな処理ですが、一つずつ解説していきます(数字は上から数えたノード順)。 まず最初に、Gridノードでベースとなる板を作成します。 Primitive Typeは「Polygon」、押し出しの解像度を合わせる為にRows/Columnsは512とします。 26万2144ポリゴンの板が作成されました。 UV ProjectノードでUVを設定します。 レンダリング 時にマテリアルを設定する際に必要になります。 パラメータはデフォルトのままで大丈夫です。 Attribute from Mapノードで、デプスマップ情報を適用します。 「Texture Map」に画像パス、「Export Attribute」に任意の名称(今回は「depth」)を設定して、データ型を「Float」に変更します。 Geometry Spreadsheetを確認すると、各Pointのデータに列「depth」が追加され、float値が格納されています。 Attribute Blur ノードで、デプスマップ情報を滑らかにします。 Attributesに「depth」を設定します。他のパラメータはお好みですが、Blurring iterationsは10、Step Sizeは0.5を設定します。 Attribute from Mapノードで、生成画像のデータを読み込みます。 「Export Attribute」には「Cd」を設定します。 Attribute VOPノードで、各Pointに対してdepthを掛け合わせてGridを押し出します。 インプットから位置情報Pのベクトルを分解してZ軸を抽出した上で、bindノードから取得したdepth情報をsubtractしています。 後から押し出し加減をコン トロール する為、depthデータ取得後にrampノードを挟んでいます。 デフォルトだと押し出しが強すぎた為、以下のようにB-Spline補完を用いてrampを設定しました。 depthの値による押し出しができました。 Group Createノードで、外縁のPointを「sides」という名称でグループ化します。 Include by EdgesをEnable、「Unshared Edges」をONにします。 Attribute Createノードで、各Pointの法線ベクトルNをZ軸+方向に設定します。 PolyExtrudeノードで、「sides」グループのみ法線ベクトルN方向に押し出します。 Normalノードで、法線ベクトルNを元に戻しておきます。 Nullノードで「OUT」という名称をつけて、3D化は完成です。 完成イメージ Soraris Karmaで レンダリング した結果がこちらです。 今回は Solaris Karmaで レンダリング を行いました。ノードの最終系は以下になります。 作成した3DモデルをSOP importで読み込み、マテリアルを設定した後、ライティングとカメラ設定を行い、Karma XPUで レンダリング を行いました。記事が長くなってしまうので、今回は レンダリング 部分の詳細説明は割愛します。 所感 今回は複数の技術(ChatGPU、画像生成AI、進度推定AI)を組み合わせました。Houdiniを使うと3Dの細かいデータやパラメータを確認しながらプロシージャルに試行錯誤ができ、非常に強力なツールです。 Project Titan のように、Houdiniは ゲームエンジン との連携も進んでいる為、今後も様々な検証を行っていきたいと思います。 また、最近のAIの進歩には目覚ましいものがあり、特にマテリアル生成の領域では実用レベルの域に達していますので、こちらも別記事で紹介していきたいと思います! 現在ISIDは web3領域のグループ横断組織 を立ち上げ、Web3および メタバース 領域のR&Dを行っております(カテゴリー「3DCG」の記事は こちら )。 もし本領域にご興味のある方や、一緒にチャレンジしていきたい方は、ぜひお気軽にご連絡ください! 私たちと同じチームで働いてくれる仲間を、是非お待ちしております! ISID採用ページ(Web3/メタバース/AI) 参考 https://github.com/AUTOMATIC1111/stable-diffusion-webui https://github.com/thygate/stable-diffusion-webui-depthmap-script https://github.com/compphoto/BoostingMonocularDepth https://entagma.com/stable-diffusion-2-0-quickstart/ 執筆: @yamashita.yuki 、レビュー: @wakamoto.ryosuke ( Shodo で執筆されました )
こんにちは!金融ソリューション事業部の山下です。 本記事では、画像生成AIのStableDiffusionとデプスマップ推定AIのBoostingMonocularDepthを用いて、上記のように板を押し出し加工したような(擬似)3Dモデル生成方法を紹介します。 3Dの モデリング および レンダリング は Houdini を使用します。 実施環境/ツール 実施手順 1. Stable Diffusion web UIのインストール 2. tex2imgで画像生成 3. BoostingMonocularDepthでデプスマップ生成 4. 生成画像をデプスマップを用いて3D化 完成イメージ 所感 参考 実施環境/ツール OS: Windows 11 pro GPU : NVIDIA GeForce RTX 3070Ti Laptop DCC:Houdini Indie version 19.5.493 Stable Diffusion 2.1 実施手順 Stable Diffusion web UIのインストール tex2imgで画像生成 BoostingMonocularDepthでデプスマップ生成 Houdiniで生成画像をデプスマップを用いて3D化 1. Stable Diffusion web UIのインストール 画像生成の為に、StableDiffusionの動作環境を構築します。 手順については XI本部三浦さんの記事 や オープンイノベーションラボ比嘉さんの記事 にて既に解説記事がありますので、こちらをご確認ください。 今回の記事では、ローカル環境にStable Diffusion web UI(AUTOMATIC1111)、Stable Diffusion 2.1をインストールしました。 2. tex2imgで画像生成 StableDiffusionに、以下のプロンプトを入力して画像を生成しました。 The marble woman bust statue stood in the center of the room. white marble surface gleaming in the soft light. The woman's face was finely carved. delicate features and a serene expression. Her eyes were closed, as if in peaceful contemplation. her lips were slightly curved in a faint smile. Her hair was styled in a series of curls that cascaded down her shoulders and back. the statue exuded a sense of grace and beauty, making it a true work of art. (DeepL日本語訳) 大理石の女性胸像が部屋の中央に立っていた。 白い大理石の表面が柔らかい光に照らされて光っている。その女性の顔には繊細な彫刻が施されている。 繊細な顔立ちで、穏やかな表情をしている。彼女の目は、まるで平和な思索に耽っているかのように閉じられている。 唇はわずかに曲がって、かすかな笑みを浮かべている。 彼女の髪は、肩から背中にかけて流れるような一連のカールをしている。 この像は、優雅さと美しさを醸し出しており、まさに芸術品と呼ぶにふさわしい。 ちなみにプロンプトはChatGPUを用いて作成しております。が、特筆すべき点はない為詳細は割愛します。 プロンプト生成方法にご興味のある方は、 イノラボ比嘉さんの一連の記事 なども参考になりますのでご覧ください。 3. BoostingMonocularDepthでデプスマップ生成 Depth生成前に、webuiのインターフェースから「stable-diffusion-webui-depthmap-script」Extensionのインストールを行います。インストールを行うと、以下のように「Depth」メニューが追加されます。 補足:執筆時、Extensionインストール時にエラーが出た為、以下 GitHub issueを立てて解決しました。 https://github.com/thygate/stable-diffusion-webui-depthmap-script/issues/55#issuecomment-1364693322 私の環境ではExtensionが依存しているライブラリ(NextViT)を手動でインストールする必要がありましたが、最新バージョンでは解決されているとのことです。 次に、2.で生成した画像をインプットして「Generate」ボタンを押下します。 手順4.の3Dモデル化の際に マッピング をする為、「Match input size」のチェックをONにします。 精度を高める為に「BOOST(multi-resolution merging)」のチェックONは推奨です。 参考論文: http://yaksoy.github.io/highresdepth/ 生成されたデプスマップです。 4. 生成画像をデプスマップを用いて3D化 いよいよ2.の生成画像と3.のデプスマップを用いて、 Houdini で3D化を行います。 今回作成したノードの全体像はこちらです。 Houdiniではこのように、ノードベースでプロシージャルに処理を行っていきます。 割とシンプルな処理ですが、一つずつ解説していきます(数字は上から数えたノード順)。 まず最初に、Gridノードでベースとなる板を作成します。 Primitive Typeは「Polygon」、押し出しの解像度を合わせる為にRows/Columnsは512とします。 26万2144ポリゴンの板が作成されました。 UV ProjectノードでUVを設定します。 レンダリング 時にマテリアルを設定する際に必要になります。 パラメータはデフォルトのままで大丈夫です。 Attribute from Mapノードで、デプスマップ情報を適用します。 「Texture Map」に画像パス、「Export Attribute」に任意の名称(今回は「depth」)を設定して、データ型を「Float」に変更します。 Geometry Spreadsheetを確認すると、各Pointのデータに列「depth」が追加され、float値が格納されています。 Attribute Blur ノードで、デプスマップ情報を滑らかにします。 Attributesに「depth」を設定します。他のパラメータはお好みですが、Blurring iterationsは10、Step Sizeは0.5を設定します。 Attribute from Mapノードで、生成画像のデータを読み込みます。 「Export Attribute」には「Cd」を設定します。 Attribute VOPノードで、各Pointに対してdepthを掛け合わせてGridを押し出します。 インプットから位置情報Pのベクトルを分解してZ軸を抽出した上で、bindノードから取得したdepth情報をsubtractしています。 後から押し出し加減をコン トロール する為、depthデータ取得後にrampノードを挟んでいます。 デフォルトだと押し出しが強すぎた為、以下のようにB-Spline補完を用いてrampを設定しました。 depthの値による押し出しができました。 Group Createノードで、外縁のPointを「sides」という名称でグループ化します。 Include by EdgesをEnable、「Unshared Edges」をONにします。 Attribute Createノードで、各Pointの法線ベクトルNをZ軸+方向に設定します。 PolyExtrudeノードで、「sides」グループのみ法線ベクトルN方向に押し出します。 Normalノードで、法線ベクトルNを元に戻しておきます。 Nullノードで「OUT」という名称をつけて、3D化は完成です。 完成イメージ Soraris Karmaで レンダリング した結果がこちらです。 今回は Solaris Karmaで レンダリング を行いました。ノードの最終系は以下になります。 作成した3DモデルをSOP importで読み込み、マテリアルを設定した後、ライティングとカメラ設定を行い、Karma XPUで レンダリング を行いました。記事が長くなってしまうので、今回は レンダリング 部分の詳細説明は割愛します。 所感 今回は複数の技術(ChatGPU、画像生成AI、進度推定AI)を組み合わせました。Houdiniを使うと3Dの細かいデータやパラメータを確認しながらプロシージャルに試行錯誤ができ、非常に強力なツールです。 Project Titan のように、Houdiniは ゲームエンジン との連携も進んでいる為、今後も様々な検証を行っていきたいと思います。 また、最近のAIの進歩には目覚ましいものがあり、特にマテリアル生成の領域では実用レベルの域に達していますので、こちらも別記事で紹介していきたいと思います! 現在ISIDは web3領域のグループ横断組織 を立ち上げ、Web3および メタバース 領域のR&Dを行っております(カテゴリー「3DCG」の記事は こちら )。 もし本領域にご興味のある方や、一緒にチャレンジしていきたい方は、ぜひお気軽にご連絡ください! 私たちと同じチームで働いてくれる仲間を、是非お待ちしております! ISID採用ページ(Web3/メタバース/AI) 参考 https://github.com/AUTOMATIC1111/stable-diffusion-webui https://github.com/thygate/stable-diffusion-webui-depthmap-script https://github.com/compphoto/BoostingMonocularDepth https://entagma.com/stable-diffusion-2-0-quickstart/ 執筆: @yamashita.yuki 、レビュー: @wakamoto.ryosuke ( Shodo で執筆されました )
こんにちは、XI 本部ソフトウェアデザインセンター所属・新卒 1 年目の松本です。 昨年10月に配属されてから 3 ヶ月間、Atlassian Forge を使った アプリ開発 を担当しました。 そこで今回は、Forge の概要と実際の開発手順を解説していきます。 Forge に関する日本語記事はほとんどなく心細い想いをしたので、本記事が誰かの助けになれば幸いです。 Forge とは UI 構築手法 2 パターン UI kit Custom UI 開発手順の例 到達目標 執筆者の環境 ① Node.js の導入 ② Forge CLI の導入 ③ プロジェクトの作成 ④ ビルド・デプロイ・インストール ⑤ TypeScript への対応 ⑥ Atlassian REST API と UI kit フックを使い、必要な情報を取得してみる ⑦ 取得した値を表示する ⑧ 編集内容を提出できるようにする 開発を便利にする Tips UI kit を使ってみた感想 おわりに Forge とは Atlassian 社が提供する FaaS プラットフォームです。Atlassian のサービスをカスタマイズ・機能拡張するためのアプリを、ユーザー自身で簡単に作成できます。現在は、Jira、Jira Service Management、Confluence の3つのサービスに対応しており、作成したアプリはこれらのサービス上から利用することとなります。 アプリの例としては、 Jira の課題パネルから多言語翻訳を使えるようにするアプリ Jira の課題の健全性を、更新の滞りなどの情報をもとに判断してくれるアプリ Confluence に、 Google フォトに保存されている写真を表示できるようにするアプリ などが公式ドキュメントで紹介されています。 https://developer.atlassian.com/platform/forge/example-apps/ アプリ開発 に伴う機能実装以外の作業(ビルド・デプロイ・権限の管理・スケーリング・テナント管理などなど)は Atlassian 側でほとんど担ってくれるため、開発者は実現したい機能の実装に注力できます。 UI 構築手法 2 パターン アプリの UI 構築手法が 2 パターン用意されており、いずれかを選ぶ必要があります。 迅速・簡便な UI kit と 自由度が高い Custom UI です。 UI kit 提供された コンポーネント を組み合わせて UI を構築します。 コンポーネント は、各種入力フォーム・ボタン・テーブルなど、豊富に用意されています。いずれも コンポーネント も Atlassian 風のデザインとなっており、自分でデザインを考える手間が省けます(逆に、カスタマイズ性はほとんどありません)。 使い方は React の コンポーネント とよく似ています。また、フック機能も提供されており、こちらもほぼ React のそれです。 なお、 レンダリング は全てサーバー側で行われるため、相応の遅延が発生します。また、現状、 コンポーネント とフックは提供されたもの以外には使うことができないため、柔軟性に欠けます(Forge 開発チームの動向を見ていると、近々できるようになるかも?)。 Custom UI HTML・ CSS ・ JavaScript などの静的リソースを使用して、独自の UI を構築します。UI kit とは異なり、 レンダリング はユーザー側で行われるため、速いです(ただし、外部リソースへのアクセスはバックエンドを経由する必要がある、といったルールがあります)。 タイトルの通り、以降の開発手順では前者の UI kit を用います。Custom UI の解説はまたの機会に…。 開発手順の例 到達目標 手順の紹介に入る前に、本記事における開発の到達目標を明確にしておきます。 ここでは、Jira Service Management に「リク エス ト内容をリク エス ター自身が編集できる機能」を追加することを目標とします。 Jira Service Management とは、Jira を拡張したサービスデスク管理ツールです。Jira Service Management では現状、届いたリク エス ト(= 困っている人からの問い合わせ)の内容を管理者側から編集することはできても、リク エス ター側からはできないという制限があります。今回実装する機能は、こうした制限を解決するものです。 なお、Jira や Confluence を対象にした場合も同じような流れで開発を進められます。 完成イメージ 設置したボタンを押すと、 編集用のモーダルが開き、 編集して submit を押すと、 反映される。 執筆者の環境 主要なものだけあげておきます。 macOS Monterey 12.6 Visual Studio Code 1.74.3 node 16.17.1 Forge CLI 6.4.0 Forge API 2.7.0 React 18.2.0 それでは開発に入っていきましょう。 ① Node.js の導入 v14 以降の LTS release が必要です。入っていない場合はインストールしてください。 ② Forge CLI の導入 Forge CLI は、Forge アプリを管理するために使用する要のパッケージです。npm からインストールしてください。 npm install --save-dev @forge/cli インストール後、 API トーク ンを使用してログインする必要があります。 詳細な手順は、以下のドキュメントを参照してください。 https://developer.atlassian.com/platform/forge/getting-started/#log-in-with-an-atlassian-api-token ③ プロジェクトの作成 以下のコマンドでプロジェクトを作成します。 forge create コマンドを実行すると 3 つ質問されるので、順に答えていきます。 (1) アプリ名 好きなアプリ名をつけましょう。 (2) UIツール UI kit と Custom UI の選択です。前述の通り、今回は UI kit を選択します。 (3) モジュールのテンプレート Forge では、Jira などのサービスにアプリを組み込むための機能を「モジュール」として提供しています。作りたいアプリに適したモジュールを選択すると、そのモジュールに合わせて良い感じのテンプレートを作成してくれます。 今回は、Jira Service Management のリク エス ト閲覧画面に編集ボタンを付けたいので、「jira-service-management- portal -request-view-action」というモジュールを選択します。これは「リク エス ト閲覧画面にボタンが追加され、ボタンをクリックすると定義したアクションを走らせることができる」というモジュールです。 モジュール一覧は以下から確認できますので、作りたいアプリに合わせて選んでみてください。 https://developer.atlassian.com/platform/forge/manifest-reference/modules/ 以上3つの選択が完了すると、自動的に以下のようなプロジェクトが作成されます。 コードも少し覗いてみましょう。 // src/index.jsx import ForgeUI, { render, Text, PortalRequestViewAction, ModalDialog, useState } from '@forge/ui'; const App = () => { const [isOpen, setOpen] = useState(true); if (!isOpen) { return null; } return ( <ModalDialog header="Hello" onClose={() => setOpen(false)}> <Text>Hello world!</Text> </ModalDialog> ); }; export const run = render( <PortalRequestViewAction> <App/> </PortalRequestViewAction> ); React そっくりですね。簡単にコードの解説をしておくと… useState は UI kit が提供するフックの1つで、使い方は React の useState とほとんど同じです。 <ModalDialog> や <Text> は UI kit componets と呼ばれ、Atlssian 風デザインのパーツを提供するための コンポーネント です。 一方、<PortalRequestViewAction> は Function components と呼ばれ、アプリ作成時に選択したモジュールが提供する コンポーネント です。今回の例では、<PortalRequestViewAction> に囲まれた UI kit componets が、リク エス ト閲覧ページのボタンをクリックした際に表示されることとなります。 ④ ビルド・デプロイ・インストール ここで 1 度アプリをデプロイし、Atlassian サービス上で確認してみましょう。 アプリのルートで以下のコマンドを実行します。これ 1 つでエラーチェック・ビルド・デプロイまでを行ってくれる強力なコマンドです。 forge deploy デプロイ先は develop、staging、production の3つが用意されており、--environment (-e) オプションで指定できます (デフォルトは development)。今回は development にします。 続いて、以下のコマンドを実行し、デプロイしたアプリを自分が管理するテナントにインストールします。実行後にテナントの ドメイン を聞かれるので入力してください。 forge install これで、Atlassianのサービスからアプリを使えるようになりました。確認してみましょう。 今回は Jira Service Management のリク エス ト閲覧画面にボタンを追加するモジュールを使ったので、当該画面を見に行きます。 すると、以下のようにボタンが設置されており、 クリックするとモーダルが開いて「 Hello World !」と表示されます。 ここまで 1 ミリもコーディングをしていません。素晴らしいですね。 ⑤ TypeScript への対応 本ステップは任意ですが、UI kit では簡単に対応できるので、ぜひやっておきましょう。 以下の 4 つの作業を行います。 (1) tsconfig. json の作成 今回は以下のように設定しました。 // tsconfig.json { "compilerOptions": { "target": "es2020", "jsx": "react", "module": "commonjs", "esModuleInterop": true, "forceConsistentCasingInFileNames": true, "strict": true } } (2) ソースファイルの拡張子を変更 js(x) → ts(x) (3) TypeScript の プリプロセッサ を package. json に追加 必要な プリプロセッサ があれば追加しましょう。 ついでに、React がないと index. tsx で エラーが表示されてしまうので、react および対応する プリプロセッサ を npm からインストールするとともに、index. tsx でインポートしておきます。 // src/index.tsx import React from "react" なお、TypeScript の コンパイル は、前述した forge deploy コマンド実行時に一緒に実行してくれます。 ⑥ Atlassian REST API と UI kit フックを使い、必要な情報を取得してみる 続いて、編集に必要な情報を取得して、モーダルに表示してみます。 アプリと Atlassian サービスとのやり取りは、基本的には Atlassian が提供する REST API を介して行われます。加えて、現在閲覧しているリク エス トの ID など、UI kit のフックを介して取得する情報も一部あります。 Forgeでは、 REST API の認可は OAuth2.0 で行われており、権限を移譲されたアプリがユーザーに代わって API 呼び出しを行います。そのため、開発者は トーク ンなどの機密情報を管理する必要がなく、簡潔なコードで API を呼び出せます。 併せて、アプリにどの程度の権限(スコープ)を与えるかを、 マニフェスト ファイル (manifest.yml) に記述する必要があり、このスコープによって扱える API の範囲が決まります。 利用できる Atlassian REST API は以下から確認してください。その API に必要なスコープなどの情報も記載されています。 https://developer.atlassian.com/platform/forge/product-rest-api-reference/ 今回は、現在閲覧しているリク エス トの ID をUI kit の フック で取得し、その ID をもとに、リク エス トの設問文や問い合わせ内容を REST API で取得してみます。 現在閲覧しているページの情報は、useProductContext という UI kit フックで取得します。なお、本フックの返り値の型として ProductContext 型が提供されていますが、Jira のみに対応していて、Jira Service Management には対応していません。ですので、今回は ProductContextForJsm 型を自身で定義しています。 // src/index.tsx // ProductContextForJsm の型定義 (省略。「コード全文を見る」から確認できます。) const productContext = useProductContext() as ProductContextForJsm; const requestId = productContext.extensionContext.request.key; 次に、欲しい情報を REST API で取得します。まずは @forge/ api モジュールを npm からインストールするとともに、index. tsx でインポートします。 // src/index.tsx import api, { Route, route } from "@forge/api"; リク エス ト情報の取得には「Get customer request by id or key」という API を用います。この API を呼びだす関数を定義しましょう。 // src/index.tsx // ResponseJson の型定義 (省略。「コード全文を見る」から確認できます。) const fetchRequest = async (requestKey: string): Promise<ResponseJson> => { const response = await api .asApp() .requestJira(route`/rest/servicedeskapi/request/${requestKey}`, { headers: { Accept: "application/json", }, }); return await response.json(); }; API 呼び出しの関数は、useEffect 内で呼び出し、返り値は state に保持するのが良いでしょう。 state を追加し、 // src/index.tsx const [responseJson, setResponseJson] = useState<ResponseJson>({ requestFieldValues: [], }); useEffect 内で API を呼び出して、返り値を state にセットします。 // src/index.tsx useEffect(async () => { const responseJson = await fetchRequest(requestId); setResponseJson(responseJson); }, []); 最後に、使用する API を呼びだすために必要なスコープを、 マニフェスト ファイルに追加します。 // manifest.yml permissions: scopes: - "read:servicedesk-request" - "read:jira-work" コード全文を見る // src/index.tsx import api, { Route, route } from "@forge/api"; import ForgeUI, { render, Text, PortalRequestViewAction, ModalDialog, useState, useProductContext, useEffect, } from "@forge/ui"; import { ExtensionContext, ProductContext } from "@forge/ui/out/types"; import React from "react"; interface ProductContextForJsm extends ProductContext { extensionContext: ExtensionContextForJsm; } interface ExtensionContextForJsm extends ExtensionContext { request: { key: string }; } interface ResponseJson { requestFieldValues: Request[]; } interface Request { fieldId: string; label: string; value: string; } const App = () => { const [isOpen, setOpen] = useState(true); const [responseJson, setResponseJson] = useState<ResponseJson>({ requestFieldValues: [], }); useEffect(async () => { const responseJson = await fetchRequest(requestId); setResponseJson(responseJson); }, []); const productContext = useProductContext() as ProductContextForJsm; const requestId = productContext.extensionContext.request.key; const fetchRequest = async (requestKey: string): Promise<ResponseJson> => { const response = await api .asApp() .requestJira(route`/rest/servicedeskapi/request/${requestKey}`, { headers: { Accept: "application/json", }, }); return await response.json(); }; if (!isOpen) { return null; } return ( <ModalDialog header="Hello" onClose={() => setOpen(false)}> <Text>Hello world!</Text> </ModalDialog> ); }; export const run = render( <PortalRequestViewAction> <App /> </PortalRequestViewAction> ); ⑦ 取得した値を表示する 続いて、先ほど取得した値を画面に表示してみましょう。Jira Service Management では多様な設問タイプ(テキストボックス、 チェックボックス 、 ラジオボタン ・・・)がありますが、これら全てに対応しようとすると、本記事では収まりきりません。今回は簡易的に、リク エス トの「要約」欄のみを表示してみることにします。 これです。 Form、TextField という UI kit コンポーネント を使用するので、まずはインポートを追加します。Text コンポーネント はもう使わないので、消しておきます。 // src/index.tsx import ForgeUI, { render, PortalRequestViewAction, ModalDialog, useState, useProductContext, useEffect, Form, TextField, } from "@forge/ui"; 続いて、 REST API で受け取ったリク エス トの情報から要約欄の情報だけを抜き出し、 TextField コンポーネント に変換する関数を定義します。 // src/index.tsx const makeTextField = ( responseJson: ResponseJson ): JSX.Element | undefined => { const summary = responseJson.requestFieldValues.find( (request) => request.fieldId === "summary" ); if (!summary) { return; } return ( <TextField label={summary.label} name={summary.fieldId} defaultValue={summary.value} ></TextField> ); }; 最後に、先ほど作成した関数から返される TextField コンポーネント を Form コンポーネント で囲み、App 関数で返すようにします。現在「 Hello World 」を返している部分を変更します。 // src/index.tsx return ( <ModalDialog header="Edit" onClose={() => setOpen(false)}> <Form onSubmit={() => setOpen(false)}>{makeTextField(responseJson)}</Form> </ModalDialog> ); Form コンポーネント は onSubmit プロパティ(画面で submit ボタンが押された際に走る処理)の指定が必須ですが、一旦は、画面を閉じる処理を入れておきます。 それでは、画面で確認してみましょう、、、 の前に、アプリのスコープを変更したので、アップグレードが必要です。以下のコマンドでアップグレードを実行します。 forge install --upgrade これでアプリを利用可能になりました。 確認してみると、以下のように、要約欄の情報を取得できるようになっていると思います。 コード全文を見る // src/index.tsx import api, { Route, route } from "@forge/api"; import ForgeUI, { render, PortalRequestViewAction, ModalDialog, useState, useProductContext, useEffect, Form, TextField, } from "@forge/ui"; import { ExtensionContext, ProductContext } from "@forge/ui/out/types"; import React from "react"; interface ProductContextForJsm extends ProductContext { extensionContext: ExtensionContextForJsm; } interface ExtensionContextForJsm extends ExtensionContext { request: { key: string }; } interface ResponseJson { requestFieldValues: Request[]; } interface Request { fieldId: string; label: string; value: string; } const App = () => { const [isOpen, setOpen] = useState(true); const [responseJson, setResponseJson] = useState<ResponseJson>({ requestFieldValues: [], }); useEffect(async () => { const responseJson = await fetchRequest(requestId); setResponseJson(responseJson); }, []); const productContext = useProductContext() as ProductContextForJsm; const requestId = productContext.extensionContext.request.key; const fetchRequest = async (requestKey: string): Promise<ResponseJson> => { const response = await api .asApp() .requestJira(route`/rest/servicedeskapi/request/${requestKey}`, { headers: { Accept: "application/json", }, }); return await response.json(); }; const makeTextField = ( responseJson: ResponseJson ): JSX.Element | undefined => { const summary = responseJson.requestFieldValues.find( (request) => request.fieldId === "summary" ); if (!summary) { return; } return ( <TextField label={summary.label} name={summary.fieldId} defaultValue={summary.value} ></TextField> ); }; if (!isOpen) { return null; } return ( <ModalDialog header="Edit" onClose={() => setOpen(false)}> <Form onSubmit={() => setOpen(false)}>{makeTextField(responseJson)}</Form> </ModalDialog> ); }; export const run = render( <PortalRequestViewAction> <App /> </PortalRequestViewAction> ); ⑧ 編集内容を提出できるようにする それでは最後に、編集した内容を提出し、変更を反映できるようにします。 編集内容の確定には「Edit issue」という API を使用します。この API を呼びだす関数を作成します。この際、リク エス トボディには、submit ボタンが押された際に送られてくるデータをもとに作成した JSON を指定します。 // src/index.tsx const execEdit = async (submitted: {summary: string}) => { await api.asApp().requestJira(route`/rest/api/3/issue/${requestId}`, { method: "PUT", headers: { Accept: "application/json", "Content-Type": "application/json", }, body: `{"fields":{"summary":"${submitted["summary"]}"}}`, }); setOpen(false); }; そして、この関数を Form コンポーネント の onSubmit プロパティで指定します。 // src/index.tsx return ( <ModalDialog header="Edit" onClose={() => setOpen(false)}> <Form onSubmit={execEdit}>{makeTextField(responseJson)}</Form> </ModalDialog> ); これでOKです。 画面で確認する前に、新たに API を追加したので、書き込み権限をアプリに与えてアップグレードしましょう。 // manifest.yml permissions: scopes: - "read:servicedesk-request" - "read:jira-work" - "write:jira-work" 以上で全ての工程が完了です。実際に使ってみます。 要約欄を編集し、submit を押して…リロードすると… 反映されています! コード全文を見る // src/index.tsx import api, { Route, route } from "@forge/api"; import ForgeUI, { render, PortalRequestViewAction, ModalDialog, useState, useProductContext, useEffect, Form, TextField, } from "@forge/ui"; import { ExtensionContext, ProductContext } from "@forge/ui/out/types"; import React from "react"; interface ProductContextForJsm extends ProductContext { extensionContext: ExtensionContextForJsm; } interface ExtensionContextForJsm extends ExtensionContext { request: { key: string }; } interface ResponseJson { requestFieldValues: Request[]; } interface Request { fieldId: string; label: string; value: string; } const App = () => { const [isOpen, setOpen] = useState(true); const [responseJson, setResponseJson] = useState<ResponseJson>({ requestFieldValues: [], }); useEffect(async () => { const responseJson = await fetchRequest(requestId); setResponseJson(responseJson); }, []); const productContext = useProductContext() as ProductContextForJsm; const requestId = productContext.extensionContext.request.key; const fetchRequest = async (requestKey: string): Promise<ResponseJson> => { const response = await api .asApp() .requestJira(route`/rest/servicedeskapi/request/${requestKey}`, { headers: { Accept: "application/json", }, }); return await response.json(); }; const makeTextField = ( responseJson: ResponseJson ): JSX.Element | undefined => { const summary = responseJson.requestFieldValues.find( (request) => request.fieldId === "summary" ); if (!summary) { return; } return ( <TextField label={summary.label} name={summary.fieldId} defaultValue={summary.value} ></TextField> ); }; const execEdit = async (submitted: { summary: string }) => { await api.asApp().requestJira(route`/rest/api/3/issue/${requestId}`, { method: "PUT", headers: { Accept: "application/json", "Content-Type": "application/json", }, body: `{"fields":{"summary":"${submitted["summary"]}"}}`, }); setOpen(false); }; if (!isOpen) { return null; } return ( <ModalDialog header="Edit" onClose={() => setOpen(false)}> <Form onSubmit={execEdit}>{makeTextField(responseJson)}</Form> </ModalDialog> ); }; export const run = render( <PortalRequestViewAction> <App /> </PortalRequestViewAction> ); 開発を便利にする Tips 開発手順の紹介は以上ですが、開発を便利にする Tips も紹介しておきます。 ① ログの出し方 ログを出したい箇所に console.log("出したい内容") を入れ、 forge logs を実行することで、ログが確認できます。 いちいち上記コマンドを打つのは面倒ですが、次に紹介する Tunnel モードを組み合わせることで解消されます。 ② Tunnel モード ファイル保存時に自動的に再ビルドを実行してくれる機能です。ただし、development 環境へアプリをデプロイしている場合に限定されます。いちいち forge deploy コマンドを打つ手間が省けるほか、前述したログもリアルタイムで出してくれるため、非常に便利です。 使い方は以下を確認してください。 https://developer.atlassian.com/platform/forge/tunneling/ 注意点として、たまに、何のエラーも出ていないにもかかわらず変更が反映されない場合がありました。把握しておかないと永遠に時間を溶かすことになるので気をつけてください。 ③ モジュールの追加方法 forge create コマンドでプロジェクトを作成した直後はモジュールは1つだけですが、当然複数モジュールを扱うこともできます。 マニフェスト ファイル (manifest.yml) に追加すればOKです。以下のようなイメージ。 // manifest.yml modules: jiraServiceManagement:portalRequestViewAction: - key: module1 function: func1 title: モジュール1 jiraServiceManagement:queuePage: - key: module2 function: func2 title: モジュール2 function: - key: func1 handler: index.run1 - key: func2 handler: index.run2 表示するボタンの表記やアイコン、ボタンを押した際に最初に呼び出される関数などを変更したい場合も マニフェスト ファイルをいじります。 UI kit を使ってみた感想 本記事では UI kit を使って開発を進めてきましたが、メリット・デメリットともに強く感じたため、感想を記しておきます(おおむねコンセプト通りの感想ですが)。 メリット とにかく開発が速くて簡単です。デザインのことは何も考えなくて良いです(考える余地がないとも言う)。 コンポーネント の種類も割と豊富で、シンプルな機能を追加するだけであればあまり困らないと思います。 デメリット 想像以上に自由がききませんでした。現状だと、文字の色やサイズ、 コンポーネント 間の間隔などのちょっとしたところも変えられません。また、今回紹介した編集機能に関して言うと、フィールドに対応した コンポーネント が提供されておらず、工夫してもどうしようもない場合がありました(リッチテキストで入力する欄など)。 レンダリング 速度が遅いです。毎回バックエンドを経由しているので仕方ないのですが、入力値のバリデーションなどでは特に気になります。 機能が複雑化してくるとどうしても UI kit では物足りない場面があるため、今後は Custom UI を使用した開発にも取り組んでいきたいと思います。 おわりに 今回は、Atlassian Forge の概要と実際の開発手順を説明しました。データの取得・画面表示・登録と、基本的な動作をカバーしたつもりです。ニッチなツールではありますが、本記事が誰かのお役に立てば幸いです。 私たちは同じチームで働いてくれる仲間を探しています。今回のエントリで紹介したような仕事に興味のある方、ご応募お待ちしています。 ソリューションアーキテクト 執筆: @matsu ( Shodo で執筆されました )
こんにちは、XI 本部ソフトウェアデザインセンター所属・新卒 1 年目の松本です。 昨年10月に配属されてから 3 ヶ月間、Atlassian Forge を使った アプリ開発 を担当しました。 そこで今回は、Forge の概要と実際の開発手順を解説していきます。 Forge に関する日本語記事はほとんどなく心細い想いをしたので、本記事が誰かの助けになれば幸いです。 Forge とは UI 構築手法 2 パターン UI kit Custom UI 開発手順の例 到達目標 執筆者の環境 ① Node.js の導入 ② Forge CLI の導入 ③ プロジェクトの作成 ④ ビルド・デプロイ・インストール ⑤ TypeScript への対応 ⑥ Atlassian REST API と UI kit フックを使い、必要な情報を取得してみる ⑦ 取得した値を表示する ⑧ 編集内容を提出できるようにする 開発を便利にする Tips UI kit を使ってみた感想 おわりに Forge とは Atlassian 社が提供する FaaS プラットフォームです。Atlassian のサービスをカスタマイズ・機能拡張するためのアプリを、ユーザー自身で簡単に作成できます。現在は、Jira、Jira Service Management、Confluence の3つのサービスに対応しており、作成したアプリはこれらのサービス上から利用することとなります。 アプリの例としては、 Jira の課題パネルから多言語翻訳を使えるようにするアプリ Jira の課題の健全性を、更新の滞りなどの情報をもとに判断してくれるアプリ Confluence に、 Google フォトに保存されている写真を表示できるようにするアプリ などが公式ドキュメントで紹介されています。 https://developer.atlassian.com/platform/forge/example-apps/ アプリ開発 に伴う機能実装以外の作業(ビルド・デプロイ・権限の管理・スケーリング・テナント管理などなど)は Atlassian 側でほとんど担ってくれるため、開発者は実現したい機能の実装に注力できます。 UI 構築手法 2 パターン アプリの UI 構築手法が 2 パターン用意されており、いずれかを選ぶ必要があります。 迅速・簡便な UI kit と 自由度が高い Custom UI です。 UI kit 提供された コンポーネント を組み合わせて UI を構築します。 コンポーネント は、各種入力フォーム・ボタン・テーブルなど、豊富に用意されています。いずれも コンポーネント も Atlassian 風のデザインとなっており、自分でデザインを考える手間が省けます(逆に、カスタマイズ性はほとんどありません)。 使い方は React の コンポーネント とよく似ています。また、フック機能も提供されており、こちらもほぼ React のそれです。 なお、 レンダリング は全てサーバー側で行われるため、相応の遅延が発生します。また、現状、 コンポーネント とフックは提供されたもの以外には使うことができないため、柔軟性に欠けます(Forge 開発チームの動向を見ていると、近々できるようになるかも?)。 Custom UI HTML・ CSS ・ JavaScript などの静的リソースを使用して、独自の UI を構築します。UI kit とは異なり、 レンダリング はユーザー側で行われるため、速いです(ただし、外部リソースへのアクセスはバックエンドを経由する必要がある、といったルールがあります)。 タイトルの通り、以降の開発手順では前者の UI kit を用います。Custom UI の解説はまたの機会に…。 開発手順の例 到達目標 手順の紹介に入る前に、本記事における開発の到達目標を明確にしておきます。 ここでは、Jira Service Management に「リク エス ト内容をリク エス ター自身が編集できる機能」を追加することを目標とします。 Jira Service Management とは、Jira を拡張したサービスデスク管理ツールです。Jira Service Management では現状、届いたリク エス ト(= 困っている人からの問い合わせ)の内容を管理者側から編集することはできても、リク エス ター側からはできないという制限があります。今回実装する機能は、こうした制限を解決するものです。 なお、Jira や Confluence を対象にした場合も同じような流れで開発を進められます。 完成イメージ 設置したボタンを押すと、 編集用のモーダルが開き、 編集して submit を押すと、 反映される。 執筆者の環境 主要なものだけあげておきます。 macOS Monterey 12.6 Visual Studio Code 1.74.3 node 16.17.1 Forge CLI 6.4.0 Forge API 2.7.0 React 18.2.0 それでは開発に入っていきましょう。 ① Node.js の導入 v14 以降の LTS release が必要です。入っていない場合はインストールしてください。 ② Forge CLI の導入 Forge CLI は、Forge アプリを管理するために使用する要のパッケージです。npm からインストールしてください。 npm install --save-dev @forge/cli インストール後、 API トーク ンを使用してログインする必要があります。 詳細な手順は、以下のドキュメントを参照してください。 https://developer.atlassian.com/platform/forge/getting-started/#log-in-with-an-atlassian-api-token ③ プロジェクトの作成 以下のコマンドでプロジェクトを作成します。 forge create コマンドを実行すると 3 つ質問されるので、順に答えていきます。 (1) アプリ名 好きなアプリ名をつけましょう。 (2) UIツール UI kit と Custom UI の選択です。前述の通り、今回は UI kit を選択します。 (3) モジュールのテンプレート Forge では、Jira などのサービスにアプリを組み込むための機能を「モジュール」として提供しています。作りたいアプリに適したモジュールを選択すると、そのモジュールに合わせて良い感じのテンプレートを作成してくれます。 今回は、Jira Service Management のリク エス ト閲覧画面に編集ボタンを付けたいので、「jira-service-management- portal -request-view-action」というモジュールを選択します。これは「リク エス ト閲覧画面にボタンが追加され、ボタンをクリックすると定義したアクションを走らせることができる」というモジュールです。 モジュール一覧は以下から確認できますので、作りたいアプリに合わせて選んでみてください。 https://developer.atlassian.com/platform/forge/manifest-reference/modules/ 以上3つの選択が完了すると、自動的に以下のようなプロジェクトが作成されます。 コードも少し覗いてみましょう。 // src/index.jsx import ForgeUI, { render, Text, PortalRequestViewAction, ModalDialog, useState } from '@forge/ui'; const App = () => { const [isOpen, setOpen] = useState(true); if (!isOpen) { return null; } return ( <ModalDialog header="Hello" onClose={() => setOpen(false)}> <Text>Hello world!</Text> </ModalDialog> ); }; export const run = render( <PortalRequestViewAction> <App/> </PortalRequestViewAction> ); React そっくりですね。簡単にコードの解説をしておくと… useState は UI kit が提供するフックの1つで、使い方は React の useState とほとんど同じです。 <ModalDialog> や <Text> は UI kit componets と呼ばれ、Atlssian 風デザインのパーツを提供するための コンポーネント です。 一方、<PortalRequestViewAction> は Function components と呼ばれ、アプリ作成時に選択したモジュールが提供する コンポーネント です。今回の例では、<PortalRequestViewAction> に囲まれた UI kit componets が、リク エス ト閲覧ページのボタンをクリックした際に表示されることとなります。 ④ ビルド・デプロイ・インストール ここで 1 度アプリをデプロイし、Atlassian サービス上で確認してみましょう。 アプリのルートで以下のコマンドを実行します。これ 1 つでエラーチェック・ビルド・デプロイまでを行ってくれる強力なコマンドです。 forge deploy デプロイ先は develop、staging、production の3つが用意されており、--environment (-e) オプションで指定できます (デフォルトは development)。今回は development にします。 続いて、以下のコマンドを実行し、デプロイしたアプリを自分が管理するテナントにインストールします。実行後にテナントの ドメイン を聞かれるので入力してください。 forge install これで、Atlassianのサービスからアプリを使えるようになりました。確認してみましょう。 今回は Jira Service Management のリク エス ト閲覧画面にボタンを追加するモジュールを使ったので、当該画面を見に行きます。 すると、以下のようにボタンが設置されており、 クリックするとモーダルが開いて「 Hello World !」と表示されます。 ここまで 1 ミリもコーディングをしていません。素晴らしいですね。 ⑤ TypeScript への対応 本ステップは任意ですが、UI kit では簡単に対応できるので、ぜひやっておきましょう。 以下の 4 つの作業を行います。 (1) tsconfig. json の作成 今回は以下のように設定しました。 // tsconfig.json { "compilerOptions": { "target": "es2020", "jsx": "react", "module": "commonjs", "esModuleInterop": true, "forceConsistentCasingInFileNames": true, "strict": true } } (2) ソースファイルの拡張子を変更 js(x) → ts(x) (3) TypeScript の プリプロセッサ を package. json に追加 必要な プリプロセッサ があれば追加しましょう。 ついでに、React がないと index. tsx で エラーが表示されてしまうので、react および対応する プリプロセッサ を npm からインストールするとともに、index. tsx でインポートしておきます。 // src/index.tsx import React from "react" なお、TypeScript の コンパイル は、前述した forge deploy コマンド実行時に一緒に実行してくれます。 ⑥ Atlassian REST API と UI kit フックを使い、必要な情報を取得してみる 続いて、編集に必要な情報を取得して、モーダルに表示してみます。 アプリと Atlassian サービスとのやり取りは、基本的には Atlassian が提供する REST API を介して行われます。加えて、現在閲覧しているリク エス トの ID など、UI kit のフックを介して取得する情報も一部あります。 Forgeでは、 REST API の認可は OAuth2.0 で行われており、権限を移譲されたアプリがユーザーに代わって API 呼び出しを行います。そのため、開発者は トーク ンなどの機密情報を管理する必要がなく、簡潔なコードで API を呼び出せます。 併せて、アプリにどの程度の権限(スコープ)を与えるかを、 マニフェスト ファイル (manifest.yml) に記述する必要があり、このスコープによって扱える API の範囲が決まります。 利用できる Atlassian REST API は以下から確認してください。その API に必要なスコープなどの情報も記載されています。 https://developer.atlassian.com/platform/forge/product-rest-api-reference/ 今回は、現在閲覧しているリク エス トの ID をUI kit の フック で取得し、その ID をもとに、リク エス トの設問文や問い合わせ内容を REST API で取得してみます。 現在閲覧しているページの情報は、useProductContext という UI kit フックで取得します。なお、本フックの返り値の型として ProductContext 型が提供されていますが、Jira のみに対応していて、Jira Service Management には対応していません。ですので、今回は ProductContextForJsm 型を自身で定義しています。 // src/index.tsx // ProductContextForJsm の型定義 (省略。「コード全文を見る」から確認できます。) const productContext = useProductContext() as ProductContextForJsm; const requestId = productContext.extensionContext.request.key; 次に、欲しい情報を REST API で取得します。まずは @forge/ api モジュールを npm からインストールするとともに、index. tsx でインポートします。 // src/index.tsx import api, { Route, route } from "@forge/api"; リク エス ト情報の取得には「Get customer request by id or key」という API を用います。この API を呼びだす関数を定義しましょう。 // src/index.tsx // ResponseJson の型定義 (省略。「コード全文を見る」から確認できます。) const fetchRequest = async (requestKey: string): Promise<ResponseJson> => { const response = await api .asApp() .requestJira(route`/rest/servicedeskapi/request/${requestKey}`, { headers: { Accept: "application/json", }, }); return await response.json(); }; API 呼び出しの関数は、useEffect 内で呼び出し、返り値は state に保持するのが良いでしょう。 state を追加し、 // src/index.tsx const [responseJson, setResponseJson] = useState<ResponseJson>({ requestFieldValues: [], }); useEffect 内で API を呼び出して、返り値を state にセットします。 // src/index.tsx useEffect(async () => { const responseJson = await fetchRequest(requestId); setResponseJson(responseJson); }, []); 最後に、使用する API を呼びだすために必要なスコープを、 マニフェスト ファイルに追加します。 // manifest.yml permissions: scopes: - "read:servicedesk-request" - "read:jira-work" コード全文を見る // src/index.tsx import api, { Route, route } from "@forge/api"; import ForgeUI, { render, Text, PortalRequestViewAction, ModalDialog, useState, useProductContext, useEffect, } from "@forge/ui"; import { ExtensionContext, ProductContext } from "@forge/ui/out/types"; import React from "react"; interface ProductContextForJsm extends ProductContext { extensionContext: ExtensionContextForJsm; } interface ExtensionContextForJsm extends ExtensionContext { request: { key: string }; } interface ResponseJson { requestFieldValues: Request[]; } interface Request { fieldId: string; label: string; value: string; } const App = () => { const [isOpen, setOpen] = useState(true); const [responseJson, setResponseJson] = useState<ResponseJson>({ requestFieldValues: [], }); useEffect(async () => { const responseJson = await fetchRequest(requestId); setResponseJson(responseJson); }, []); const productContext = useProductContext() as ProductContextForJsm; const requestId = productContext.extensionContext.request.key; const fetchRequest = async (requestKey: string): Promise<ResponseJson> => { const response = await api .asApp() .requestJira(route`/rest/servicedeskapi/request/${requestKey}`, { headers: { Accept: "application/json", }, }); return await response.json(); }; if (!isOpen) { return null; } return ( <ModalDialog header="Hello" onClose={() => setOpen(false)}> <Text>Hello world!</Text> </ModalDialog> ); }; export const run = render( <PortalRequestViewAction> <App /> </PortalRequestViewAction> ); ⑦ 取得した値を表示する 続いて、先ほど取得した値を画面に表示してみましょう。Jira Service Management では多様な設問タイプ(テキストボックス、 チェックボックス 、 ラジオボタン ・・・)がありますが、これら全てに対応しようとすると、本記事では収まりきりません。今回は簡易的に、リク エス トの「要約」欄のみを表示してみることにします。 これです。 Form、TextField という UI kit コンポーネント を使用するので、まずはインポートを追加します。Text コンポーネント はもう使わないので、消しておきます。 // src/index.tsx import ForgeUI, { render, PortalRequestViewAction, ModalDialog, useState, useProductContext, useEffect, Form, TextField, } from "@forge/ui"; 続いて、 REST API で受け取ったリク エス トの情報から要約欄の情報だけを抜き出し、 TextField コンポーネント に変換する関数を定義します。 // src/index.tsx const makeTextField = ( responseJson: ResponseJson ): JSX.Element | undefined => { const summary = responseJson.requestFieldValues.find( (request) => request.fieldId === "summary" ); if (!summary) { return; } return ( <TextField label={summary.label} name={summary.fieldId} defaultValue={summary.value} ></TextField> ); }; 最後に、先ほど作成した関数から返される TextField コンポーネント を Form コンポーネント で囲み、App 関数で返すようにします。現在「 Hello World 」を返している部分を変更します。 // src/index.tsx return ( <ModalDialog header="Edit" onClose={() => setOpen(false)}> <Form onSubmit={() => setOpen(false)}>{makeTextField(responseJson)}</Form> </ModalDialog> ); Form コンポーネント は onSubmit プロパティ(画面で submit ボタンが押された際に走る処理)の指定が必須ですが、一旦は、画面を閉じる処理を入れておきます。 それでは、画面で確認してみましょう、、、 の前に、アプリのスコープを変更したので、アップグレードが必要です。以下のコマンドでアップグレードを実行します。 forge install --upgrade これでアプリを利用可能になりました。 確認してみると、以下のように、要約欄の情報を取得できるようになっていると思います。 コード全文を見る // src/index.tsx import api, { Route, route } from "@forge/api"; import ForgeUI, { render, PortalRequestViewAction, ModalDialog, useState, useProductContext, useEffect, Form, TextField, } from "@forge/ui"; import { ExtensionContext, ProductContext } from "@forge/ui/out/types"; import React from "react"; interface ProductContextForJsm extends ProductContext { extensionContext: ExtensionContextForJsm; } interface ExtensionContextForJsm extends ExtensionContext { request: { key: string }; } interface ResponseJson { requestFieldValues: Request[]; } interface Request { fieldId: string; label: string; value: string; } const App = () => { const [isOpen, setOpen] = useState(true); const [responseJson, setResponseJson] = useState<ResponseJson>({ requestFieldValues: [], }); useEffect(async () => { const responseJson = await fetchRequest(requestId); setResponseJson(responseJson); }, []); const productContext = useProductContext() as ProductContextForJsm; const requestId = productContext.extensionContext.request.key; const fetchRequest = async (requestKey: string): Promise<ResponseJson> => { const response = await api .asApp() .requestJira(route`/rest/servicedeskapi/request/${requestKey}`, { headers: { Accept: "application/json", }, }); return await response.json(); }; const makeTextField = ( responseJson: ResponseJson ): JSX.Element | undefined => { const summary = responseJson.requestFieldValues.find( (request) => request.fieldId === "summary" ); if (!summary) { return; } return ( <TextField label={summary.label} name={summary.fieldId} defaultValue={summary.value} ></TextField> ); }; if (!isOpen) { return null; } return ( <ModalDialog header="Edit" onClose={() => setOpen(false)}> <Form onSubmit={() => setOpen(false)}>{makeTextField(responseJson)}</Form> </ModalDialog> ); }; export const run = render( <PortalRequestViewAction> <App /> </PortalRequestViewAction> ); ⑧ 編集内容を提出できるようにする それでは最後に、編集した内容を提出し、変更を反映できるようにします。 編集内容の確定には「Edit issue」という API を使用します。この API を呼びだす関数を作成します。この際、リク エス トボディには、submit ボタンが押された際に送られてくるデータをもとに作成した JSON を指定します。 // src/index.tsx const execEdit = async (submitted: {summary: string}) => { await api.asApp().requestJira(route`/rest/api/3/issue/${requestId}`, { method: "PUT", headers: { Accept: "application/json", "Content-Type": "application/json", }, body: `{"fields":{"summary":"${submitted["summary"]}"}}`, }); setOpen(false); }; そして、この関数を Form コンポーネント の onSubmit プロパティで指定します。 // src/index.tsx return ( <ModalDialog header="Edit" onClose={() => setOpen(false)}> <Form onSubmit={execEdit}>{makeTextField(responseJson)}</Form> </ModalDialog> ); これでOKです。 画面で確認する前に、新たに API を追加したので、書き込み権限をアプリに与えてアップグレードしましょう。 // manifest.yml permissions: scopes: - "read:servicedesk-request" - "read:jira-work" - "write:jira-work" 以上で全ての工程が完了です。実際に使ってみます。 要約欄を編集し、submit を押して…リロードすると… 反映されています! コード全文を見る // src/index.tsx import api, { Route, route } from "@forge/api"; import ForgeUI, { render, PortalRequestViewAction, ModalDialog, useState, useProductContext, useEffect, Form, TextField, } from "@forge/ui"; import { ExtensionContext, ProductContext } from "@forge/ui/out/types"; import React from "react"; interface ProductContextForJsm extends ProductContext { extensionContext: ExtensionContextForJsm; } interface ExtensionContextForJsm extends ExtensionContext { request: { key: string }; } interface ResponseJson { requestFieldValues: Request[]; } interface Request { fieldId: string; label: string; value: string; } const App = () => { const [isOpen, setOpen] = useState(true); const [responseJson, setResponseJson] = useState<ResponseJson>({ requestFieldValues: [], }); useEffect(async () => { const responseJson = await fetchRequest(requestId); setResponseJson(responseJson); }, []); const productContext = useProductContext() as ProductContextForJsm; const requestId = productContext.extensionContext.request.key; const fetchRequest = async (requestKey: string): Promise<ResponseJson> => { const response = await api .asApp() .requestJira(route`/rest/servicedeskapi/request/${requestKey}`, { headers: { Accept: "application/json", }, }); return await response.json(); }; const makeTextField = ( responseJson: ResponseJson ): JSX.Element | undefined => { const summary = responseJson.requestFieldValues.find( (request) => request.fieldId === "summary" ); if (!summary) { return; } return ( <TextField label={summary.label} name={summary.fieldId} defaultValue={summary.value} ></TextField> ); }; const execEdit = async (submitted: { summary: string }) => { await api.asApp().requestJira(route`/rest/api/3/issue/${requestId}`, { method: "PUT", headers: { Accept: "application/json", "Content-Type": "application/json", }, body: `{"fields":{"summary":"${submitted["summary"]}"}}`, }); setOpen(false); }; if (!isOpen) { return null; } return ( <ModalDialog header="Edit" onClose={() => setOpen(false)}> <Form onSubmit={execEdit}>{makeTextField(responseJson)}</Form> </ModalDialog> ); }; export const run = render( <PortalRequestViewAction> <App /> </PortalRequestViewAction> ); 開発を便利にする Tips 開発手順の紹介は以上ですが、開発を便利にする Tips も紹介しておきます。 ① ログの出し方 ログを出したい箇所に console.log("出したい内容") を入れ、 forge logs を実行することで、ログが確認できます。 いちいち上記コマンドを打つのは面倒ですが、次に紹介する Tunnel モードを組み合わせることで解消されます。 ② Tunnel モード ファイル保存時に自動的に再ビルドを実行してくれる機能です。ただし、development 環境へアプリをデプロイしている場合に限定されます。いちいち forge deploy コマンドを打つ手間が省けるほか、前述したログもリアルタイムで出してくれるため、非常に便利です。 使い方は以下を確認してください。 https://developer.atlassian.com/platform/forge/tunneling/ 注意点として、たまに、何のエラーも出ていないにもかかわらず変更が反映されない場合がありました。把握しておかないと永遠に時間を溶かすことになるので気をつけてください。 ③ モジュールの追加方法 forge create コマンドでプロジェクトを作成した直後はモジュールは1つだけですが、当然複数モジュールを扱うこともできます。 マニフェスト ファイル (manifest.yml) に追加すればOKです。以下のようなイメージ。 // manifest.yml modules: jiraServiceManagement:portalRequestViewAction: - key: module1 function: func1 title: モジュール1 jiraServiceManagement:queuePage: - key: module2 function: func2 title: モジュール2 function: - key: func1 handler: index.run1 - key: func2 handler: index.run2 表示するボタンの表記やアイコン、ボタンを押した際に最初に呼び出される関数などを変更したい場合も マニフェスト ファイルをいじります。 UI kit を使ってみた感想 本記事では UI kit を使って開発を進めてきましたが、メリット・デメリットともに強く感じたため、感想を記しておきます(おおむねコンセプト通りの感想ですが)。 メリット とにかく開発が速くて簡単です。デザインのことは何も考えなくて良いです(考える余地がないとも言う)。 コンポーネント の種類も割と豊富で、シンプルな機能を追加するだけであればあまり困らないと思います。 デメリット 想像以上に自由がききませんでした。現状だと、文字の色やサイズ、 コンポーネント 間の間隔などのちょっとしたところも変えられません。また、今回紹介した編集機能に関して言うと、フィールドに対応した コンポーネント が提供されておらず、工夫してもどうしようもない場合がありました(リッチテキストで入力する欄など)。 レンダリング 速度が遅いです。毎回バックエンドを経由しているので仕方ないのですが、入力値のバリデーションなどでは特に気になります。 機能が複雑化してくるとどうしても UI kit では物足りない場面があるため、今後は Custom UI を使用した開発にも取り組んでいきたいと思います。 おわりに 今回は、Atlassian Forge の概要と実際の開発手順を説明しました。データの取得・画面表示・登録と、基本的な動作をカバーしたつもりです。ニッチなツールではありますが、本記事が誰かのお役に立てば幸いです。 私たちは同じチームで働いてくれる仲間を探しています。今回のエントリで紹介したような仕事に興味のある方、ご応募お待ちしています。 ソリューションアーキテクト 執筆: @matsu ( Shodo で執筆されました )
こんにちは!金融ソリューション事業部の山下です。 本記事では、 オープンソース の3DCGソフト Blender を用いて、現実の地形や建物を模した3DCGモデルを生成する方法を紹介します。 今回は Blender GIS という プラグイン を用いて、衛星画像、建物データ( OSM )、標高データ(SRTM)を利用してモデルを制作しました。 実施環境/ツール 実施手順 1. BlenderにBlenderGISプラグインをインストールする 2. 衛星画像データを取得する 3. 標高データ(SRTM)の取得、反映 4. 建物、その他データ(OSM)の取得、反映 5. 建物上部へテクスチャをマッピング 6. 建物側面へのマテリアルの適用 完成イメージ 所感 参考 実施環境/ツール OS: Windows 11 pro GPU : NVIDIA GeForce RTX 3070Ti Laptop DCC: Blender 3.3.1 Plugin: Blender GIS 2.2.8 実施手順 Blender にBlenderGIS プラグイン をインストールする 衛星画像データを取得する 標高データ(SRTM)の取得、反映 建物、その他データ( OSM )の取得、反映 建物上部へテクスチャを マッピング 建物側面へのマテリアルの適用 1. Blender にBlenderGIS プラグイン をインストールする 以下の GitHub リポジトリ をダウンロードします。 Blender   GIS プラグイン https://github.com/domlysz/BlenderGIS プラグイン のインストールは、メニューのEdit > Preferences > Add-onsを選択して、ダウンロードしたZIPファイルを読み込むことで完了します。完了後、Add onの一覧にBlenderGISが追加され、チェックがつきます。 2. 衛星画像データを取得する BlenderGIS プラグイン をインストールすると、以下のように3D viewport内に「 GIS 」というメニューが表示されます。 GIS > Web geodata > Basemapを選択します。 設定はそのままで、OKを押下します。 世界地図が表示されます。 Gボタン押下で検索バーが表示されるので、表示させたい地名で検索します。 今回は「Shinagawa Station」、Zoom Levelは「16」と入力します。 品川駅周辺の地図が表示されました。 Eボタン押下で、Basemapの2D画像がExportできます。 3. 標高データ(SRTM)の取得、反映 2D画像を選択した状態で、 GIS > Web geodata > Get SRTMを選択します。 ちなみにSRTMはShuttle Radar Topography Missionの略で、 スペースシャトル に搭載したレーダーで取得した地球の標高データです。 取得にはopnetopography.orgの API Keyが必要になります。以下のサイトから API keyが無料で取得可能です。 https://portal.opentopography.org/ API Keyを入力してOKボタンを押下。 先ほどの2D画像にSRTMの標高データが反映されます。 起伏には乏しい地域ですが、高輪のグ ランドプリンス ホテル周辺や御殿山周辺は比較的標高が高いことが分かります。 4. 建物、その他データ( OSM )の取得、反映 2D画像を選択した状態で、 GIS > Web geodata > Get OSM を選択します。 ちなみに OSM は OpenStreetMap の略で、 オープンソース で運営されている地図データのプロジェクトです。 取得するデータ種類を選択します。今回は全て選択します。 また、手順3.で標高データの マッピング を行っている為、Elevation from objectのチェックをONにします。 OKボタンを押下すると、建物データや線路データなどが反映されます。 5. 建物上部へテクスチャを マッピング 4.で取得した建物データ(Areas;building)を選択した状態で、Tabキー押下でEditModeに切り替えます。 ModeをFace Selectに変更します。 どれか一つの建物上部の面を選択した状態で、Select > Select Similar > Normalにより、同じ向きの面を全て選択します。 建物上部の面が選択されている状態 次に、Edit Modeから、UV Editor Modeに切り替えます。 上部メニューから、 マッピング させる画像(EXPORT_ GOOGLE _SAT_WM)を選択します。 選択した面と、画像が一致するように、位置を修正します。 Gボタン + マウスカーソルで移動、Sボタン+マウスカーソルでスケールの調整が可能です。 ランドマークとなる建物にフォーカスすると調整しやすいです。 位置が決まったら、マテリアルを設定します。 まず、3D View右下のMaterial Propertyメニューを選択して、+ボタンでマテリアルを作成します。 今回は、2つのマテリアルスロットを作成しました(「Material 001」と「roof」)。 Assignボタン押下で、Edit Modeで選択している面に、これらのマテリアルを適用します。 roofマテリアルを選択した状態で、UV Editor ModeからShader Editor Modeに切り替えます。 Shift + Aで検索バーを出して、Image Textureノードを追加します。 インプットイメージに、先ほどUV Editorで マッピング させた画像(EXPORT_ GOOGLE _SAT_WM)を選択して、ColorをPrincipled BSDFノードのBase Colorに接続します。 建物上部の面に、衛星画像が マッピング されました。 6. 建物側面へのマテリアルの適用 続いて、建物側面のマテリアルを作成します。 建物側面のテクスチャは衛星データやオープンデータで提供されていないので、一般的なビルに近しいテクスチャを使用します。 以下のテクスチャを使用します(フリーアカウントでも商用フリーの画像がダウンロード可能です)。 Size MのAlbedo, Height, Normal, Roughness, Metalic, AO, Emissiveの7種類の画像をダウンロードします。 https://www.textures.com/download/PBR0537/138572 先ほど作成したマテリアル(Material 001)を選択した状態で、UV Editingメニューを開きます。 Principle BSDFを選択した状態で、Ctrl + Shift + Tを押下します。 Blender File Viewが表示されるので、先ほどダウンロードした画像を全て選択して、「Principled Texture Setup」を押下します。 建物の側面にもマテリアルが適用されました。 完成イメージ 完成イメージはこちらです。夜景にしてみました。 本記事ではライティング、 レンダリング のプロセスは割愛します。 所感 今回は GIS を用いてビル群を作成しました。 ハイクオリティなビルを作成するアプローチは他にも色々とありますが、 GIS を使うと大規模な都市や地形がほぼ一瞬で生成できる為、高精細なクオリティが不要な遠景等で用いる分には有用だと感じました。また、山など起伏のある地形のモデルを制作する場合は 国土地理院 地図などもう少し正確な標高データの活用も有用だと思います。 現在ISIDは web3領域のグループ横断組織 を立ち上げ、Web3および メタバース 領域のR&Dを行っております(カテゴリー「3DCG」の記事は こちら )。 もし本領域にご興味のある方や、一緒にチャレンジしていきたい方は、ぜひお気軽にご連絡ください! 私たちと同じチームで働いてくれる仲間を、是非お待ちしております! ISID採用ページ(Web3/メタバース/AI) 参考 https://www.esrij.com/gis-guide/gis-datamodel/gis-datamodel/ https://www.youtube.com/watch?v=YNtKnmRXVlo&t=283s https://www.youtube.com/watch?v=uk404c43pRY 執筆: @yamashita.yuki 、レビュー: @wakamoto.ryosuke ( Shodo で執筆されました )
こんにちは!金融ソリューション事業部の山下です。 本記事では、 オープンソース の3DCGソフト Blender を用いて、現実の地形や建物を模した3DCGモデルを生成する方法を紹介します。 今回は Blender GIS という プラグイン を用いて、衛星画像、建物データ( OSM )、標高データ(SRTM)を利用してモデルを制作しました。 実施環境/ツール 実施手順 1. BlenderにBlenderGISプラグインをインストールする 2. 衛星画像データを取得する 3. 標高データ(SRTM)の取得、反映 4. 建物、その他データ(OSM)の取得、反映 5. 建物上部へテクスチャをマッピング 6. 建物側面へのマテリアルの適用 完成イメージ 所感 参考 実施環境/ツール OS: Windows 11 pro GPU : NVIDIA GeForce RTX 3070Ti Laptop DCC: Blender 3.3.1 Plugin: Blender GIS 2.2.8 実施手順 Blender にBlenderGIS プラグイン をインストールする 衛星画像データを取得する 標高データ(SRTM)の取得、反映 建物、その他データ( OSM )の取得、反映 建物上部へテクスチャを マッピング 建物側面へのマテリアルの適用 1. Blender にBlenderGIS プラグイン をインストールする 以下の GitHub リポジトリ をダウンロードします。 Blender   GIS プラグイン https://github.com/domlysz/BlenderGIS プラグイン のインストールは、メニューのEdit > Preferences > Add-onsを選択して、ダウンロードしたZIPファイルを読み込むことで完了します。完了後、Add onの一覧にBlenderGISが追加され、チェックがつきます。 2. 衛星画像データを取得する BlenderGIS プラグイン をインストールすると、以下のように3D viewport内に「 GIS 」というメニューが表示されます。 GIS > Web geodata > Basemapを選択します。 設定はそのままで、OKを押下します。 世界地図が表示されます。 Gボタン押下で検索バーが表示されるので、表示させたい地名で検索します。 今回は「Shinagawa Station」、Zoom Levelは「16」と入力します。 品川駅周辺の地図が表示されました。 Eボタン押下で、Basemapの2D画像がExportできます。 3. 標高データ(SRTM)の取得、反映 2D画像を選択した状態で、 GIS > Web geodata > Get SRTMを選択します。 ちなみにSRTMはShuttle Radar Topography Missionの略で、 スペースシャトル に搭載したレーダーで取得した地球の標高データです。 取得にはopnetopography.orgの API Keyが必要になります。以下のサイトから API keyが無料で取得可能です。 https://portal.opentopography.org/ API Keyを入力してOKボタンを押下。 先ほどの2D画像にSRTMの標高データが反映されます。 起伏には乏しい地域ですが、高輪のグ ランドプリンス ホテル周辺や御殿山周辺は比較的標高が高いことが分かります。 4. 建物、その他データ( OSM )の取得、反映 2D画像を選択した状態で、 GIS > Web geodata > Get OSM を選択します。 ちなみに OSM は OpenStreetMap の略で、 オープンソース で運営されている地図データのプロジェクトです。 取得するデータ種類を選択します。今回は全て選択します。 また、手順3.で標高データの マッピング を行っている為、Elevation from objectのチェックをONにします。 OKボタンを押下すると、建物データや線路データなどが反映されます。 5. 建物上部へテクスチャを マッピング 4.で取得した建物データ(Areas;building)を選択した状態で、Tabキー押下でEditModeに切り替えます。 ModeをFace Selectに変更します。 どれか一つの建物上部の面を選択した状態で、Select > Select Similar > Normalにより、同じ向きの面を全て選択します。 建物上部の面が選択されている状態 次に、Edit Modeから、UV Editor Modeに切り替えます。 上部メニューから、 マッピング させる画像(EXPORT_ GOOGLE _SAT_WM)を選択します。 選択した面と、画像が一致するように、位置を修正します。 Gボタン + マウスカーソルで移動、Sボタン+マウスカーソルでスケールの調整が可能です。 ランドマークとなる建物にフォーカスすると調整しやすいです。 位置が決まったら、マテリアルを設定します。 まず、3D View右下のMaterial Propertyメニューを選択して、+ボタンでマテリアルを作成します。 今回は、2つのマテリアルスロットを作成しました(「Material 001」と「roof」)。 Assignボタン押下で、Edit Modeで選択している面に、これらのマテリアルを適用します。 roofマテリアルを選択した状態で、UV Editor ModeからShader Editor Modeに切り替えます。 Shift + Aで検索バーを出して、Image Textureノードを追加します。 インプットイメージに、先ほどUV Editorで マッピング させた画像(EXPORT_ GOOGLE _SAT_WM)を選択して、ColorをPrincipled BSDFノードのBase Colorに接続します。 建物上部の面に、衛星画像が マッピング されました。 6. 建物側面へのマテリアルの適用 続いて、建物側面のマテリアルを作成します。 建物側面のテクスチャは衛星データやオープンデータで提供されていないので、一般的なビルに近しいテクスチャを使用します。 以下のテクスチャを使用します(フリーアカウントでも商用フリーの画像がダウンロード可能です)。 Size MのAlbedo, Height, Normal, Roughness, Metalic, AO, Emissiveの7種類の画像をダウンロードします。 https://www.textures.com/download/PBR0537/138572 先ほど作成したマテリアル(Material 001)を選択した状態で、UV Editingメニューを開きます。 Principle BSDFを選択した状態で、Ctrl + Shift + Tを押下します。 Blender File Viewが表示されるので、先ほどダウンロードした画像を全て選択して、「Principled Texture Setup」を押下します。 建物の側面にもマテリアルが適用されました。 完成イメージ 完成イメージはこちらです。夜景にしてみました。 本記事ではライティング、 レンダリング のプロセスは割愛します。 所感 今回は GIS を用いてビル群を作成しました。 ハイクオリティなビルを作成するアプローチは他にも色々とありますが、 GIS を使うと大規模な都市や地形がほぼ一瞬で生成できる為、高精細なクオリティが不要な遠景等で用いる分には有用だと感じました。また、山など起伏のある地形のモデルを制作する場合は 国土地理院 地図などもう少し正確な標高データの活用も有用だと思います。 現在ISIDは web3領域のグループ横断組織 を立ち上げ、Web3および メタバース 領域のR&Dを行っております(カテゴリー「3DCG」の記事は こちら )。 もし本領域にご興味のある方や、一緒にチャレンジしていきたい方は、ぜひお気軽にご連絡ください! 私たちと同じチームで働いてくれる仲間を、是非お待ちしております! ISID採用ページ(Web3/メタバース/AI) 参考 https://www.esrij.com/gis-guide/gis-datamodel/gis-datamodel/ https://www.youtube.com/watch?v=YNtKnmRXVlo&t=283s https://www.youtube.com/watch?v=uk404c43pRY 執筆: @yamashita.yuki 、レビュー: @wakamoto.ryosuke ( Shodo で執筆されました )
こんにちは。X イノベーション 本部ソフトウェアデザインセンターの陳です。 この記事ではNext.jsの getServerSideProps の利用でハマったことについて話します。 Server-side Rendering( SSR )とgetServerSideProps Server-side Renderingはリク エス トごとにサーバー側で レンダリング を行い、HTMLページを生成する機能です。 頻繁に変更されるデータを画面に表示させたい時はServer-side Renderingを利用します。Server-side Renderingを実現するには、サーバー側からデータを受け取る処理を行う getServerSideProps 関数を使います。 Next.jsの 公式ドキュメント では以下の例を掲載しています。 function Page({ data }) { // Render data... } // This gets called on every request export async function getServerSideProps() { // Fetch data from external API const res = await fetch(`https://.../data`) const data = await res.json() // Pass data to the page via props return { props: { data } } } export default Page Blue/Greenデプロイでハマったこと 今回はNext.jsの API routes を使ってバックエンド処理の API を作成しました。 例えば、以下はデータベースからarticle名のリストを取得する処理を行う API routeです。 // pages/api/articles.ts export default function handler(_req: NextApiRequest, res: NextApiResponse) { const articles: Article[] = await getArticlesFromDB(); const articleNames = articles.map((article) => article.name ); res.status(200).json(articleNames); } getServerSideProps で API からデータを受け取って ブラウザー に渡します。Axiosの baseURL を 環境変数 で指定していました。 // pages/index.tsx function Page({ articleNames }) { // Render articles data... } export async function getServerSideProps() { const baseURL = process.env.SERVER ? process.env.SERVER : "http://localhost:3000"; const res = await Axios.get<string[]>(`{baseURL}/api/articles`) return { props: { articleNames: res.data } } } export default Page このコードは一見問題なさそうですが、Blue/GreenデプロイでAxiosの baseURL を正しく指定しないと問題が起きます(Fetch API を利用する場合も同様です)。 Blue/Greenデプロイは、本番環境と検証環境を交互に入れ替えることにより、ダウンタイムを最小にするデプロイ手法です。 本来であれば、 API のパスはウェブサーバーと同一環境のものにならないといけません。例えば、本番環境のパスは https://example.com であれば、 API のパスは https://example.com/api/articles になります。 今回はAxiosのbaseURLを本番環境のパスに指定しましたため、検証環境ウェブサーバーにアクセスしても、叩いた API は本番環境のものでした。 Blue/Greenデプロイはルーティング制御により、本番環境と検証環境の入れ替えが行われるため、 API のホスト名も環境と共に切り替える必要があります。 アクセスした環境は本番環境か検証環境かを識別し、 API のパスを変換する仕組みが必要ですが、なかなか難しいです。 解決方法 そもそも getServerSideProps と API routes は両方ともサーバー側で実行されるため、 getServerSideProps で API routes を呼びだすのは蛇足ですね。データの取得などのバックエンド処理は関数で作成し、 getServerSideProps で呼び出せばいいです。 修正後のコードはこちらです。 API routesの作成をやめて、データベースの処理を関数にしました。 // logic/articles.ts export async function fetchArticleNames(): Promise<string[]> { const articles: Article[] = await getArticlesFromDB(); return articles.map((article) => article.name ); } 続いて、 getServerSideProps で api/articles を介さずに、 fetchArticleNames() 関数でarticle名のリストを取得するように修正しました。 // pages/index.tsx function Page({ articleNames }) { // Render article names... } export async function getServerSideProps() { const articleNames = await fetchArticleNames(); return { props: { articleNames } } } export default Page これで、Blue/Greenデプロイの API パス問題を回避し、コードもすっきりしました。 まとめ この記事では、Next.jsの getServerSideProps を使ってBlue/Greenデプロイでハマったことについてまとめました。 getServerSideProps はサーバー側で実行されますので、データの取得処理は API routes を介さずに関数で呼び出しましょう。 私たちは同じチームで働いてくれる仲間を探しています。今回のエントリで紹介したような仕事に興味のある方、ご応募お待ちしています。 - ソリューションアーキテクト 執筆: @chen.xinying 、レビュー: @sato.taichi ( Shodo で執筆されました )
こんにちは。X イノベーション 本部ソフトウェアデザインセンターの陳です。 この記事ではNext.jsの getServerSideProps の利用でハマったことについて話します。 Server-side Rendering( SSR )とgetServerSideProps Server-side Renderingはリク エス トごとにサーバー側で レンダリング を行い、HTMLページを生成する機能です。 頻繁に変更されるデータを画面に表示させたい時はServer-side Renderingを利用します。Server-side Renderingを実現するには、サーバー側からデータを受け取る処理を行う getServerSideProps 関数を使います。 Next.jsの 公式ドキュメント では以下の例を掲載しています。 function Page({ data }) { // Render data... } // This gets called on every request export async function getServerSideProps() { // Fetch data from external API const res = await fetch(`https://.../data`) const data = await res.json() // Pass data to the page via props return { props: { data } } } export default Page Blue/Greenデプロイでハマったこと 今回はNext.jsの API routes を使ってバックエンド処理の API を作成しました。 例えば、以下はデータベースからarticle名のリストを取得する処理を行う API routeです。 // pages/api/articles.ts export default function handler(_req: NextApiRequest, res: NextApiResponse) { const articles: Article[] = await getArticlesFromDB(); const articleNames = articles.map((article) => article.name ); res.status(200).json(articleNames); } getServerSideProps で API からデータを受け取って ブラウザー に渡します。Axiosの baseURL を 環境変数 で指定していました。 // pages/index.tsx function Page({ articleNames }) { // Render articles data... } export async function getServerSideProps() { const baseURL = process.env.SERVER ? process.env.SERVER : "http://localhost:3000"; const res = await Axios.get<string[]>(`{baseURL}/api/articles`) return { props: { articleNames: res.data } } } export default Page このコードは一見問題なさそうですが、Blue/GreenデプロイでAxiosの baseURL を正しく指定しないと問題が起きます(Fetch API を利用する場合も同様です)。 Blue/Greenデプロイは、本番環境と検証環境を交互に入れ替えることにより、ダウンタイムを最小にするデプロイ手法です。 本来であれば、 API のパスはウェブサーバーと同一環境のものにならないといけません。例えば、本番環境のパスは https://example.com であれば、 API のパスは https://example.com/api/articles になります。 今回はAxiosのbaseURLを本番環境のパスに指定しましたため、検証環境ウェブサーバーにアクセスしても、叩いた API は本番環境のものでした。 Blue/Greenデプロイはルーティング制御により、本番環境と検証環境の入れ替えが行われるため、 API のホスト名も環境と共に切り替える必要があります。 アクセスした環境は本番環境か検証環境かを識別し、 API のパスを変換する仕組みが必要ですが、なかなか難しいです。 解決方法 そもそも getServerSideProps と API routes は両方ともサーバー側で実行されるため、 getServerSideProps で API routes を呼びだすのは蛇足ですね。データの取得などのバックエンド処理は関数で作成し、 getServerSideProps で呼び出せばいいです。 修正後のコードはこちらです。 API routesの作成をやめて、データベースの処理を関数にしました。 // logic/articles.ts export async function fetchArticleNames(): Promise<string[]> { const articles: Article[] = await getArticlesFromDB(); return articles.map((article) => article.name ); } 続いて、 getServerSideProps で api/articles を介さずに、 fetchArticleNames() 関数でarticle名のリストを取得するように修正しました。 // pages/index.tsx function Page({ articleNames }) { // Render article names... } export async function getServerSideProps() { const articleNames = await fetchArticleNames(); return { props: { articleNames } } } export default Page これで、Blue/Greenデプロイの API パス問題を回避し、コードもすっきりしました。 まとめ この記事では、Next.jsの getServerSideProps を使ってBlue/Greenデプロイでハマったことについてまとめました。 getServerSideProps はサーバー側で実行されますので、データの取得処理は API routes を介さずに関数で呼び出しましょう。 私たちは同じチームで働いてくれる仲間を探しています。今回のエントリで紹介したような仕事に興味のある方、ご応募お待ちしています。 - ソリューションアーキテクト 執筆: @chen.xinying 、レビュー: @sato.taichi ( Shodo で執筆されました )
皆さん、こんにちは。イノラボ小林です。 今回の記事では1月3日~1月8日にラスベガスで開催されたCES2023について取材をしてきたので、その中でも気になったクイックインタビューを数点紹介させて頂きます。 尚、その他の動画については、下記リンクから飛んでいただけるとまとめて視聴可能です。 https://www.tiktok.com/@tyoreporter 名称:CES®(世界最大級のテックイベント) 主催:Consumer Technology Association ( CTA ) 日程:Media Days:2023.1.3 – 4 ( 2日間 )    CES2023 :2023.1.5 – 8 ( 4日間 ) ■ マイクロソフト (カテゴリー:XR) Hololens2を活用した展示解説ツアー @tyoreporter #ces2023 #ces #AR #HoloLens #マイクロソフト ♬ オリジナル楽曲 - TYO-REPORTER ■ BMW (カテゴリー:モビリティ) 32色に変色する車体パネル @tyoreporter #ces2023 #ces #車 #bmw ♬ オリジナル楽曲 - TYO-REPORTER ■ ARHT(カテゴリー:コミュニケーション) リアルタイムで1/1を映し出す遠隔コミュニケーションディスプレイ @tyoreporter #ディスプレイ #メタバース #デジタルツイン #サイネージ #ces #ces2023 #マーケティング ♬ オリジナル楽曲 - TYO-REPORTER PPT資料(PDF)もあるので、閲覧/配布希望の方はご連絡下さい。 連絡先:kobayashi.kentaro@isid.co.jp 執筆: @tyoreporter 、レビュー: @sato.taichi ( Shodo で執筆されました )