¥297,000 税込
この商品は送料無料です。
現在ご注文後2週間目処でご発送可能です。
CR Handは"本当に"人間と同等サイズの6自由度ロボットハンドです。手首取付面から指先までの距離はわずか172mmです。このコンパクトな筐体に全てのモーター・コントロールボックスが納まっており、USBケーブルと電源を接続すればすぐに動作が可能です。高精度FDM 3Dプリンタを活用することでお求めやすい価格を実現しました。教育・研究開発用途に最適です。
<主な特徴>
<製品仕様>
重量: 326g
電圧: 6V
モータ牽引力: 最大18N(1指あたり)
<内容物一覧>
CR Hand 本体
6V電源アダプタ
USB2.0ケーブル(mini-Bタイプ)
接続フランジ(協働ロボット向けISO 9409-1-50-4-M6 UR, TM等に対応)
ネジ類 M3L8 x4, M6L10 x4
<概寸・取付部寸法>
<指先着脱部寸法>
<接続フランジ>
こちらのリンクより3Dデータのダウンロードが可能です。
<セットアップ>
1.ドライバ・ソフトウェアのダウンロード
PCにPololu社のドライバとMaestro Control Centerをダウンロードして下さい。
2.ケーブル接続
ハンドとPCを付属のUSBケーブルで接続して下さい。また、ハンドに付属の6V電源アダプタを繋ぎ、コンセントに接続して下さい。
3.ソフトウェア起動
前述の1でダウンロードしたMaestro Control Centerを起動して下さい。
①プルダウンリストより接続した基板を選択して下さい(#XXXXXXXXのように数字で表示されます)。
②#0~5の全てのServoのEnableをチェックして下さい。
③スライダを左右にドラッグして6個のモーター全てが動作することを確認してください。
Maestro Control Centerは、ロボットハンドの操作や設定を直感的に行えるツールです。主な特徴は以下の通りです。
リアルタイム制御: 各モーターを個別に制御でき、スライダーをドラッグするだけでモーターの位置を調整可能です。
クロスプラットフォーム対応: WindowsおよびLinuxに対応しています。
スクリプト作成と実行: 内蔵のスクリプトエディタを使用して、簡単なスクリプトを作成・編集し、直接実行できます。これにより、動作の自動化やカスタマイズが可能です。
モーションの記録と再生: モーターの動作をシーケンスとして記録し、再生する機能があります。これにより、複雑な動作パターンを簡単に作成・編集できます。
これらの機能により、CR Handの動作を直感的かつ効率的に設定・制御できます。
4.プログラムからの操作
内蔵する制御基板Pololu Micro Maestro 6-Channel USB Servo Controllerはシリアル通信に対応しており、Pythonなどのプログラミング言語を使用してシリアル通信を行うことでCR Handを使用することが可能です。
以下にPythonとProcessingによるサンプルプログラムを掲載します。どちらの場合も、プログラム内のポート番号を適切に変更して使用してください。
ポート番号はデバイスマネージャーより"Pololu Micro Maestro 6-Servo Controller Port"の番号を確認して使用してください。下図の場合はCOM22となります。
Pythonによるサンプルプログラムの例です。実行すると下図のようなウィンドウが立ち上がります。各ボタンをクリックすることでハンドを操作することが可能です。
# cr_hand_button_controller.py
# Usage:
# python cr_hand_buttons.py
# python cr_hand_buttons.py --port COM1 --baud 9600
import sys
import argparse
import time
from typing import List, Dict
try:
import serial
from serial.tools import list_ports
except ImportError:
print("ERROR: This script requires pyserial. Install with: pip install pyserial")
sys.exit(1)
import tkinter as tk
from tkinter import ttk
# ---- Servo scenarios (Ch0..Ch5) ----
SCENARIOS: Dict[str, List[int]] = {
"Open": [4000, 4000, 4000, 4000, 4000, 4000],
"Pinch_open": [8000, 7000, 4000, 8000, 8000, 8000],
"Pinch_close": [8000, 7000, 6000, 8000, 8000, 8000],
"Grasp_open": [8000, 4000, 4000, 4000, 4000, 4000],
"Grasp_close": [8000, 6000, 8000, 8000, 8000, 8000],
"Key_Pinch_open": [4000, 4000, 8000, 8000, 8000, 8000],
"Key_Pinch_close": [4000, 8000, 8000, 8000, 8000, 8000],
}
NUM_CHANNELS = 6 # Ch0..Ch5
class MaestroController:
"""
Pololu Micro Maestro (Command Port) minimal controller.
Sends 'Set Target' (0x84) commands in quarter-microseconds.
"""
def __init__(self, port: str, baud: int = 9600, timeout: float = 1.0):
self.port_name = port
self.baud = baud
self.timeout = timeout
self.ser: serial.Serial | None = None
def open(self):
self.ser = serial.Serial(self.port_name, self.baud, timeout=self.timeout)
time.sleep(0.1)
print(f"[INFO] Connected to {self.port_name} @ {self.baud}bps")
def close(self):
if self.ser and self.ser.is_open:
self.ser.close()
print("[INFO] Serial port closed.")
def set_servo_position(self, channel: int, target: int):
if not (0 <= channel < 24):
raise ValueError("Channel out of range.")
if not (0 <= target <= 16383):
raise ValueError("Target out of range (0..16383).")
cmd = bytes([0x84, channel & 0xFF, target & 0x7F, (target >> 7) & 0x7F])
us = target * 0.25
print(f"[TX] Ch{channel}: {cmd[0]:#04x} {cmd[1]:#04x} {cmd[2]:#04x} {cmd[3]:#04x} "
f"| Target={target} ({us:.2f} µs)")
assert self.ser is not None and self.ser.is_open, "Serial port is not open."
self.ser.write(cmd)
def set_all(self, positions: List[int]):
if len(positions) < NUM_CHANNELS:
raise ValueError(f"positions must have {NUM_CHANNELS} values.")
for ch in range(NUM_CHANNELS):
self.set_servo_position(ch, positions[ch])
def list_available_ports() -> List[str]:
try:
return [p.device for p in list_ports.comports()]
except Exception:
return []
def build_ui(ctrl: MaestroController):
root = tk.Tk()
root.title("CR Hand Button Panel")
# simple spacing
root.geometry("420x260")
root.resizable(False, False)
container = ttk.Frame(root, padding=12)
container.pack(fill="both", expand=True)
title = ttk.Label(container, text="CR Hand Controller", font=("Segoe UI", 14, "bold"))
title.grid(row=0, column=0, columnspan=3, sticky="w")
hint = ttk.Label(container, text="Click a button below to send positions.")
hint.grid(row=1, column=0, columnspan=3, sticky="w", pady=(0, 8))
status = tk.StringVar(value="Ready.")
status_lbl = ttk.Label(container, textvariable=status)
status_lbl.grid(row=99, column=0, columnspan=3, sticky="w", pady=(10, 0))
# Button callback
def send(name: str):
try:
positions = SCENARIOS[name]
ctrl.set_all(positions)
status.set(f"Sent: {name} {positions}")
except Exception as e:
status.set(f"Error: {e}")
print(f"[ERROR] {e}", file=sys.stderr)
# Make 7 buttons in a tidy grid (3x3-ish)
names = list(SCENARIOS.keys())
for i, name in enumerate(names):
r, c = divmod(i, 3)
btn = ttk.Button(container, text=name, command=lambda n=name: send(n), width=16)
btn.grid(row=2 + r, column=c, padx=6, pady=6, sticky="nsew")
# Stretch columns a bit
for c in range(3):
container.grid_columnconfigure(c, weight=1)
# Initialize to "Open" like Processing setup()
try:
ctrl.set_all(SCENARIOS["Open"])
status.set(f"Initialized: Open {SCENARIOS['Open']}")
except Exception as e:
status.set(f"Init error: {e}")
print(f"[ERROR] {e}", file=sys.stderr)
# Cleanly close serial on window close
def on_close():
try:
ctrl.close()
finally:
root.destroy()
root.protocol("WM_DELETE_WINDOW", on_close)
return root
def main():
ports = list_available_ports()
default_port = "COM1" if "COM1" in ports or not ports else ports[0]
parser = argparse.ArgumentParser(description="CR Hand button controller (Python + Tkinter + pyserial)")
parser.add_argument("--port", default=default_port, help=f"Serial port (default: {default_port})")
parser.add_argument("--baud", type=int, default=9600, help="Baud rate (default: 9600)")
args = parser.parse_args()
if ports:
print("[INFO] Available serial ports:")
for p in ports:
print(f" - {p}")
else:
print("[WARN] No serial ports found by pyserial.")
ctrl = MaestroController(args.port, args.baud)
try:
ctrl.open()
except Exception as e:
print(f"[FATAL] Could not open {args.port}: {e}")
sys.exit(1)
app = build_ui(ctrl)
app.mainloop()
if __name__ == "__main__":
main()
こちらはProcessingを使用してキーボード入力からハンドの姿勢の操作する場合の例です。サンプルプログラムをProcessingのテキストエディタにコピー&ペーストし、ポート番号を実際の番号に変更した上で実行ボタンを押してください。実行するとウィンドウが立ち上がります。このウィンドウがアクティブな状態でキーボードから1~7を入力すると、ハンドはそれぞれの番号に対応した姿勢を取ります。
import processing.serial.*;
// シリアルオブジェクト
Serial myPort;
// 各キー('1'~'7')を押した時に設定するサーボ位置を定義
// index: 0〜5がCh0〜Ch5に対応
// 例: scenarios[0]がキー'1'を押した時に設定する各サーボの位置
int[][] scenarios = {
{4000, 4000, 4000, 4000, 4000, 4000}, // '1'Open
{8000, 7000, 4000, 8000, 8000, 8000}, // '2'Pinch_open
{8000, 7000, 6000, 8000, 8000, 8000}, // '3'Pinch_close
{8000, 4000, 4000, 4000, 4000, 4000}, // '4'Graso_open
{8000, 6000, 8000, 8000, 8000, 8000}, // '5'Grasp_close
{4000, 4000, 8000, 8000, 8000, 8000}, // '6'Key_Pinch_open
{4000, 8000, 8000, 8000, 8000, 8000} // '7'Key_Pinch_close
};
void setup() {
size(400, 200);
// 利用可能なシリアルポートを表示(デバッグ用)
println(Serial.list());
// MaestroのCommand Portに接続(適宜ポート名を変更)
myPort = new Serial(this, "COM4", 9600);
println("Connected to COM4");
// 初期状態として、例えばキー'1'のポジションに合わせてみる
setAllServos(scenarios[0]);
}
void draw() {
// 特に処理なし
}
// キーが押されたときに呼ばれる
void keyPressed() {
// '1'~'7' のキーであるか判定
// '1'はASCIIで49, '7'は55 なので、'1'〜'7'に対応
if (key >= '1' && key <= '7') {
int index = key - '1'; // '1'が押されたら0、'2'なら1…と計算
if (index >= 0 && index < scenarios.length) {
// scenarios[index]で定義した全サーボの姿勢を設定
setAllServos(scenarios[index]);
}
}
}
// 全サーボ(Ch0〜Ch5)の位置を指定する関数
void setAllServos(int[] positions) {
for (int ch = 0; ch < 6; ch++) {
setServoPosition(ch, positions[ch]);
}
}
// サーボ位置を設定する関数
void setServoPosition(int channel, int target) {
byte[] command = new byte[4];
command[0] = (byte)0x84; // サーボ位置設定コマンド(0x84)
command[1] = (byte)channel;
command[2] = (byte)(target & 0x7F); // 下位7ビット
command[3] = (byte)((target >> 7) & 0x7F); // 上位7ビット
println("Sending command to Ch" + channel + ": "
+ hex(command[0]) + " "
+ hex(command[1]) + " "
+ hex(command[2]) + " "
+ hex(command[3]));
println("Target: " + target + " (" + (target * 0.25) + "µs)");
myPort.write(command);
}
基本的な使用方法は以上です。ご不明点等ございましたらadmin@curious-robotics.comまでご連絡下さい。
<アンケート>
SNSにて最新情報を発信しております。