cvl-robot's diary

研究ノート メモメモ https://github.com/dotchang/

メモ:ur_rtdeに独自関数を追加したいときの方法

URロボットの通信用インターフェースの一つであるRTDEでは、urscriptやその入出力の変数を自前で定義して、呼び出してやる必要があります。URは、入出力のデータの並びの定義をrecipeと呼んでいます。わかってしまえば、たいして難しくないものの、その仕組みはちょっとヤヤコシイので、ur_rtdeに自前の関数を追加したいときのメモを残しておくことにします。

編集する必要があるファイルは、
1. rtde_control.script
2. rtde.h
3. rtde_control.h
4. rtde_control.cpp
です。
rtde_control.scriptにはURScript形式で記述したロボットコマンドを追加します。
rtde.hには、RobotCommandのTypeとRecipeの定義を追加します。
rtde_control.hには、自前スクリプトの呼び出し関数の定義を追加し、rtde_control.cppには、自前スクリプトの呼び出し関数の定義を記述します。入力変数と、出力変数の受け取りも記述します。
定義や関数を追加した後に、cmakeからur_rtdeの再ビルドを行います。

is_within_safety_limits()をコマンド33に追加するときの例

rtde_control.script

    def process_cmd():
        cmd = read_input_integer_register(0)

        if cmd == 1:
            textmsg("movej")
            q = [0, 0, 0, 0, 0, 0]
            q[0] = read_input_float_register(0)

~中略~

        elif cmd == 33:
            textmsg("is_within_safety_limits")
            x = p[0, 0, 0, 0, 0, 0]
            x[0] = read_input_float_register(0)
            x[1] = read_input_float_register(1)
            x[2] = read_input_float_register(2)
            x[3] = read_input_float_register(3)
            x[4] = read_input_float_register(4)
            x[5] = read_input_float_register(5)
            
            val = is_within_safety_limits(x)
            if val == False:
                        write_output_integer_register(1, 0)
            else:
                        write_output_integer_register(1, 1)
            end
            textmsg("is_within_safety_limits done")
        elif cmd == 255:
            textmsg("Received stop!")
        end

        return cmd != 255
    end

rtde.h

  class RobotCommand
  {
   public:
    enum Type
    {
      NO_CMD = 0,

~中略~

      GET_INVERSE_KINEMATICS = 31,
      PROTECTIVE_STOP = 32,
      IS_WITHIN_SAFETY_LIMITS = 33, ///// added
      STOP = 255
    };

    enum Recipe
    {
      RECIPE_1 = 1,

~中略~

      RECIPE_11 = 11,
      RECIPE_12 = 12 ///// added
    };

rtde_control.h

~前略~

  RTDE_EXPORT std::vector<double> getInverseKinematics(const std::vector<double> &x, const std::vector<double> &qnear,
      double max_position_error=1e-10, double max_orientation_error=1e-10);

  RTDE_EXPORT int getIsWithinSafetyLimits(const std::vector<double> &x); ///// added

  /**
    * @brief Triggers a protective stop on the robot. Can be used for testing and debugging.
    */
  RTDE_EXPORT bool triggerProtectiveStop();

~中略~
  private:
    int getIsWithinSafetyLimitsValue(); ///// added

~後略~

rtde_control.cpp

RTDEControlInterface::RTDEControlInterface(std::string hostname, int port) : hostname_(std::move(hostname)), port_(port)
{
 ~前略~

  // Setup input recipes

  ~中略~

  // Recipe_12
  std::vector<std::string> is_within_safety_limits_input = {
      "input_int_register_0",    "input_double_register_0", "input_double_register_1", "input_double_register_2",
      "input_double_register_3", "input_double_register_4", "input_double_register_5"};
  rtde_->sendInputSetup(is_within_safety_limits_input);

 ~後略~
  }
}


bool RTDEControlInterface::reconnect()
{
~前略~

  // Setup input recipes
  // Recipe 1

~中略~

  // Recipe_12
  std::vector<std::string> is_within_safety_limits_input = {
      "input_int_register_0",    "input_double_register_0", "input_double_register_1", "input_double_register_2",
      "input_double_register_3", "input_double_register_4", "input_double_register_5"};
  rtde_->sendInputSetup(is_within_safety_limits_input);

  // Init Robot state
 ~後略~
}

int RTDEControlInterface::getIsWithinSafetyLimitsValue()
{
  if (robot_state_ != nullptr)
  {
    return robot_state_->getOutput_int_register_1();
  }
  else
  {
    throw std::logic_error("Please initialize the RobotState, before using it!");
  }
}

int RTDEControlInterface::getIsWithinSafetyLimits(const std::vector<double> &x)
{
  RTDE::RobotCommand robot_cmd;
  robot_cmd.type_ = RTDE::RobotCommand::Type::IS_WITHIN_SAFETY_LIMITS;
  robot_cmd.recipe_id_ = RTDE::RobotCommand::Recipe::RECIPE_12;
  robot_cmd.val_ = x;
  if (sendCommand(robot_cmd))
  {
    return getIsWithinSafetyLimitsValue();
  }
  else
  {
    return -1;
  }
}

double型のベクターを渡したいだけなのに、頭に "input_int_register_0" がついているのは、ベクターの大きさを暗黙のうちに渡すような仕組みになっているからです。明示的には渡しません。

実行例

#include <ur_rtde/rtde_control_interface.h>
#include <thread>
#include <chrono>
#include <iostream>

using namespace ur_rtde;

int main(int argc, char* argv[])
{
  RTDEControlInterface rtde_control("192.168.0.1");

  // int movec_mode = 0;
  std::vector<double> tcp_pose1 = {-0.143, -0.435, 0.20, -0.001, 3.12, 0.04};
  std::vector<double> tcp_pose2 = {-0.143, -0.51, 0.21, -0.001, 3.12, 0.04};
  std::vector<double> tcp_pose3 = {0.4, 0.4, 10.0, 0.0, 3.14159, 0.0};

  //rtde_control.getInverseKinematics();
  std::cout << "getIsWithinSafetyLimits" << std::endl;
  bool result;
  result = rtde_control.getIsWithinSafetyLimits(tcp_pose1);
  std::cout << result << std::endl;
  result = rtde_control.getIsWithinSafetyLimits(tcp_pose2);
  std::cout << result << std::endl;
  result = rtde_control.getIsWithinSafetyLimits(tcp_pose3);
  std::cout << result << std::endl;

  return 0;
}

今日の本文

大きなテレビが安い。

今なら同じSONYの4kチューナーを買って、ソニーに申請すると3万円返ってくる。実質4Kチューナーをタダでもらえたうえで300円得する計算になります。

www.sony.jp

メモ:onRobot社のRG2GripperをURスクリプトを使って、ur_rtdeから動かしたいときのスクリプトのサンプル

ロボットアームUR5eに取り付けたonRobot社RG2グリッパーを、URScriptを使って、自前のc++プログラムから操作するときのサンプルを紹介します。

UR5eの駆動方法

UR5eを動かすための方法は、URScriptを使う(port 30000~30002)か、RTDE(Real-Time Data Exchange, port 30004)[0]を使うかに分かれます。
ROSIndustrialなどは中でURScriptを叩いているそうですが、URScriptの応答は速くなくロボットハードウェアの性能を全て引き出すことは難しいです。
ロボットの性能を引き出すために、RTDE経由でコマンドを送る方が良く、そこに着目した幾つかのグループでRTDEをラップして便利に使いやすくするライブラリの開発[1][2][3]が進められています。
一方で、onRobotのRG2はRTDEではなく、URScriptから呼び出す必要が有ります。
ここでは、開発が現在進行形で進んでいるソースコードがきれいなur_rtdeを使って、そこからURScriptを呼び出す方法を試してみたいと思います。

onRobot社のマニュアルによれば、簡単にURScriptからRG2関数を呼べるようになるのでは?

RG2関数がURScriptにロードされるのは、PolyScope内だけです。外部から呼び出すことはできません。
onRobot社のマニュアルに不備があります。

ur_rtdeのScriptClient

ur_rtdeはいくつかのコンポーネントから構成されており、RTDEReceiveInterface、RTDEControlInterface、RTDEIOInterface、ScriptClientなどがあります。
うまく使えばRTDEIOInterfaceを使ってRG2グリッパーを動かすことができるかもしれませんが、まだノウハウの蓄積がないのでわかりません。
ここでは、ScriptClientを使ってURScriptを流し込む方法で動かしてみたいと思います。

ソースコードのサンプル

ファイルに書いたスクリプトを読み込む方法と、平書きしたstringを渡す方法の2つがあります。
URScriptでは、scriptの中のタブとか改行コードとかがシビアに影響します。デバッグもし辛いので慎重に確認してください。
実機を動作させるときには、電源をOnにして、polyscopeのタブレットからリモートコントロールができるように設定しておく必要がありますので、忘れないでください。

ofApp.h

#pragma once

#include "ofMain.h"

#include <ur_rtde/rtde_receive_interface.h>
#include <ur_rtde/rtde_control_interface.h>
#include <ur_rtde/script_client.h>

class ofApp : public ofBaseApp{

	public:
		void setup();
		void update();
		void draw();

		void RG2(int width, int force);

		std::shared_ptr<ur_rtde::RTDEReceiveInterface> rtde_receive;
		std::shared_ptr<ur_rtde::RTDEControlInterface> rtde_control;
		std::shared_ptr<ur_rtde::ScriptClient> script_client;
};

ofApp.cpp

#include "ofApp.h"
#pragma comment(lib, "rtde.lib")

//--------------------------------------------------------------
void ofApp::setup(){
	script_client = std::make_shared<ur_rtde::ScriptClient>("192.168.1.1", 5, 5, 30002); // Polyscope ver. 5.5 port 30002

	script_client->connect();
	if (script_client->isConnected()) {
		script_client->sendScript("data/RG2.script");
		std::cout << "send command" << std::endl;
        }
}

void ofApp::update()
{
}

void ofApp::draw()
{
}

void ofApp::RG2(int width, int force)
{
	int offset_width = 9; // 9.2[mm];
	int target_width = offset_width + width;
	if (target_width > 110) target_width = 110;
	else if (target_width < 0) target_width = 0;

	if (script_client->isConnected()) {
		std::string cmd_str;
		cmd_str = "def RG2():\n";
		cmd_str += "\tdef bit(input):\n";
		cmd_str += "\t\tmsb = 65536\n";
		cmd_str += "\t\tlocal i = 0\n";
		cmd_str += "\t\tlocal output = 0\n";
		cmd_str += "\t\twhile i < 17:\n";
		cmd_str += "\t\t\tset_digital_out(8, True)\n";
		cmd_str += "\t\t\tif input >= msb :\n";
		cmd_str += "\t\t\t\tinput = input - msb\n";
		cmd_str += "\t\t\t\tset_digital_out(9, False)\n";
		cmd_str += "\t\t\telse :\n";
		cmd_str += "\t\t\t\tset_digital_out(9, True)\n";
		cmd_str += "\t\t\tend\n";
		cmd_str += "\t\t\tif get_digital_in(8):\n";
		cmd_str += "\t\t\t\toutput = 1\n";
		cmd_str += "\t\t\tend\n";
		cmd_str += "\t\t\tsync()\n";
		cmd_str += "\t\t\tset_digital_out(8, False)\n";
		cmd_str += "\t\t\tsync()\n";
		cmd_str += "\t\t\tinput = input * 2\n";
		cmd_str += "\t\t\toutput = output * 2\n";
		cmd_str += "\t\t\ti = i + 1\n";
		cmd_str += "\t\tend\n";
		cmd_str += "\t\treturn output\n";
		cmd_str += "\tend\n";
		cmd_str += "\tdef RG2(target_width = 110, target_force = 40):\n";
		cmd_str += "\t\tbit(0)\n";
		cmd_str += "\t\tsleep(0.024)\n";
		cmd_str += "\t\trg_data = floor(target_width) * 4\n";
		cmd_str += "\t\trg_data = rg_data + floor(target_force / 2) * 4 * 111\n";
		cmd_str += "\t\trg_data = rg_data + 32768\n";
		cmd_str += "\t\tbit(rg_data)\n";
		cmd_str += "\t\twhile get_digital_in(9) == True:\n";
		cmd_str += "\t\t\tsync()\n";
		cmd_str += "\t\tend\n";
		cmd_str += "\t\twhile get_digital_in(9) == False:\n";
		cmd_str += "\t\t\tsync()\n";
		cmd_str += "\t\tend\n";
		cmd_str += "\tend\n";
		cmd_str += "\tRG2(" + std::to_string(target_width) + "," + std::to_string(rg2_force) + ")\n";
		cmd_str += "end\n";
		cmd_str += "run program\n";
		script_client->sendScriptCommand(cmd_str);

		std::cout << cmd_str << std::endl;
	}
}

RG2.script

def RG2():
	def bit(input):
		msb=65536
		local i=0
		local output=0
		while i<17:
			set_digital_out(8,True)
			if input>=msb:
				input=input-msb
				set_digital_out(9,False)
			else:
				set_digital_out(9,True)
			end
			if get_digital_in(8):
				output=1
			end
			sync()
			set_digital_out(8,False)
			sync()
			input=input*2
			output=output*2
			i=i+1
		end
		return output
	end
	def RG2(target_width=110, target_force=40):
		bit(0)
		sleep(0.024)
		rg_data=floor(target_width)*4
		rg_data=rg_data+floor(target_force/2)*4*111
		rg_data=rg_data+32768
		bit(rg_data)
		while get_digital_in(9) == True:
			sync()
		end
		while get_digital_in(9) == False:
			sync()
		end
	end
	RG2(100, 40)
end
run program


References:
[0] https://www.universal-robots.com/how-tos-and-faqs/how-to/ur-how-tos/real-time-data-exchange-rtde-guide-22229/
[1] pypi.org
[2] gitlab.com
[3] github.com
[4] bitbucket.org

自分用読むべき論文メモ 2019年9月版

相変わらず忙しいふりをしています。Twitterで見かけた面白い記事まとめです。


はいどろ


こういう病院の事務は詐欺で立件されてもよい。


マニピュレーションのダイナミクス学習


量子コンピュータリンク集


MRTK非公式日本語マニュアル


Calibration一杯アルゴリズムあるけど、必要な時に欲しいものが見つからない。
Kalibr


ああ、こういうのが大好き。


論文読み方


Google機械学習学習マンガ。続編どうなったかな?



こういうのが当たり前になりつつある


年次更新


精度良いね


時間が大事


サリエンシー


Thetaの実力すごい


意味不明


量子コンピュータ関連記事。分からないけど、読む。


dopeoplesay.com
英語の言い回し検索


ゲームエンジンは必須科目になりつつある


コレ!なんでもいいから人数は多い方が良い。


ラズパイの屋外連続稼働はまだ高コストだなぁ。


LGSVLシミュレータ

www.k2.t.u-tokyo.ac.jp
Maxwellモデル制御は、勉強しなければならない。


安いなぁ


GaNは来たのに、SiCはノーベル賞来ないのかな?


姿勢が悪くても怒られない?

www.cvlibs.net
まだ通用するかな


太平洋戦争で日本がボロ負けした理由、の一つ?


大事


pythonノウハウ


人間の生物としての研究、大事。


物体検出の進歩


ロボホンの並木精密宝石サーボモータ24$

qiita.com
データの作り方だいじ。


github.com
セマンテックセグメンテーションの実装集


nerural rendererは、必須ツールになりつつある感じ?

http://www.jfssa.jp/taikai/2019/table/program_detail/pdf/1/1-100/10070.pdf
わかってないけど、読まねば。


ハンドは柔らかい方が良いよね


matlabの分類器。試してみたい。


カワイイ

shiropen.com
手とオブジェクトのモデリング


よくわからないけど、すごそうなもの。


使い捨て輸送ドローン。軍事応用が怖い。


推論理由の可視化
qiita.com
qiita.com

github.com
jetson-nano用ffmpeg。NDIは対応してないのかな?

www.slideshare.net
ICRA2019まとめ


LIO-mapping


5本指ロボット


みんな出世していてうれしい。

arxiv.org
認識の基本は言語化だと思うんだ。


お昼寝推奨

google.github.io
Googleのコードの書き方


CARLA


eng-memo.info
Yoloの改良


Yolo実装


WiFiの届く範囲のシミュレーション

ai-scholar.tech
集合を扱うネットワーク。数学


言語の違いに大した有意差はなく、大体39bits/secの情報伝達が行われる。

japanese.engadget.com
アンドロイドがもっとリアル肌になるかな?

oaktree-lab.shop-pro.jp
900度まで観測可能な低解像度サーモカメラ


ZMP歩行のSTM32F4マイコン実装

github.com
ChoreonoidでPremaid Ai


亀岡の野菜工場

謎カメラ


作り込みではなくて、どの辺が研究のキモなのか分かりやすいと良いな。


勉強の出遅れを取り戻したいときに、縋り付くための記事。


お手軽そうな溶接機。安全なら欲しい。


MagicLeapによる視線と感情の認識


キネクトなりRealsenseからなり、こういうデータを取り込んで、サクッとロボットシミュレーションに使えるようにしたい。


少ないパラメータでの物体変形、昔やりかけたままだなぁ。

phi16.hatenablog.com
こんなノウハウの塊の公開、とてもありがたい。本にしてほしい。

よくわからないけど、すごそうなもの。

自分用読むべき論文メモ 2019年8月版

主にTwitterで見かけた面白い記事まとめです。


ハンド


永守賞で見た。


組み立て作業解析


アランココーニは今何やってるんだろう


自由度多い


鉄イオン電池は重くないのかな


FPV商売?


とても結果がきれい


蚊でごまかしてるけど、兵器ですね


Jinsの面白眼鏡はいろいろ欲しい


モーターが変わるかも。


ありがたい



血圧計を使っても誤診断が多いから実用化急いでほしい。


bvhの話


Waymoの自動運転データセット


小さい会社でも罹患する危険性


ZMP


ハンドの認識


講義で使いたい


depthのカラー化


Githubの用語解説。ありがたや


みんな分かってるはずなのに忘れがち。


レンズアレイを見ると反応してしまう。


安い


データセット


ハンドのシミュレーション


量子


位置エネルギー電池


直感的に操作できるインターフェース大事


ちょっと気になる


いつものフエス


人体動作の予測


すごくよくできてる


視覚から音楽変換


早くネットワークは人が考えなくてもいいようになってほしい。


勝てない理由


ドローン


テキスト読み上げ。すごい綺麗


GR-Rose、ちょっとしたROS2開発に便利そう


Raspi 660fps


Andrew Ng先生


フーリエ


現時点で、結論、とか言われると、、、


ハンドの制御


謎の新技術。アヤシ


葡萄の認識と武道の認識


最近傍探索


地球規模の移動をGPS


便利そうではあるが、怪しげな。

自分用読むべき論文メモ 2019年7月版

Twitterで面白かった7月の記事まとめです。


カメラの高解像度化が進むから、もっと重要になるかも。

https://www.st.com/content/ccc/resource/technical/document/application_note/group1/13/fd/27/76/de/e8/46/4d/DM00566701/files/DM00566701.pdf/jcr:content/translations/en.DM00566701.pdf
1ポイントTOFセンサ100Hz


球面調和関数を用いた3次元音場再現


気になるギア内蔵モータ。


触覚大事。


新原理MEMSマイク使ってみたい。


Jetson TX2関係。でも、センサーが優秀になりつつある今、デプス復元にリソース喰われるのはどうなんだろうとは思う。


リアルタイム化凄い。


博士号持ちの凄さが分かるぐらいの教養が、政治家全員に求められる。


触覚大事。


インターフェースの多様性は欲しいので柔軟に対応してほしいけど、面白いカメラ。


Theta欲しいな。耐久モデルが特別扱いになってしまったのが悲しい。


こんなに小さいモーターが。


なんかシステムがデカくて、ロボットに使うのに便利なのかどうかよくわからん。


指さし動作の起源


CVPR2019速報


panasonicがやっている研究なのが良い。


この変速機、だれか正しく解説してくれないかな


気配の知覚のヒントになるか


振動触覚は一見退化のように見えるけど、今は主流なのかな



プリメイドAiいじりたい・・・

github.com
Virtual Gimbal凄い。


フーリエ


見た目と音楽の一致。80年代に流行?


式の実装してみた人いないかな?


光音響センサでCO2


ヒビ割れの検出

ROS2版が待たれる


このセンサの情報全然聞かないな


プロジェクションマッピング




jetson nano関係


Saliencyは今後もっと重要になると思う。


Webviz


陰除去


良い政治


応援したい日本製サーボモータ。でもトルクが足らない。。。


あらゆる事故、災害に備えておかなければならない。


意識、好奇心、気配


近い将来

自分用読むべき論文メモ 2019年6月版

しばらく論文読んでる暇がなかったので、面白かったTwitterの記事を中心に。(いつも、ほぼそうですが。。。)



研究者注目の的、タコ。


進化が明示的にコントロールされるようになったら、ますますやばい。


基本ツール


[メモ]Blue Noiseとリアルタイムレイトレーシングshikihuiku.wordpress.com


カメラキャリブレーションはとても大事。


農業ロボット関係


Choreonid関係


戦車型なのが日本での教育に向いてない。実銃やレーザーに置き換えるも簡単だろうから怖いし。


よくわかんないけど。

myenigma.hatenablog.com


低価格ってどのくらいなんですかね?



新しい情報がなかなか出てこない新型LeapMotion

NVIDIA Jetson Nanoで OpenPoseをビルドする方法、動画から人体の骨格検出 (NVIDIA Jetson Nanoの CUDAパワーで OpenPoseを使って動画から人体の骨格検出)
でべ on Twitter: "レビュー記事書きました!Jetson Nanoですが、ラズパイも少しフォローしてます。 Jetson Nano でカルマンフィルタ不要の9軸フュージョンセンサ BOSCH BNO055を使う https://t.co/6J658G3E1p"


JetsonNano関係


翻訳を期待!


BNO055では何も考えずQuaternion出力を使え、という話。


大事だと思うんです。Unityでオブジェクト置いたら終わり、じゃ意味ないもん。

todaitotexas.com
欲しい情報が何一つ手に入らない素敵なWEBページ。


展示内容は素晴らしい。

Jetson Nanoをロボットに搭載するために、リチウムポリマー6S22.2Vから5V80Wを安全に取り出せる電源を作る

Jetson Nanoは、安くて早くて便利ですが、フルスピードで動かそうとすると20Wの5V電源が必要になります。一般に、これをUSB電源からとるのは無理なので、DCDCコンバータを用意する必要があります。
一方、ロボットではモータを駆動するために、+12Vや+24Vの電源が使われることが多いです。そこで、24Vから5Vを作る電源を検討したいと思います。

この記事を参考にして事故等が起きても一切の責任を取れません。よくご検討の上自己責任でお願いいたします。

DCDCコンバータの選定

ロボットに搭載するために、できるだけ回路は物理的に小さくしたいと思います。自作でDCDCコンバータを作るとどうしても大きくなってしまいますから、素直にメーカー品を選定することにします。
www.cosel.co.jp
www.cosel.co.jp
有名メーカーのモジュールを探したところ、COSEL MGFS40/80シリーズが出力/サイズ比がもっともよさそうです。値段もそれぞれ、4000円、7000円とリーズナブルです。それぞれ、2台、4台のフルスペックJetson Nanoを動かすことができます。
難点は、現時点でどちらも在庫薄であることですが、そのうち入荷するでしょう。

低電圧検出回路の設計

大本の電源をリチウムポリマー電池から取り出すことに注意しなければなりません。リチウムポリマー電池は、過放電すると単に使えなくなるばかりか、膨らんで爆発するなどの危険性があります。そこで、終止電圧が来たらDCDCコンバータを自動的に止めるようにしなければなりません。リチウムポリマーの1セルの基準電圧は3.7V、終止電圧は3.0Vぐらいが一般的です。厳密にやるならば、各セルの電圧を監視するべきなのですが、回路規模的に大変になってしまうので、6S18Vを終止電圧としてDCDCコンバータを止めるようにしたいと思います。

ツェナーダイオードを使って基準電圧を作ります。18Vを直接比較しようとすると、もっと大きな電圧が比較回路のために必要になってしまいますので、5V程度の電源で駆動できるように適当に電圧を調整します。また、電圧を比較するのに最も手軽な方法は、OPアンプをコンパレータとして使うことだと思います。OPアンプの+入力にツェナーダイオード、-入力に抵抗で分圧したバッテリー電源電圧を入れます。

f:id:cvl-robot:20190904090105p:plain
電圧比較回路
www.falstad.com
回路の原理確認には、このWEBアプレットの回路シミュレータを使いました。電源電圧が18Vを超えるとコンパレータの出力はLowになり、18Vを切るとHighの+5Vを出力します。

部品は、手元にあった3.6Vのツェナーダイオードを使うことにします。またコンパレータには、手元に転がっていた単電源OPアンプのJRC 3414ADを使うことにしました。これは、バイポーラ型ですが消費電力の少ないFET入力の方が良いと思います。
抵抗の分圧比は、電源電圧が18Vの時に3.6Vの電圧が下の抵抗にかかるように調整します。系列の抵抗値に当てはめて、下を3.6kΩ、上を14.4k(12k+2.4k)にしました。ノイズを恐れて多めに電流を流すようにしましたが、もうちょっと少なくてもいいかもしれません。

単電源OPアンプの電源を用意するのが億劫ですが、強い味方のスーパー三端子レギュレータ+5Vが手元にあったのでこれを使うことにします。超便利なので、手元にいくつか在庫を用意しておくと良いです。
ただし、こいつは低電圧検出後も停止されず微弱ながら電流を引き続けますので、停止してしまったら速やかにバッテリーを取り外す必要があります。基準電圧用のツェナーダイオードの電源とOPアンプの電源は同じものを用いてください。
akizukidenshi.com

あとは、このコンパレータの出力電圧をCOSELのDCDCコンバータのRC端子につないでやれば良いです。
注意点として、本来は出力にヒステリシスを入れて、一度基準電圧を切ったらラッチさせてチャタリングが起きないようにするべきだと思います。クリティカルな用途に使う際はよく注意してください。

出力状態の監視出力

この5V用DCDCコンバータで低電圧検出回路が働いたら、(もし使っていれば)他の系統の電源も連携して停止するようにするべきです。出力側の5Vの電圧でフォトカプラを駆動して、入力側の電圧基準で信号を取り出せるようにしたいと思います。
フォトカプラには、京都のマルツで入手できた東芝TLP550を使うことにします。これは、何の変哲もないオープンコレクタ出力1回路の物です。
toshiba.semicon-storage.com

f:id:cvl-robot:20190904094852p:plain
フォトカプラ
わざわざ回路図にするまでもないですが、左側の電源をCOSELのDCDCコンバータの5V出力、右側の電源をスーパー三端子レギュレータの5V電源とします。負論理で動きますので、そのまま別のコーセルのDCDCコンバータのRCに入力することができます。

メインのDCDCコンバータ電源回路

COSELのデータシートに従って素直に作ります。コンデンサのESRが無いので、シミュレータはこのままでは動きません。

f:id:cvl-robot:20190904103127p:plain
全体回路図

実装

出来ました。

f:id:cvl-robot:20190904103302p:plain
5V80WのDCDCコンバータの実装
が、やらかしています。DCDCコンバータモジュールは熱を持つので、電解コンデンサーを接しさせてはイケマセン!また、ラインフィルタを入れてはいますが、多分無意味なので不要です。

今日の本文

ダイエットのために、病院でおすすめされました。