使用するDynamixelの情報を予めライブラリ内に保持させておき、位置や角速度等の指令およびフィードバック値は物理値を扱い、各々の区別はIDのみで行うAPIです。
これAPIによりDynamixelのモデルごとに異なるコントロールテーブルや煩雑な運転方法の違いを意識する事なく、少ないコードで目的の挙動を実現できます。
なお、従来通りコントロールテーブルへの直接アクセスを制限するものではありませんが、その場合は本機能が想定する状況と一致しなくなる事があります。
※以下の使用例はDX2LIBを前提としています。
Dynamixelが持つ固有の情報を予め記憶させておくことで、それ以後の操作はIDのみを指定し、どのモデルであっても使用頻度が高いアイテムはコントロールテーブルを意識する事無く同じAPIで同様の動作ができます。
ID0~252のデバイスを順次検索し、サポートするDynamixelであればライブラリ内のリストに登録する。
リストに登録されていないデバイスのIDに対しては存在しないものとして通信を行わないため、DXL_ScanDevicesかDXL_GetModelInfoを用いて予めリストに登録しておく必要がある。
int DXL_ScanDevices (TDeviceID dvid, uint8_t *ids);
見つかったデバイスの数。
#include <stdio.h> #include <dx2lib.h> void main (void) { // COM10を57600bpsでオープン TDeviceID dev = DX2_OpenPort ("\\\\.\\COM10", 57600); if (dev != 0) { // ID=0~252の情報を取得し成功したもののみライブラリ内のリストに追加 printf("detect num=%d\n", DXL_ScanDevices (dev, NULL)); DX2_Close (dev); } }
指定IDのモデル情報の取得し、サポートするDynamixelであればライブラリ内のリストに登録する。
リストに登録されていないデバイスのIDに対しては存在しないものとして通信を行わないため、DXL_ScanDevicesかDXL_GetModelInfoを用いて予めリストに登録しておく必要がある。
PDXL_ModelInfo DXL_GetModelInfo (TDeviceID dvid, uint8_t id);
登録されたIDと一致するTDXL_ModelInfoのアドレス。
#include <stdio.h> #include <dx2lib.h> void main (void) { TDeviceID dev = DX2_OpenPort ("/dev/ttyUSB0", 57600); for (uint8_t id = 0; id <= 252; id++) { // idの情報を取得し成功したらライブラリ内のリストに追加 PDXL_ModelInfo p = DXL_GetModelInfo (dev, id); if (p->modelno != 0) printf ("[%3d] %s ($%04X) %d\n", id, p->name, p->modelno, p->devtype); } } DX2_ClosePort (dev); }
ライブラリ内のリストに登録された全てのデバイスの情報をコンソールに出力する。
ID・モデル名・モデル番号の順に出力される。
bool DXL_PrintDevicesList (int (*pf) (const char *, ...));
printf等の書式化文字列出力ルーチンのポインタ。
処理が正常終了したらtrue、それ以外はfalseを返す。
#include <stdio.h> #include <dx2lib.h> void main (void) { TDeviceID dev = DX2_OpenPort ("/dev/ttyUSB0", 57600); DXL_ScanDevices (dev, NULL); DXL_PrintDevicesList ((void *)&printf); DX2_ClosePort (dev); }
追加APIの処理の中で最後に取得したエラーを返す。本API自体は通信を行わない。
TErrorCode DXL_GetErrorCode (TDeviceID dvid, uint8_t id);
エラーコード。
対象IDのコントロールテーブルにハードウェアエラーが備わっている場合にのみ取得する。
bool DXL_GetHWErrorCode (TDeviceID dvid, uint8_t id, uint8_t *hwerr);
運転モードはDynamixelのDrive Mode、動作モードはOperating Modeを意味します。
運転モードはデフォルトの回転方向やプロファイルの選択、マスタースレーブの設定を行います。
動作モードについてはDynamixel X・Pシリーズの動作モードを基準とし、他のモデルにおいてもこの動作モードの番号を踏襲することとします。
対象IDの運転モードを変更する。
指定されたモードと現在のモードが異なる場合にのみトルクをOFFにし運転モードを更新する。
対称IDがライブラリ内のリストに登録されている必要がある。
bool DXL_SetDriveMode (TDeviceID dvid, uint8_t id, uint8_t mode);
処理が正常終了したらtrue、それ以外はfalseを返す。
#include <dx2lib.h> void main (void) { TDeviceID dev = DX2_OpenPort ("\\\\.\\COM10", 57600); // ID:1を検索し見つかれば登録 DXL_GetModelInfo (dev, 1); // ID:1のXシリーズをTime-Base Profileに設定 DXL_SetDriveMode (dev, 1, 4); DX2_ClosePort (dev); }
複数IDの運転モードを一括変更する。
指定されたモードと現在のモードが異なる場合にのみトルクをOFFにし運転モードを更新する。
ライブラリ内のリストに登録されていないIDは無視される。
bool DXL_SetDriveModesEquival (TDeviceID dvid, const uint8_t *ids, int num, uint8_t mode);
処理が正常終了したらtrue、それ以外はfalseを返す。
#include <dx2lib.h> void main (void) { TDeviceID dev = DX2_OpenPort ("\\\\.\\COM10", 57600); uint8_t ids[3] = {1, 2, 3}; // ID:1~3を検索し見つかれば登録 for (int i = 0; i < sizeof (ids); i++) DXL_GetModelInfo (dev, ids[i]); // ID:1~3のDrive Modeを出荷時デフォルト値に設定 DXL_SetDriveModesEquival (dev, ids, sizeof (ids), 0); DX2_ClosePort (dev); }
対象IDの動作モードを変更する。
指定されたモードと現在のモードが異なる場合にのみトルクをOFFにし動作モードを更新する。
対称IDがライブラリ内のリストに登録されている必要がある。
bool DXL_SetOperatingMode (TDeviceID dvid, uint8_t id, uint8_t mode);
DX?_OpenPortで開いた際のTDeviceID。
対象とするID (0~252)。
Dynamixel Xシリーズの動作モードを想定し、それに完全対応しないデバイスに対しては近似値もしくは失敗を返す。
0: Current Control (電流制御)
1: Velocity Control (速度制御)
3: Position Control (位置制御)
4: Expand Position Control (多回転位置制御)
5: Current-Base Position Control
16: PWM Control
処理が正常終了したらtrue、それ以外はfalseを返す。
#include <dx2lib.h> void main (void) { TDeviceID dev = DX2_OpenPort ("\\\\.\\COM10", 57600); // ID:1を検索し見つかれば登録 DXL_GetModelInfo (dev, 1); // ID:1をCurrent-Base Position Controlに設定 DXL_SetOperatingMode (dev, 1, 5); DX2_ClosePort (dev); }
複数IDの動作モードを一括変更する。
指定されたモードと現在のモードが異なる場合にのみトルクをOFFにし動作モードを更新する。
ライブラリ内のリストに登録されていないIDは無視される。
bool DXL_SetOperatingModesEquival (TDeviceID dvid, const uint8_t *ids, int num, uint8_t mode);
DX?_OpenPortで開いた際のTDeviceID。
対象とするID一覧を保持する配列の保存先。
対象とするID数
Dynamixel Xシリーズの動作モードを想定し、それに完全対応しないデバイスに対しては近似値もしくは失敗を返す。
0: Current Control
1: Velocity Control
3: Position Control
4: Expand Position Control
5: Current-Base Position Control
16: PWM Control
処理が正常終了したらtrue、それ以外はfalseを返す。
#include <dx2lib.h> void main (void) { TDeviceID dev = DX2_OpenPort ("\\\\.\\COM10", 57600); uint8_t ids[3] = {1, 2, 3}; // ID:1~3を検索し見つかれば登録 for (int i = 0; i < sizeof (ids); i++) DXL_GetModelInfo (dev, ids[i]); // ID:1~3をVelocity Controlに設定 DXL_SetOperatingModesEquival (dev, ids, sizeof (ids), 1); DX2_ClosePort (dev); }
対象IDの動作モードを取得する。なお内部ではDrive Modeも一緒に取得し保持している。
bool DXL_GetOperatingMode (TDeviceID dvid, uint8_t id, uint8_t *mode);
対象IDの制御を開始ないし停止させる。
なお、プロトコルV2のDynamixelは明示的に制御を開始しない限りモータの制御を行わない。
bool DXL_SetTorqueEnable (TDeviceID dvid, uint8_t id, bool en);
処理が正常終了したらtrue、それ以外はfalseを返す。
#include <dx2lib.h> void main (void) { TDeviceID dev = DX2_OpenPort ("\\\\.\\COM10", 57600); DXL_GetModelInfo (dev, 1); DXL_SetOperatingMode (dev, 1, 3); // ID:1の制御をON DXL_SetTorqueEnable (dev, 1, true); // ID:1へ角度指令 180deg DXL_SetGoalAngle (dev, 1, 180.0); // 1000ms待機 Sleep (1000); // ID:1の制御をOFF DXL_SetTorqueEnable (dev, 1, false); DX2_ClosePort (dev); }
複数IDの制御を個別に開始ないし停止させる。
ライブラリ内のリストに登録されていないIDは無視される。
なお、プロトコルV2のDynamixelは明示的に制御を開始しない限りモータの制御を行わない。
bool DXL_SetTorqueEnables (TDeviceID dvid, const uint8_t *ids, const bool *ens, int num);
複数IDの制御を一括で開始ないし停止させる。
ライブラリ内のリストに登録されていないIDは無視される。
なお、プロトコルV2のDynamixelは明示的に制御を開始しない限りモータの制御を行わない。
bool DXL_SetTorqueEnablesEquival (TDeviceID dvid, const uint8_t *ids, int num, bool en);
処理が正常終了したらtrue、それ以外はfalseを返す。
#include <dx2lib.h> void main (void) { TDeviceID dev = DX2_OpenPort ("\\\\.\\COM10", 57600); DXL_GetModelInfo (dev, 1); DXL_GetModelInfo (dev, 2); DXL_GetModelInfo (dev, 3); uint8_t ids[3] = {1, 2, 3}; // ID:1~3の制御をON DXL_SetTorqueEnablesEquival (dev, ids, sizeof (ids), true); DX2_ClosePort (dev); }
対象IDのトルクイネーブル状態を取得する。
bool DXL_GetTorqueEnable (TDeviceID dvid, uint8_t id, bool *en);
複数IDのトルクイネーブル状態を取得する。
ライブラリ内のリストに登録されていないIDは無視される。
bool DXL_GetTorqueEnables (TDeviceID dvid, const uint8_t *ids, bool *en, int num);
DynamixelのコントロールテーブルではPositionと称しているユニークな単位系を持つアイテムは、モデルによって動作角度や分解能が大きく異なります。異なるモデルを混在して運用する場合は非常に不便なため、物理値の角度[deg]を用いてアクセスします。
指定IDへ目標角度を指令する。
動作モードがPosition Controlである事と、プロトコルV2のDynamixelは明示的に制御を開始しない限りモータの制御を行わない。
bool DXL_SetGoalAngle (TDeviceID dvid, uint8_t id, double angle);
処理が正常終了したらtrue、それ以外はfalseを返す。
#include <dx2lib.h> void main (void) { TDeviceID dev = DX2_OpenPort ("\\\\.\\COM10", 57600); DXL_GetModelInfo (dev, 1); DXL_SetOperatingMode (dev, 1, 3); DXL_SetTorqueEnable (dev, 1, true); // ID:1へ角度指令 180deg DXL_SetGoalAngle (dev, 1, 180.0); Sleep (1000); // ID:1へ角度指令 -180deg DXL_SetGoalAngle (dev, 1, -180.0); Sleep (1000); // ID:1へ角度指令 0deg DXL_SetGoalAngle (dev, 1, 0.0); Sleep (1000); DXL_SetTorqueEnable (dev, 1, false); DX2_ClosePort (dev); }
複数IDへ個別の目標角度を指令する。
ライブラリ内のリストに登録されていないIDは無視される。
動作モードがPosition Controlである事と、プロトコルV2のDynamixelは明示的に制御を開始しない限りモータの制御を行わない。
bool DXL_SetGoalAngles (TDeviceID dvid, const uint8_t *ids, const double *angles, int num);
処理が正常終了したらtrue、それ以外はfalseを返す。
#include <dx2lib.h> void main (void) { TDeviceID dev = DX2_OpenPort ("\\\\.\\COM10", 57600); DXL_GetModelInfo (dev, 1); DXL_GetModelInfo (dev, 2); DXL_GetModelInfo (dev, 3); uint8_t ids[3] = {1, 2, 3}; DXL_SetOperatingModesEquival (dev, ids, sizeof (ids), 3); DXL_SetTorqueEnablesEquival (dev, ids, sizeof (ids), true); // 3軸分の角度を保存したの配列 double angles[3] = { 0.0, 150.0, 300.0 }; // 3軸分の角度指令 DXL_SetGoalAngles (dev, ids, angles, sizeof (ids)); Sleep (2000); DXL_SetTorqueEnablesEquival (dev, ids, sizeof (ids), false); DX2_ClosePort (dev); }
対象IDの現在角度を取得する。
bool DXL_GetPresentAngle (TDeviceID dvid, uint8_t id, double *angle);
処理が正常終了したらtrue、それ以外はfalseを返す。
#include <stdio.h> #include <dx2lib.h> void main (void) { TDeviceID dev = DX2_OpenPort ("\\\\.\\COM10", 57600); uint8_t id = 1; DXL_GetModelInfo (dev, id); DXL_SetOperatingMode (dev, id, 3); DXL_SetTorqueEnable (dev, id, true); DXL_SetGoalAngle (dev, id, -180.0); Sleep (1000); DXL_SetGoalAngle (dev, id, 180.0); for (int i = 0; i < 1000; i++) { double pang; // 現在角度取得 if (DXL_GetPresentAngle (dev, id, &pang)) printf ("%5.1\r", pang); Sleep (10); } DXL_SetTorqueEnable (dev, id, false); DX2_ClosePort (dev); }
複数IDの現在角度を取得する。
ライブラリ内のリストに登録されていないIDは無視される。
bool DXL_GetPresentAngles (TDeviceID dvid, const uint8_t *ids, double *angles, int num);
制御をOFFにする事で制御が停止するのと合わせて脱力状態になります。それでは現在の角度を保持しつつ止めることができないため、指令されたタイミングの角度を取得してその値をそのまま角度指令し直す機能を設けています。
指定IDを現在角度で停止させる。
動作モードがPosition Controlである事。
bool DXL_StandStillAngle (TDeviceID dvid, uint8_t id);
複数IDを現在角度で停止させる。
ライブラリ内のリストに登録されていないIDは無視される。
動作モードがPosition Controlである事。
bool DXL_StandStillAngles (TDeviceID dvid, const uint8_t *ids, int num);
DynamixelのコントロールテーブルではVelocityと称しているユニークな単位系を持つアイテムは、モデルによってレンジや分解能が異なります。異なるモデルを混在して運用する場合は非常に不便なため、物理値の角速度[deg/sec]を用いてアクセスします。
指定IDへ目標角速度を指令する。
動作モードがVelocity Controlである事と、プロトコルV2のDynamixelは明示的に制御を開始しない限りモータの制御を行わない。
bool DXL_SetGoalVelocity (TDeviceID dvid, uint8_t id, double velocity);
処理が正常終了したらtrue、それ以外はfalseを返す。
#include <dx2lib.h> void main (void) { TDeviceID dev = DX2_OpenPort ("\\\\.\\COM10", 57600); DXL_GetModelInfo (dev, 1); DXL_SetOperatingMode (dev, 1, 1); DXL_SetTorqueEnable (dev, 1, true); // 角速度指令 30deg/s DXL_SetGoalVelocity (dev, 1, 30.0); Sleep (1000); // 角速度指令 40deg/s DXL_SetGoalVelocity (dev, 1, 40.0); Sleep (1000); DXL_SetTorqueEnable (dev, 1, false); DX2_ClosePort (dev); }
複数IDへ個別の目標角速度を指令する。
ライブラリ内のリストに登録されていないIDは無視される。
動作モードがVelocity Controlである事と、プロトコルV2のDynamixelは明示的に制御を開始しない限りモータの制御を行わない。
bool DXL_SetGoalVelocities (TDeviceID dvid, const uint8_t *ids, const double *velocities, int num);
対象IDの現在角速度を取得する。
bool DXL_GetPresentVelocity (TDeviceID dvid, uint8_t id, double *velocity);
複数IDの現在角速度を取得する。
ライブラリ内のリストに登録されていないIDは無視される。
bool DXL_GetPresentVelocities (TDeviceID dvid, const uint8_t *ids, double *velocities, int num);
角度と合わせて角速度を同時に指令することで、指定角度へゆっくり動かすと行った動作を行わせる事ができます。
なお、Dynamixelの角速度制御の分解能はさほど大きくないため、角速度が低い場合は誤差が大きくなります。
指定IDへ目標角度と目標角速度を指令する。
動作モードがPosition Controlである事と、プロトコルV2のDynamixelは明示的に制御を開始しない限りモータの制御を行わない。
bool DXL_SetGoalAngleAndVelocity (TDeviceID dvid, uint8_t id, double angle, double velocity);
処理が正常終了したらtrue、それ以外はfalseを返す。
#include <dx2lib.h> void main (void) { TDeviceID dev = DX2_OpenPort ("\\\\.\\COM10", 57600); uint8_t id = 3; DXL_GetModelInfo (dev, id); DXL_SetOperatingMode (dev, id, 3); DXL_SetTorqueEnable (dev, id, true); // 現在角度から-170degの角度へ30deg/sの角速度で DXL_SetGoalAngleAndVelocity (dev, id, -170.0, 30.0); Sleep (10000); // 現在角度から160degの角度へ40deg/sの角速度で DXL_SetGoalAngleAndVelocity (dev, id, 160.0, 40.0); Sleep (10000); DXL_SetTorqueEnable (dev, id, false); DX2_ClosePort (dev); }
複数IDへ個別の目標角度と目標角速度を指令する。
ライブラリ内のリストに登録されていないIDは無視される。
動作モードがPosition Controlである事と、プロトコルV2のDynamixelは明示的に制御を開始しない限りモータの制御を行わない。
bool DXL_SetGoalAnglesAndVelocities (TDeviceID dvid, const uint8_t *ids, const PAngleVelocity anglevelocity, int num);
DX?_OpenPortで開いた際のTDeviceID。
対象とするID一覧を保持する配列の保存先。
idsで指定されたID順に目標角度[deg]と目標角速度[deg/s]を保持する構造体の配列の保存先。
対象とするID数
処理が正常終了したらtrue、それ以外はfalseを返す。
角度と合わせて時間を同時に指令します。ライブラリ内では時間を角速度(=(目標角度-現在角度)/移動時間)に変換して指令します。
なお、Dynamixelの角速度制御の分解能はさほど大きくないため、移動速度が長い場合は誤差が大きくなります。
また事前にDXL_SetDriveModeもしくはDXL_SetDriveModesEquivalでVelocity-Base Profile(出荷時デフォルト)を指定しておく必要があります。
最新のファームウェアを備えたDynamixelの場合は角度と時間2のAPIを利用することを推奨します。
指定IDへ目標角度と現在角度から目標角度までの移動時間を指令する。
動作モードがPosition Controlである事と、プロトコルV2のDynamixelは明示的に制御を開始しない限りモータの制御を行わない。
bool DXL_SetGoalAngleAndTime (TDeviceID dvid, uint8_t id, double angle, double sec);
処理が正常終了したらtrue、それ以外はfalseを返す。
#include <dx2lib.h> void main (void) { TDeviceID dev = DX2_OpenPort ("\\\\.\\COM10", 57600); uint8_t id = 3; DXL_GetModelInfo (dev, id); DXL_SetOperatingMode (dev, id, 3); DXL_SetTorqueEnable (dev, id, true); // 現在角度から-150degの角度へ3秒で移動 DXL_SetGoalAngleAndTime (dev, id, -150.0, 3.0); Sleep (4000); // 現在角度から180degの角度へ5秒で移動 DXL_SetGoalAngleAndTime (dev, id, 180.0, 5.0); Sleep (6000); DXL_SetTorqueEnable (dev, id, false); DX2_ClosePort (dev); }
複数IDへ個別の目標角度と現在角度から目標角度までの移動時間を指令する。
ライブラリ内のリストに登録されていないIDは無視される。
動作モードがPosition Controlである事と、プロトコルV2のDynamixelは明示的に制御を開始しない限りモータの制御を行わない。
bool DXL_SetGoalAnglesAndTime (TDeviceID dvid, const uint8_t *ids, const double *angles, int num, double sec);
角度と合わせて時間を同時に指令します。目的は先のAPIと同様ですが、Dynamixelの新しいファームウェアに備わっているTime-Base Profileを用いて指令するため、指定時間通りに目標角度に到達します。
事前にDXL_SetDriveModeもしくはDXL_SetDriveModesEquivalでTime-Base Profileを設定しておく必要があります。
指定IDへ目標角度と現在角度から目標角度までの移動時間を指令する。
動作モードがPosition Controlである事と、プロトコルV2のDynamixelは明示的に制御を開始しない限りモータの制御を行わない。
bool DXL_SetGoalAngleAndTime2 (TDeviceID dvid, uint8_t id, double angle, double sec);
処理が正常終了したらtrue、それ以外はfalseを返す。
#include <dx2lib.h> void main (void) { TDeviceID dev = DX2_OpenPort ("\\\\.\\COM10", 57600); uint8_t id = 3; DXL_GetModelInfo (dev, id); // Time-Base profileを設定 DXL_SetDriveMode (dev, id, 0x04); DXL_SetOperatingMode (dev, id, 3); DXL_SetTorqueEnable (dev, id, true); // 現在角度から-150degの角度へ3秒で移動 DXL_SetGoalAngleAndTime2 (dev, id, -150.0, 3.0); Sleep (4000); // 現在角度から180degの角度へ5秒で移動 DXL_SetGoalAngleAndTime2 (dev, id, 180.0, 5.0); Sleep (6000); DXL_SetTorqueEnable (dev, id, false); DX2_ClosePort (dev); }
複数IDへ個別の目標角度と現在角度から目標角度までの移動時間を指令する。
ライブラリ内のリストに登録されていないIDは無視される。
動作モードがPosition Controlである事と、プロトコルV2のDynamixelは明示的に制御を開始しない限りモータの制御を行わない。
bool DXL_SetGoalAnglesAndTime2 (TDeviceID dvid, const uint8_t *ids, const double *angles, int num, double sec);
指定IDへ目標電流を指令する。
プロトコルV2のDynamixelは明示的に制御を開始しない限りモータの制御を行わない。
bool DXL_SetGoalCurrent (TDeviceID dvid, uint8_t id, double current);
処理が正常終了したらtrue、それ以外はfalseを返す。
#include <dx2lib.h> void main (void) { TDeviceID dev = DX2_OpenPort ("\\\\.\\COM10", 57600); DXL_GetModelInfo (dev, 1); DXL_SetOperatingMode (dev, 1, 0); DXL_SetTorqueEnable (dev, 1, true); // 電流指令 200mA DXL_SetGoalCurrent (dev, 1, 200.0); Sleep (1000); // 電流指令 -200mA DXL_SetGoalAngle (dev, 1, -200.0); Sleep (1000); DXL_SetTorqueEnable (dev, 1, false); DX2_ClosePort (dev); }
複数IDへ個別の目標電流を指令する。
ライブラリ内のリストに登録されていないIDは無視される。
プロトコルV2のDynamixelは明示的に制御を開始しない限りモータの制御を行わない。
bool DXL_SetGoalCurrents (TDeviceID dvid, const uint8_t *ids, const double *currents, int num);
指定IDの現在電流を取得する。
bool DXL_GetPresentCurrent (TDeviceID dvid, uint8_t id, double *current);
複数IDの現在電流を取得する。
ライブラリ内のリストに登録されていないIDは無視される。
bool DXL_GetPresentCurrents (TDeviceID dvid, const uint8_t *ids, double *currents, int num);
指定IDへ目標PWMを指令する。
動作モードがPWM Controlである事と、プロトコルV2のDynamixelは明示的に制御を開始しない限りモータの制御を行わない。
bool DXL_SetGoalPWM (TDeviceID dvid, uint8_t id, double pwm);
処理が正常終了したらtrue、それ以外はfalseを返す。
#include <dx2lib.h> void main (void) { TDeviceID dev = DX2_OpenPort ("\\\\.\\COM10", 57600); DXL_GetModelInfo (dev, 1); DXL_SetOperatingMode (dev, 1, 16); DXL_SetTorqueEnable (dev, 1, true); // PWM指令 50% DXL_SetGoalPWM (dev, 1, 50.0); Sleep (1000); // PWM指令 -40% DXL_SetGoalPWM (dev, 1, -40.0); Sleep (1000); DXL_SetTorqueEnable (dev, 1, false); DX2_ClosePort (dev); }
複数IDへ個別の目標PWMを指令する。
ライブラリ内のリストに登録されていないIDは無視される。
動作モードがPWM Controlである事と、プロトコルV2のDynamixelは明示的に制御を開始しない限りモータの制御を行わない。
bool DXL_SetGoalPWMs (TDeviceID dvid, const uint8_t *ids, const double *pwms, int num);
指定IDの現在PWMを取得する。
bool DXL_GetPresentPWM (TDeviceID dvid, uint8_t id, double *pwm);
複数IDの現在PWMを取得する。
ライブラリ内のリストに登録されていないIDは無視される。
bool DXL_GetPresentPWMs (TDeviceID dvid, const uint8_t *ids, double *pwms, int num);