Table of Contents
1. Overview
DynamixelforUnity (D4U) is an asset to easily implement Dynamixel servomotor control within in Unity3D. D4U provides numerous methods to interface with Dynamixel servomotors, enabling you to efficiently and easily connect, control, and read data from a variety of Dynamixel servomotors.
Specificially, D4U focuses on the following feature sets:
- Automatically load the Control Table of the servomotor
- Enable simultaneous control of multiple servomotor models.
- Enable Controlling Dynamixel servomotor with simple declarative code.
- Abstracts low level servomotor and provides a number of classes to simplify servomotor controls.
- Enable advanced functions like, batch control of multiple models and unit conversion.
- Provide low-level communication and servomotor controls within Unity3D (when required).
Therefore, users are able to completely focus on writing all robot control code from within Unity3D, using simple code in C# that can easily be integrated with a variety of applications, games, simulations or other experiences and use cases that leverage Unity3D.
Supported OS
Supported protocol
Supported Dynamixel models
Model compatible with DYNAMIXEL Protocol 2.0.
- MX-28
- MX-64
- MX-106
- X Series (2X Series included)
- PRO Series
- P Series
2. Installation
With the Unity3D project you want to use, double-click DynamixelForUnity.unitypackage, or drag and drop it into the Project window of the Unity3D project. A pop-up will appear, please choose to improt the package and all its contents to your project.
3. License Purchase and Activation
A license must be purchased from HatsuMuv site in order to use D4U with complete expirence. Without a license, you can only use 10 operations for every execution.
After the purcahse, you will recieve a link to a form, where you are required to provide various information, including device ID, which is a unique ID number that is used to link your license to the machine D4U will be used on:
To generate your device ID and insert it in the above form, click Get DeviceID for Registration in your toolbar. It will automatically copy your device ID to your clip board and shows in consle window. Please follow the instructions shown in the screenshot below:
After your purchase D4U, you will recieve an SN by email. To use your SN within D4U, please insert your Email and SN in the D4U verificate method or through the Dynamixel For Unity Component in Unity3D UI as shown below:
To check your verify your activation, simply run your scene, and you can check if the activation is correct or not in consle.
4. Quick Start
Here is a demo that gets and sets the positions of 2 Dynamixel servomotors.
Before Starting, Assigning ID Numbers to Your New DYNAMIXEL Servos
Before you start this demo, you will need to set your Dynamixel Servos with different IDs.
The simplest way to do this is by using ROBOTIS’ DYNAMIXEL Wizard 2.0 Software. Please refers to ROBOTIS website to search for ID
Setting up a new scene
- Open a new scene and drag and drop HatsuMuv/DynamixelForUnity/Prefabs/DynamixelForUnity into the hierarchy window.
- Select DynamixelForUnity gameobject in Hierarchy menu
-
In Inspector window, you can find a component called DynamixelForUnity. Enter your Email and SN, and the USB serial port which connected to your Dynamixel servomotor in the Device Name field. (You can find the port name from your Device manager, e.g. “COM3”).
-
(Optional) If you know the baudrate of the servomotor you want to operate, set the Baud Rate in the inspector of DynamixelForUnity beforehand. If you don’t know, leave it blank, D4U SetUp method will scan for you. (Which can be time comsuming)
-
“Click Add Component” Button, and input script name as you like (For this time, “Demo”). Then click “New script”.
- Double click on the script called Demo written in gray text and wait for a while. Visual studio will open.
Coding C# script
When Visual Studio opens, write as below. This code prints the current positions of two servomotors to Debug.Log and then sets their goal positions to 1024 each.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using HatsuMuv.DynamixelForUnity.x64;
public class Demo : MonoBehaviour
{
DynamixelForUnity d4u;
void Start()
{
d4u = GetComponent<DynamixelForUnity>();
d4u.ConnectDynamixel();
d4u.SetUp();
d4u.SyncSetDataGroupMultiModels("OperatingMode", new uint[] { 3, 3 });
d4u.SyncSetDataGroupMultiModels("TorqueEnable", new uint[] { 1, 1 });
int[] presentPosition = d4u.SyncGetSignedDataGroupMultiModels("PresentPosition");
Debug.Log("PresentPosition: " + string.Join(", ", presentPosition));
d4u.SyncSetDataGroupMultiModels("GoalPosition", new uint[] { 1024, 1024 });
}
void OnApplicationQuit()
{
uint[] torqueEnableCommand = new uint[] { 0, 0 };
d4u.SyncSetDataGroupMultiModels("TorqueEnable", torqueEnableCommand);
}
}
Execution
Return to the Unity screen and click the Play button.
The position of the servomotor will be printed on the console.
5. Script Reference
Select a namespace from the following according to your system configuration.
// Select a namespace which suit for your system (OS)
HatsuMuv.DynamixelForUnity.x64
HatsuMuv.DynamixelForUnity.x86
DynamixelForUnity
DynamixelForUnity is a class provided to control Dynamixel servomotors with declarative program.
Declarative programming: Describe what you want, not how to do it. For more details, please search for ‘Declarative Programming’.
One DynamixelForUnity component manage one port. If you want to control multiple ports simultaneously, please add as many components as the number of ports.
DynamixelForUnity is implementing IControlTableUser.
Flow of Use:
- Open a port with ConnectDynamixel.
- (Optional) Keep the servomotor ID and model number used in SetUp or SetIDsForUse. This procedure allows for concise writing when sending instructions using only data field names or when sending instructions to all servomotors.
- Control the servomotor with methods such as SetData, etc. Note that data in the EEPROM area such as OperatingMode can only be written when the torque is OFF.
- At the end of the oparation, perform a termination procedure such as torque disable in the OnApplicationQuit or OnDisable. If the DynamixelForUnity is connected at the time when OnDestroy is called, it will call DisconnectDynamixel.
Here is Example.
using HatsuMuv.DynamixelForUnity.x64;
public class ExampleClass : MonoBehaviour
{
DynamixelForUnity d4u;
void Start() {
d4u = GetComponent<DynamxielForUnity>();
d4u.ConnectDynamixel();
d4u.SetUp();
d4u.SetData("TorqueEnable", 1, 1);
}
void OnApplicationQuit() {
d4u.SetData("TorqueEnable", 0, 1)
}
}
Constant
Constant |
Value |
Description |
PROTOCOL_VERSION |
2 |
DynamixelForUnity supports protocol version 2.0 only. |
Variables
Name |
Description |
showMessage |
If this is set to true, all execution logs of DynamixelForUnity will be output to Debug.Log. Errors and warnings are not affected. |
Propertyies
Name |
Description |
ControlTables |
An object that contains controlTable of multiple models. Functions that send commands from data field names refer to this. |
BaudRate |
Returns the current baud rate. Read only. |
IDsForUse |
ID array held in DynamixelForUnity. SetUp method and SetIDsForUse method. Read-only. |
ModelNumbers |
Dictionary<byte, int> type. Represents the model number of the servomotor for which the ID is being held, set by the SetIDsForUse and SetUp methods. Read-only. |
ConnectStatus |
True/false value indicating whether or not there is a connection with the servomotor. Read only. |
Varification |
True/False value indicating whether the license is authenticated. Read-only. |
Verificate
-
Declaration
public bool Verificate(HatsuVerif verif)
-
Argument
- HatsuVerif verif
- Verification class object. Created from the license file path and verification information.
-
Returns
License validity.
-
Description
This function is used for validating your license, which will be automatically called (Awake function) if you put DynamxielForUnity in your gameobject as component from beginning. If you new a instant after pressing play, you will need to run this method to validate your license before you start to use D4U’s functions.
-
Declaration
public bool Verificate(string userEmail, string userSN, bool forceRenew = false)
-
Returns
License validity.
ConnectDynamixel
-
Declaration
public bool ConnectDynamixel()
public bool ConnectDynamixel(string deviceName)
public bool ConnectDynamixel(BaudRate baudRate)
public bool ConnectDynamixel(string deviceName, BaudRate baudRate)
-
Argument
- string deviceName
- Port name to connect. ex.) "COM3".
- BaudRate baudRate
- Baud rate to be connected.
-
Returns
Returns true if the connection succeeds, false otherwise.
-
Description
Opens a port with the specified baud rate and connects to the Dynamixel servomotor. If no port or baud rate is specified, the value specified in the inspector is used.
ScanInBaudRate
-
Declaration
public byte[] ScanInBaudRate(BaudRate baudRate, byte[] idsForScan = null)
-
Argument
- BaudRate baudRate
- Baud rate used for scanning.
- byte[] idsForScan
- The ID of the target to be scanned, used to search only for servomotors with a specific ID; if null is specified, all IDs are scanned.
-
Returns
Byte array of available servomotor IDs.
-
Description
Ping the Dynamixel servomotor at the specified baud rate and scan it; use the SetBaudRate method to change to the specified baud rate.
-
Declaration
public byte[] ScanInBaudRate(BaudRate baudRate, byte minIDsForScan, byte maxIDsForScan)
-
Argument
- byte minIDsForScan
- Lower limit of the range for the ID of the object to be scanned. (Included in the range)
- byte maxIDsForScan
- Upper limit of the range for the ID of the object to be scanned. (Included in the range)
-
Returns
Byte array of available servomotor IDs.
-
Description
Ping the Dynamixel servomotor at the specified baud rate and scan it, using the SetBaudRate method to change to the specified baud rate. The scan target can be specified in a range.
ScanInBaudRateAsync
-
Declaration
public async Task<byte[]> ScanInBaudRateAsync(BaudRate baudRate, byte[] idsForScan = null, CancellationToken cancellationToken = default(CancellationToken))
-
Argument
- BaudRate baudRate
- Baud rate used for scanning.
- byte[] idsForScan
- The ID of the target to be scanned, used to search only for servomotors with a specific ID; if null is specified, all IDs are scanned.
- CancellationToken cancellationToken
- Used to cancel a process.
-
Returns
Byte array of available servomotor IDs.
-
Description
Asynchronously pings and scans Dynamixel servomotors at the specified baud rate; changes to the specified baud rate using the SetBaudRate method.
-
Declaration
public async Task<byte[]> ScanInBaudRateAsync(BaudRate baudRate, byte minIDsForScan, byte maxIDsForScan, CancellationToken cancellationToken = default(CancellationToken))
-
Argument
- byte minIDsForScan
- Lower limit of the range for the ID of the object to be scanned. (Included in the range)
- byte maxIDsForScan
- Upper limit of the range for the ID of the object to be scanned. (Included in the range)
- CancellationToken cancellationToken
- Used to cancel a process.
-
Returns
Byte array of available servomotor IDs.
-
Description
Asynchronously pings and scans Dynamixel servomotors at a specified baud rate, using the SetBaudRate method to change to the specified baud rate. The scan target can be specified in a range.
Ping
-
Declaration
public bool Ping(byte ID, bool hideErrorMsg = true)
-
Argument
- byte ID
- ID of the target to ping.
- bool hideErrorMsg
- Disable error output on connection failure.
-
Returns
Whether they are connected.
-
Description
Ping the specified ID to check if it is connected.
PingGetModelNumber
-
Declaration
public int PingGetModelNumber(byte ID)
-
Argument
- byte ID
- ID of the target to ping.
-
Returns
Model number. When communication fails, -1 is returned.
-
Description
Ping the specified ID to obtain the model number.
GetAllModelNumber
-
Declaration
public int[] GetAllModelNumber(byte[] ids = null)
-
Argument
- byte[] ids
- The target ID from which the model number is obtained; if null is specified, the ID held in DynamixelForUnity is targeted.
-
Returns
An array of model numbers. Items for which communication failed are marked with -1.
-
Description
Ping the specified multiple IDs and return an array of model numbers.
SetControlTable
SetUp
-
Declaration
public byte[] SetUp(BaudRate? baudRate = null, byte[] idsForScan = null, bool scanAllBaudRateIfNotFound = true)
-
Argument
- BaudRate? baudRate
- The baud rate to be scanned first; if null is specified, the BaudRate previously set by Inspector or other means is used.
- byte[] idsForScan
- ID for setup target; if null is specified, scan is performed for all IDs.
- bool scanAllBaudRateIfNotFound
- If no Dynamixel servomotors are found at the first baud rate scanned, scan at all baud rates.
-
Returns
Byte array of available servomotor IDs.
-
Description
Scan the dynamixel servomotor with the ScanInBaudRate method and hold the scanned ID as the servomotor to be used with the SetIDsForUse method.
SetUpAsync
-
Declaration
public async Task<byte[]> SetUpAsync(BaudRate? baudRate = null, byte[] idsForScan = null, bool scanAllBaudRateIfNotFound = true, CancellationToken cancellationToken = default(CancellationToken))
-
Argument
- BaudRate? baudRate
- The baud rate to be scanned first; if null is specified, the BaudRate previously set by Inspector or other means is used.
- byte[] idsForScan
- ID for setup target; if null is specified, scan is performed for all IDs.
- bool scanAllBaudRateIfNotFound
- If no Dynamixel servomotors are found at the first baud rate scanned, scan at all baud rates.
- CancellationToken cancellationToken
- Used to cancel a process.
-
Returns
Byte array of available servomotor IDs.
-
Description
Asynchronously scan the dynamixel servomotor with the ScanInBaudRateAsync method and hold the scanned ID as the servomotor to be used with the SetIDsForUse method.
SetIDsForUse
By having DynamixelForUnity retain the servomotor ID and model number, it is possible to send commands using only the data field names, or to write concisely when sending commands to all servomotors.
DisconnectDynamixel
CloseAndReopenPort
RebootDynamixel
FactoryResetDynamixel
-
Declaration
public void FactoryResetDynamixel(DynamixelFactoryResetMode mode, byte[] ids = null)
-
Argument
- DynamixelFactoryResetMode mode
- Select whether to reset all values, all values except ID, or all values except ID and baud rate.
- byte[] idsForScan
- Target ID; if null is specified, the ID held in DynamixelForUnity is targeted.
-
Description
Reset the Dynamixel servomotor to the factory defaults.
SetBaudRate
-
Declaration
public bool SetBaudRate(BaudRate baudRate)
-
Argument
- BaudRate baudRate
- The baud rate of the target.
-
Returns
Returns true if successful, false otherwise.
-
Description
Set the baudrate of the port.
SetData
-
Declaration
public bool SetData(ushort ADDR, ushort LEN, uint data, byte id)
-
Argument
- ushort ADDR
- Address of the data field to be written. See Control Table of the model.
- ushort LEN
- Size of the data field to be written. See Control Table in the model.
- uint data
- Data to be written.
- byte id
- Target ID.
-
Returns
Returns true if successful, false otherwise.
-
Description
Writes data to the Dynamixel servomotor with the specified ID.
Check the Contorol Table from the ROBOTIS e-Manual of each Dynamixel servomotor for the address and length of the data field.
-
Declaration
public bool SetData(ControlTableAddressInfo addressInfo, uint data, byte id)
-
Argument
- ControlTableAddressInfo addressInfo
- A structure with the address, length, and access for each data field in the Control Table.
- uint data
- Data to be written.
- byte id
- Target ID.
-
Returns
Returns true if successful, false otherwise.
-
Description
SetData(ushort ADDR, ushort LEN, uint data, byte id) is used to write data to the Dynamixel servomotor with the specified ID. If the data field is read-only (e.g. present position), this method will not execute the command.
-
Declaration
public bool SetData(string dataName, uint data, byte id)
-
Argument
- string dataName
- Servomotor control Table data field name. Please refer to using the control table section for more information.
- uint data
- Data to be written.
- byte id
- Target ID.
-
Returns
Returns true if successful, false otherwise.
-
Description
SetData(ushort ADDR, ushort LEN, uint data, byte id) is used to write data to the Dynamixel servomotor with the specified ID. If the data field is read-only, it is not executed.
d4u.SyncGetSignedDataGroupMultiModels("GoalPosition").ToActualNumber(UNIT.POSITION).ToFloatArray(), ct);
The ID and model number must be retained by the SetUp or SetIDsForUse method to be used.
SetSignedData
-
Declaration
public bool SetSignedData(ushort ADDR, ushort LEN, uint data, byte id)
public bool SetSignedData(ControlTableAddressInfo addressInfo, int data, byte id)
public bool SetSignedData(string dataName, int data, byte id)
-
Description
Writes signed data to the Dynamixel servomotor with the specified ID, see Description of SetData.
GetData
-
Declaration
public uint GetData(ushort ADDR, ushort LEN, byte id)
-
Argument
- ushort ADDR
- Address of the data field to be rewritten. See Control Table of the model.
- ushort LEN
- Size of the data field to be rewritten. See Control Table in the model.
- byte id
- Target ID.
-
Returns
Data read. Returns 0 if an error occurs.
-
Description
Reads the data of the Dynamixel servomotor with the specified ID.
Check the Contorol Table from the ROBOTIS e-Manual of each Dynamixel servomotor for the address and length of the data field.
-
Declaration
public uint GetData(ControlTableAddressInfo addressInfo, byte id)
-
Argument
- ControlTableAddressInfo addressInfo
- A structure containing the address, length, and access for each data field in the Control Table.
- byte id
- Target ID.
-
Returns
Data read. Returns 0 if an error occurs.
-
Description
GetData(ushort ADDR, ushort LEN, byte id) is used to read data of a servomotor by specifying it’s ID.
-
Declaration
public uint GetData(string dataName, byte id)
-
Argument
- string dataName
- Control Table data field name.
- byte id
- Target ID.
-
Returns
Data read. Returns 0 if an error occurs.
-
Description
GetData(ushort ADDR, ushort LEN, byte id) is used to read data from a servomotor by specifying it’s ID.
The ID and model number must be created in using either the SetUp method or SetIDsForUse method to be used.
GetSignedData
-
Declaration
public int GetSignedData(ushort ADDR, ushort LEN, byte id)
public int GetSignedData(ControlTableAddressInfo addressInfo, byte id)
public int GetSignedData(string dataName, byte id)
-
Description
Reads the signed data of the Dynamixel servomotor with the specified ID, see Description of GetData.
SyncSetDataGroup
-
Declaration
public bool SyncSetDataGroup(ushort ADDR, ushort LEN, uint[] data, byte[] ids = null)
public bool SyncSetDataGroup(ControlTableAddressInfo addressInfo, uint[] data, byte[] ids = null)
-
Argument
- ushort ADDR
- Address of the data field to be rewritten. See Control Table of the model.
- ushort LEN
- Size of the data field to be rewritten. See Control Table in the model.
- ControlTableAddressInfo addressInfo
- A structure containing the address, length, and access for each data field in the Control Table.
- uint[] data
- Data array to be written.
- byte[] ids = null
- Target ID; if null is specified, the ID held in DynamixelForUnity is targeted.
-
Returns
Returns true if successful, false otherwise.
-
Description
Writes data to multiple servomotors simultaneously using GroupSyncWrite.
SyncSetDataGroupMultiModels
-
Declaration
public bool SyncSetDataGroupMultiModels(string dataName, uint[] data, byte[] ids = null)
-
Description
Writes data to multiple servomotors at the same time using GroupSyncWrite method. If the item names on the ControlTable are the same, the data will be sent to different addresses. In that case, call SyncSetDataGroup for each unique address; see Description of SyncSetDataGroup.
The ID and model number must be retained by the SetUp or SetIDsForUse method to be used.
SyncSetSignedDataGroup
-
Declaration
public bool SyncSetSignedDataGroup(ushort ADDR, ushort LEN, int[] data, byte[] ids = null)
public bool SyncSetSignedDataGroup(ControlTableAddressInfo addressInfo, int[] data, byte[] ids = null)
-
Description
Writes signed data to multiple servomotors simultaneously using GroupSyncWrite; see SyncSetDataGroup Description.
SyncSetSignedDataGroupMultiModels
-
Declaration
public bool SyncSetSignedDataGroupMultiModels(string dataName, int[] data, byte[] ids = null)
-
Description
Write signed data to multiple servomotors simultaneously using GroupSyncWrite method, see Description of SyncSetDataGroupMultiModels.
The ID and model number must be retained by the SetUp or SetIDsForUse method to be used.
SyncGetDataGroup
-
Declaration
public uint[] SyncGetDataGroup(ushort ADDR, ushort LEN, byte[] ids = null)
public uint[] SyncGetDataGroup(ControlTableAddressInfo addressInfo, byte[] ids = null)
-
Argument
- ushort ADDR
- Address of the data field to be read. See Control Table of the model.
- ushort LEN
- Size of the data field to be read. See Control Table in the model.
- ControlTableAddressInfo addressInfo
- A structure containing the address, length, and access for each data field in the Control Table.
- byte[] ids = null
- Target ID; if null is specified, the ID held in DynamixelForUnity is targeted.
-
Returns
uint array containing the read after executing the SyncGetDataGroup.
-
Description
Read data from multiple servomotors simultaneously using GroupSyncRead.
SyncGetDataGroupMultiModels
-
Declaration
public uint[] SyncGetDataGroupMultiModels(string dataName, byte[] ids = null)
-
Description
Simultaneously read data from multiple servomotors using GroupSyncRead method. If the item names on the ControlTable are the same, the data will be sent to different addresses. In that case, call SyncSetDataGroup for each unique address; see Description of SyncGetDataGroup.
The ID and model number must be retained by the SetUp or SetIDsForUse method to be used.
SyncGetSignedDataGroup
-
Declaration
public int[] SyncGetSignedDataGroup(ushort ADDR, ushort LEN, byte[] ids = null)
public int[] SyncGetSignedDataGroup(ControlTableAddressInfo addressInfo, byte[] ids = null)
-
Description
Read signed data to multiple servomotors simultaneously using GroupSyncRead, see Description of SyncGetDataGroup.
SyncGetSignedDataGroupMultiModels
-
Declaration
public int[] SyncGetSignedDataGroupMultiModels(string dataName, byte[] ids = null)
-
Description
Read signed data to multiple servomotors simultaneously using GroupSyncRead, see Description of SyncGetDataGroupMultiModels.
The ID and model number must be retained by the SetUp or SetIDsForUse method to be used.
BulkSetDataGroup
-
Declaration
public BulkWritePacket BulkSetDataGroup()
-
Returns
BulkWritePacket object.
-
Description
Returns a BulkWritePacket object for writing data to multiple servomotors at once using GroupBulkWrite.
GroupBulkWrite is described in a method chain mediated by BulkWritePacket.
BulkGetDataGroup
-
Declaration
public BulkReadPacket BulkGetDataGroup()
-
Returns
BulkReadPacket object.
-
Description
Returns a BulkReadPacket object for reading data in batches to multiple servomotors using GroupBulkRead.
GroupBulkRead is described in a method chain mediated by BulkReadPacket.
Using the Control Table
We created a text file to represent the control table of each Dynamixel servomotor. The control tables map each property name to the corresponding register number within for servomotor model.
The control tables correspond to the servomotor control tables found in ROBOTIS e-Manual.
Please check the control table data under D4U HatsuMuv/DynamixelForUnity/Resources/ControlTables/ and find the corresponding servomotor, as shown in the screenshot below:
The control tables can be used as parameters in a variety of methods in D4U, where you can pass the parameter name as a string to control or get feedback from various servomotors, as shown in the example below
// you may pass a control table parameter to read in the below method, where the control table parameter corresponds to the string representation of the register you need to set/read.
// This example uses wet a group of data through sync method
SyncGetDataGroupMultiModels("GoalPosition");
Using BulkWritePacket
Executing bulk write includes the following steps:
1- Initiate struct to hold bulk write parameters.
2- Add parameters to the struct.
3- Send the bulkwrite command.
4- (Options) read result of executing the command.
The BulkWritePacket object is used to execute the above four steps by settings its properties and calling its methods as highlighting explained below.
Step 1. Initiate Struct
To initiate the struct to hold the parameters for the writing packet, you must first declare and initialize the relevant BulkWritePacket objects as follows:
BulkWritePacket writePacket = dynamixelForUnity.BulkSetDataGroup();
Step 2. Adding Parameters
Upon creating the BulkWritePacket object, the data to be written should be added to the created object as parameters. This can be done as follows:
writePacket.AddParam(addressInfo1, idArray1, data1);
writePacket.AddParam(addressInfo2, idArray2, data2);
writePacket.AddParam(addressInfo3, idArray3, data3);
Step 3. Sending BulkWrite Command
Upon adding the parameters, the command can be executed by calling the BulkWritePacket object’s Send() method, as shown below:
writePacket.Send();
Step 4. (Optional) Checking results of BulkWrite Command Execution
You may optionally check the status of the command, whether it was successfully executed or not. You can check the property “AllSuccess” which is set to true if the command is successfully executed.
if(writePacket.AllSuccess)
Debug.Log("Successful");
Alternatively, you can directly place the BulkPacket object in an ‘if’ conditional to check if the command was successful.
if(writePacket)
Debug.Log("Successful");
Overall, you may execute the four steps in one line efficiently as follows:
Example:
if(dynamixelForUnity
.BulkSetDataGroup()
.AddParam(addressInfo1, idArray1, data1)
.AddParam(addressInfo2, idArray2, data2)
.AddParam(addressInfo3, idArray3, data3)
.Send())
Debug.Log("Successful");
Properties
Name |
Description |
IDParamPair |
It is of type Dictionary<byte, ParamInfo>. This holds parameters for each ID. ParamInfo contains address, length, communication success, and data to be written. Read-only. |
AllSuccess |
A boolean value indicating whether communication of all parameters was successful. Read only. |
HasSent |
A boolean value indicating whether the command was sent. Read only. |
AddParam
-
Declaration
public BulkWritePacket AddParam(ushort ADDR, ushort LEN, uint[] data, byte[] ids = null)
-
Argument
- ushort ADDR
- Address of the data field to be written. See Control Table of the model.
- ushort LEN
- Size of the data field to be written. See Control Table in the model.
- uint[] data
- Data to be written.
- byte[] id
- Target ID; if null is specified, the IDs held in DynamixelForUnity is targeted.
-
Returns
Itself.
-
Description
The information and data of the data field to be written are stored in IDParamPair.
-
Declaration
public BulkWritePacket AddParam(ControlTableAddressInfo addressInfo, uint[] data, byte[] ids = null)
-
Argument
- ControlTableAddressInfo addressInfo
- A structure containing the address, length, and access for each data field in the Control Table.
- uint[] data
- Data to be written.
- byte[] id
- Target ID; if null is specified, the ID held in DynamixelForUnity is targeted.
-
Returns
Itself.
-
Description
AddParam(ushort ADDR, ushort LEN, uint[] data, byte[] ids = null) is used to store the information and data of the data field to be written in IDParamPair. If the data field is read-only, it is not executed.
AddParamSigned
-
Declaration
public BulkWritePacket AddParamSigned(ushort ADDR, ushort LEN, int[] data, byte[] ids = null)
public BulkWritePacket AddParamSigned(ControlTableAddressInfo addressInfo, int[] data, byte[] ids = null)
-
Description
Stores information and signed data of the data field to be written in IDParamPair; see Description in AddParam.
Send
ResetStatus
Using BulkReadPacket
Executing bulk read includes the following steps:
1- Initiate struct to hold bulkread parameters.
2- Add parameters to the struct.
3- Send the bulkread command.
4- (Options) read result of executing the command.
5- Reading returned values from the servomotors.
The BulkReadPacket object is used to execute the above four steps by settings its properties and calling its methods as highlighting explained below.
Step 1. Initiate Struct
To initiate the struct to hold the parameters for the reading packet, you must first declare and initialize the relevant BulkdReadPacket object as follows:
BulkReadPacket readPacket = dynamixelForUnity.BulkGetDataGroup();
Step 2. Adding Parameters
Upon creating the BulkReadPacket object, the data to be read should be added to the created object as parameters. This can be done as follows:
readPacket.AddParam(addressInfo1, idArray1);
readPacket.AddParam(addressInfo2, idArray2);
readPacket.AddParam(addressInfo3, idArray3);
Step 3. Sending BulkRead Command
Upon adding the parameters, the command can be executed by calling the BulkReadPacket object’s Send() method, as shown below:
readPacket.Send();
Step 4. (Optional) Checking results of BulkRead Command Execution
You may optionally check the status of the command, whether it was successfully executed or not. You can check the property “AllSuccess” which is set to true if the command is successfully executed.
if(readPacket.AllSuccess)
Debug.Log("Successful");
Alternatively, you can directly place the BulkPacket object in an ‘if’ conditional to check if the command was successful.
if(readPacket)
Debug.Log("Successful");
Step 5. Reading returned values from the servomotors.
To read the data that was read from the servomotors after executing the bulkread command, you can use the method GetData() of the BulkReadPacket as follows:
uint[] data = readPacket.GetData();
Overall, you may execute the five steps and print out the results as follows:
Example:
if(var readPacket = dynamixelForUnity
.BulkGetDataGroup()
.AddParam(addressInfo1, idArray1)
.AddParam(addressInfo2, idArray2)
.AddParam(addressInfo3, idArray3)
.Send())
{
Debug.Log("Successful");
uint[] data = readPacket.GetData();
Debug.Log("Data: " + string.Join(", ", data));
}
Property
Name |
Description |
IDParamPair |
It is of type Dictionary<byte, ParamInfo>. This holds parameters for each ID. ParamInfo contains address, length, communication success, and data from servomotor. Read only. |
AllSuccess |
A boolean value indicating whether communication of all parameters was successful. Read only. |
HasSent |
A boolean value indicating whether the command was sent. Read only. |
AddParam
-
Declaration
public BulkReadPacket AddParam(ushort ADDR, ushort LEN, byte[] ids = null)
-
Argument
- ushort ADDR
- Address of the data field to be read. See Control Table of the model.
- ushort LEN
- Size of the data field to be read. See Control Table in the model.
- byte[] id
- Target ID; if null is specified, the ID held in DynamixelForUnity is targeted.
-
Returns
Itself.
-
Description
The information and data of the data field to be read are stored in IDParamPair.
-
Declaration
public BulkReadPacket AddParam(ControlTableAddressInfo addressInfo, byte[] ids = null)
-
Argument
- ControlTableAddressInfo addressInfo
- A structure containing the address, length, and access for each data field in the Control Table.
- byte[] id
- Target ID; if null is specified, the ID held in DynamixelForUnity is targeted.
-
Returns
Itself.
-
Description
AddParam(ushort ADDR, ushort LEN, byte[] ids = null) is used to store information about the data field to be read in IDParamPair.
Send
GetData
GetSignedData
ResetStatus
ParamInfo
Class representing data fields in BulkWritePacket and BulkReadPacket.
Variable
Name |
Description |
address |
Data address. |
length |
Length of data. |
isSuccess |
Whether the communication was successful or not. |
data |
In case of BulkWritePacket, data to be written; in case of BulkReadPacket, data to be read. |
ControlTables
A class that stores the Control Table for each servomotor; the Control Table is initialized by putting text written in the specified format into the constructor argument. The constructor takes either string[] or TextAsset[] as an argument.
Text files of Control Table for DynamxielForUnity compatible models are located in Assets/HatsuMuv/DynamixelForUnity/Resources/ControlTables. See ControlTableInjectorFromResources for usage examples.
ControlTables is the ControlTable of the servomotor to be used during initialization. The first line describes the model name and model number with “:” in between. The other lines describe the itemName, address, length, and access.
ItemName is derived from the item name in the ControlTable on Dynamixel’s model page, with spaces removed.
If the access is read-only, specify ‘R’; if writable, specify ‘RW’.
Lines beginning with “#” or “//” are ignored as comments.
<ModelName>:<ModelName>
<ItemName>, <Address>, <Length>, <Access>
<ItemName>, <Address>, <Length>, <Access>
...
Property
Name |
Description |
ModelNames |
This is of type Dictionary<int, string>. It records the correspondence between model numbers and model names from the read text data. |
-
Declaration
public ControlTableAddressInfo GetAddrssInfo(int modelNumber, string dataName)
public ControlTableAddressInfo this[int modelNumber, string dataName]
-
Argument
- int modelNumber
- Model Number.
- string dataName
- Data Name.
-
Returns
ControlTableAddressInfo type representing data field information.
-
Description
Returns a ControlTableAddressInfo type representing the data field information from the specified model number and data name. The indexer [int modelNubmer, string dataName] also produces the same result.
GetControlTable
-
Declaration
public Dictionary<string, ControlTableAddressInfo> GetControlTable(int modelNumber)
public Dictionary<string, ControlTableAddressInfo> this[int modelNumber]
-
Argument
- int modelNumber
- Model number of the subject.
-
Returns
Dictionary<string, ControlTableAddressInfo> type representing the control table.
-
Description
Returns a Dictionary<string, ControlTableAddressInfo> type representing the control table from the specified model number. The indexer [int modelNubmer] produces the same result.
Contains
-
Declaration
public bool Contains(int modelNumber)
-
Argument
- int modelNubmer
- The model number to look up.
-
Returns
Returns true if the Control Table with the specified model number exists, otherwise returns false.
-
Description
Returns whether the Control Table with the specified model number exists.
-
Declaration
public bool Contains(int modelNumber, string dataName)
-
Argument
- int modelNubmer
- The model number to look up.
- string dataName
- Name of the data to be examined.
-
Returns
Returns true if the Control Table with the specified model number exists and the data field with the specified data name exists, otherwise returns false.
-
Description
Returns whether a data field with a data name of the specified model number exists.
GetModelsContains
-
Declaration
public int[] GetModelsContains(string dataName)
-
Argument
- string dataName
- Name of the data to be examined.
-
Returns
An array of model numbers with data fields of the specified data name in the Control Table.
-
Description
Returns an array of model numbers that have data fields with the specified data name in the Control Table.
ControlTableAddressInfo
A structure representing information about data fields in the Control Table.
Variable
Name |
Description |
address |
Data address. |
length |
Length of data. |
readWrite |
True if writable, false if read-only. |
IControlTableUser
An Interface to inject control tables, implemented by DynamixelForUnity.
SetControlTables
- Declaration
public void SetControlTables(ControlTables controlTables)
Core
Dynamixel SDK compatible class. Put a HatsuVerif object in the constructor and create an instance.
6. Explanation of Example Scene
A sample scene is located within: HatsuMuv/DynamixelForUnity/Example/ExampleScene_x64.unity
This scene has a sample graphical-user interface (GUI) application using that uses DynamixelForUnity to open a com port, scan for servomotors, connect to servomotors, control servomotors and read various information from servomotors that are all displayed on the GUI.
Screen Explanation
- Select DynamixelForUnity gameobject in Hierarchy menu
-
In Inspector window, you can find a component called DynamixelForUnity. Enter your Email and SN, and the USB serial port which connected to your Dynamixel servomotor in the Device Name field. (You can find the port name from your Device manager, e.g. “COM3”).
-
(Optional) If you know the baudrate of the servomotor you want to operate, set the Baud Rate in the inspector of DynamixelForUnity beforehand. If you don’t know, leave it blank, D4U will scan for you. (Which can be time comsuming)
After setup DynamxielForUnity components, click play, Dynamixel4Unity will automatically attempt to open the designated port and connect to available servomotors.
The screen lists the connected Dynamixel servomotors. The connected baud rate is displayed at the top of the screen.
The read-only data items at the bottom are constantly updated (such as present position) .
The other items are updated when there is a change in the inserted data (for example, to set a new servomotor position).
Hint: If values differ from the actual value, try press the Refresh button to retrieve the data again.
Implementation Explanation
D4UExampleController
Start()
private async void Start()
{
NeedWait = true;
if (d4u == null)
{
Debug.LogError("[DynamixelForUnitySample] DynamixelForUnity is not assigned!");
return;
}
cancellationTokenSource = new CancellationTokenSource();
var connectResult = await Task.Run(() => InitializeDynamixel(cancellationTokenSource.Token));
if (connectResult) StartMotorMetrics();
NeedWait = false;
}
The NeedWait property is externally referenced to play the screen load animation.
DynamixelForUnity (d4u) is expected to be assigned by Inspector.
The cancellationTokenSource is created to interrupt asynchronous tasks.
Connect to the servomotor and execute the initialization method InitializeDynamixel asynchronously and wait for it.
Once the Dynamixel servomotor is connected by InitializeDynamixel, the StartMotorMetricsm method starts a loop that continuously measures the state of the servomotor.
InitializeDynamixel(CancellationToken ct)
private async Task<bool> InitializeDynamixel(CancellationToken ct)
{
if (d4u == null)
{
Debug.LogError("[DynamixelForUnitySample] DynamixelForUnity is not assigned!");
return false;
}
if (!d4u.ConnectStatus)
{
var connectResult = d4u.ConnectDynamixel();
if (!connectResult)
{
Debug.LogError("[DynamixelForUnitySample] Dynamixel is not connected. Connect it first.");
return false;
}
await d4u.SetUpAsync(cancellationToken:ct);
}
servomotors = new List<DynamixelMotor>();
ids = d4u.IDsForUse;
if (ids.Length == 0) return false;
await GetAllMotorProperty(ct);
return true;
}
The d4u.ConnectDynamixel method connects to the servomotor. You can also specify a port name and baudrate as arguments. In this case, the values entered in the Unity3D Inspector are ignored.
The SetUpAsync method calls two methods to scan the servomotor and hold the IDs found at once.
- Call the ScanInBaudRateAsync method to scan for Dynamixel servomotors at the specified port name and baudrate. If the servomotor is not found, it will start a scan in all baudrates and sets the port to the baudrate at which the servomotor is first found.
- Retains the ID and model number of the servomotor found by calling the SetIDsForUse method.
DynamixelForUnity retain servomotor IDs and model numbers, it is possible to send commands using only the data field names, and functions can be written to be concise when sending commands to all the servomotors.
Next, we use get all servomotor properties by calling GetAllMotorProperty method and create a DynamixelMotor instance.
GetAllMotorProperty(CancellationToken ct)
private async Task GetAllMotorProperty(CancellationToken ct)
{
OperatingMode[] operatingModes =
await Task.Run(() =>
d4u.SyncGetDataGroupMultiModels("OperatingMode")
.Select(d => (OperatingMode)d)
.ToArray(),
ct);
float[] homingOffsets = await Task.Run(() => d4u.SyncGetSignedDataGroupMultiModels("HomingOffset").ToActualNumber(UNIT.POSITION).ToFloatArray(), ct);
...
for (int i = 0; i < ids.Length; i++)
{
DynamixelMotor m;
if (motors.Count < i + 1)
{
m = new DynamixelMotor(ids[i]);
servomotors.Add(m);
}
else
{
m = servomotors[i];
}
m.OperatingMode = operatingModes[i];
m.HomingOffset = homingOffsets[i];
...
}
}
Each and every property of the DynamixelMotor class is obtained by the method SyncGetSignedDataGroupMultiModels. One property is explained using an example.
float[] homingOffsets =
await Task.Run(
() => d4u.SyncGetSignedDataGroupMultiModels("HomingOffset")
.ToActualNumber(UNIT.POSITION)
.ToFloatArray(),
ct
);
The line that initializes homingOffsets has a line break for clarity.
The second line, Task.Run method, executes the function of the first argument asynchronously in a separate thread.
From the third line, it is the function you want to execute in a separate thread.
d4u.SyncGetSignedDataGroupMultiModels(“HomingOffset”) retrieves the value of the “HomingOffset” data field for all servomotors stored in DynamixelForUnity.
ToActualNumber(UNIT.POSITION) applies units to the raw data obtained from the SyncGetSignedDataGroupMultiModels.
ToFloatArray() converts a double[] to a float[].
MotorMetrics is a similar method that strips some data from GetAllMotorProperty.
StartMotorMetrics()
servomotorMetricsLoop(CancellationToken ct)
StopMotorMetrics()
private void StartMotorMetrics()
{
if (!d4u.ConnectStatus)
return;
cancellationTokenSource = cancellationTokenSource ?? new CancellationTokenSource();
var cancellationToken = cancellationTokenSource.Token;
metricsLoop = servomotorMetricsLoop(cancellationToken);
}
private async Task servomotorMetricsLoop(CancellationToken ct)
{
while (true)
{
if (ct.IsCancellationRequested)
return;
Debug.Log("[SampleController] Metrics");
try
{
await servomotorMetrics(ct);
}
catch (OperationCanceledException)
{
Debug.Log("[SampleController] Metrics canceled");
return;
}
catch (Exception e)
{
Debug.LogError(e);
return;
}
}
}
private async Task StopMotorMetrics()
{
if (cancellationTokenSource != null && !cancellationTokenSource.IsCancellationRequested)
{
cancellationTokenSource.Cancel();
cancellationTokenSource.Dispose();
cancellationTokenSource = null;
if(metricsLoop != null)
await metricsLoop;
}
}
MotorMetricsLoop continues to call servomotorMetrics until it is canceled by CancellationToken. StopMotorMetrics cancels servomotorMetrics and waits for the process to finish.
D4UExampleUI
Generate UI elements. Generates a panel for each servomotor from D4UExampleController and updates those data.
D4UExampleUIElement
It directly controls the fields in each panel; when it receives input from a UI element, it passes the value to D4UExampleContorller.
Table of Contents
1. Overview
DynamixelforUnity (D4U) is an asset to easily implement Dynamixel servomotor control within in Unity3D. D4U provides numerous methods to interface with Dynamixel servomotors, enabling you to efficiently and easily connect, control, and read data from a variety of Dynamixel servomotors.
Specificially, D4U focuses on the following feature sets:
Therefore, users are able to completely focus on writing all robot control code from within Unity3D, using simple code in C# that can easily be integrated with a variety of applications, games, simulations or other experiences and use cases that leverage Unity3D.
Supported OS
Supported protocol
Supported Dynamixel models
Model compatible with DYNAMIXEL Protocol 2.0.
2. Installation
With the Unity3D project you want to use, double-click DynamixelForUnity.unitypackage, or drag and drop it into the Project window of the Unity3D project. A pop-up will appear, please choose to improt the package and all its contents to your project.
3. License Purchase and Activation
A license must be purchased from HatsuMuv site in order to use D4U with complete expirence. Without a license, you can only use 10 operations for every execution.
After the purcahse, you will recieve a link to a form, where you are required to provide various information, including device ID, which is a unique ID number that is used to link your license to the machine D4U will be used on:
To generate your device ID and insert it in the above form, click Get DeviceID for Registration in your toolbar. It will automatically copy your device ID to your clip board and shows in consle window. Please follow the instructions shown in the screenshot below:
After your purchase D4U, you will recieve an SN by email. To use your SN within D4U, please insert your Email and SN in the D4U verificate method or through the Dynamixel For Unity Component in Unity3D UI as shown below:
To check your verify your activation, simply run your scene, and you can check if the activation is correct or not in consle.
4. Quick Start
Here is a demo that gets and sets the positions of 2 Dynamixel servomotors.
Before Starting, Assigning ID Numbers to Your New DYNAMIXEL Servos
Before you start this demo, you will need to set your Dynamixel Servos with different IDs.
The simplest way to do this is by using ROBOTIS’ DYNAMIXEL Wizard 2.0 Software. Please refers to ROBOTIS website to search for ID
Setting up a new scene
In Inspector window, you can find a component called DynamixelForUnity. Enter your Email and SN, and the USB serial port which connected to your Dynamixel servomotor in the Device Name field. (You can find the port name from your Device manager, e.g. “COM3”).
(Optional) If you know the baudrate of the servomotor you want to operate, set the Baud Rate in the inspector of DynamixelForUnity beforehand. If you don’t know, leave it blank, D4U SetUp method will scan for you. (Which can be time comsuming)
“Click Add Component” Button, and input script name as you like (For this time, “Demo”). Then click “New script”.
Coding C# script
When Visual Studio opens, write as below. This code prints the current positions of two servomotors to Debug.Log and then sets their goal positions to 1024 each.
Execution
Return to the Unity screen and click the Play button.
The position of the servomotor will be printed on the console.
5. Script Reference
Select a namespace from the following according to your system configuration.
DynamixelForUnity
DynamixelForUnity is a class provided to control Dynamixel servomotors with declarative program.
Declarative programming: Describe what you want, not how to do it. For more details, please search for ‘Declarative Programming’.
One DynamixelForUnity component manage one port. If you want to control multiple ports simultaneously, please add as many components as the number of ports.
DynamixelForUnity is implementing IControlTableUser.
Flow of Use:
Here is Example.
using HatsuMuv.DynamixelForUnity.x64; public class ExampleClass : MonoBehaviour { DynamixelForUnity d4u; void Start() { d4u = GetComponent<DynamxielForUnity>(); // If the SN code and email address are not set in the inspector, this code is necessary. // d4u.Verificate(); d4u.ConnectDynamixel(); d4u.SetUp(); // something you want to do. d4u.SetData("TorqueEnable", 1, 1); } void OnApplicationQuit() { // Termination procedure d4u.SetData("TorqueEnable", 0, 1) } }
Constant
Variables
Debug.Log. Errors and warnings are not affected.
Propertyies
Verificate
Declaration
public bool Verificate(HatsuVerif verif)
Argument
Returns
License validity.
Description
This function is used for validating your license, which will be automatically called (Awake function) if you put DynamxielForUnity in your gameobject as component from beginning. If you new a instant after pressing play, you will need to run this method to validate your license before you start to use D4U’s functions.
Declaration
public bool Verificate(string userEmail, string userSN, bool forceRenew = false)
Returns
License validity.
ConnectDynamixel
Declaration
public bool ConnectDynamixel()
public bool ConnectDynamixel(string deviceName)
public bool ConnectDynamixel(BaudRate baudRate)
public bool ConnectDynamixel(string deviceName, BaudRate baudRate)
Argument
Returns
Returns true if the connection succeeds, false otherwise.
Description
Opens a port with the specified baud rate and connects to the Dynamixel servomotor. If no port or baud rate is specified, the value specified in the inspector is used.
ScanInBaudRate
Declaration
public byte[] ScanInBaudRate(BaudRate baudRate, byte[] idsForScan = null)
Argument
Returns
Byte array of available servomotor IDs.
Description
Ping the Dynamixel servomotor at the specified baud rate and scan it; use the SetBaudRate method to change to the specified baud rate.
Declaration
public byte[] ScanInBaudRate(BaudRate baudRate, byte minIDsForScan, byte maxIDsForScan)
Argument
Returns
Byte array of available servomotor IDs.
Description
Ping the Dynamixel servomotor at the specified baud rate and scan it, using the SetBaudRate method to change to the specified baud rate. The scan target can be specified in a range.
ScanInBaudRateAsync
Declaration
public async Task<byte[]> ScanInBaudRateAsync(BaudRate baudRate, byte[] idsForScan = null, CancellationToken cancellationToken = default(CancellationToken))
Argument
Returns
Byte array of available servomotor IDs.
Description
Asynchronously pings and scans Dynamixel servomotors at the specified baud rate; changes to the specified baud rate using the SetBaudRate method.
Declaration
public async Task<byte[]> ScanInBaudRateAsync(BaudRate baudRate, byte minIDsForScan, byte maxIDsForScan, CancellationToken cancellationToken = default(CancellationToken))
Argument
Returns
Byte array of available servomotor IDs.
Description
Asynchronously pings and scans Dynamixel servomotors at a specified baud rate, using the SetBaudRate method to change to the specified baud rate. The scan target can be specified in a range.
Ping
Declaration
public bool Ping(byte ID, bool hideErrorMsg = true)
Argument
Returns
Whether they are connected.
Description
Ping the specified ID to check if it is connected.
PingGetModelNumber
Declaration
public int PingGetModelNumber(byte ID)
Argument
Returns
Model number. When communication fails, -1 is returned.
Description
Ping the specified ID to obtain the model number.
GetAllModelNumber
Declaration
public int[] GetAllModelNumber(byte[] ids = null)
Argument
Returns
An array of model numbers. Items for which communication failed are marked with -1.
Description
Ping the specified multiple IDs and return an array of model numbers.
SetControlTable
Declaration
public void SetControlTable(ControlTables controlTables)
Argument
Description
Implementation of IControlTableUser. Sets the control table.
SetUp
Declaration
public byte[] SetUp(BaudRate? baudRate = null, byte[] idsForScan = null, bool scanAllBaudRateIfNotFound = true)
Argument
Returns
Byte array of available servomotor IDs.
Description
Scan the dynamixel servomotor with the ScanInBaudRate method and hold the scanned ID as the servomotor to be used with the SetIDsForUse method.
SetUpAsync
Declaration
public async Task<byte[]> SetUpAsync(BaudRate? baudRate = null, byte[] idsForScan = null, bool scanAllBaudRateIfNotFound = true, CancellationToken cancellationToken = default(CancellationToken))
Argument
Returns
Byte array of available servomotor IDs.
Description
Asynchronously scan the dynamixel servomotor with the ScanInBaudRateAsync method and hold the scanned ID as the servomotor to be used with the SetIDsForUse method.
SetIDsForUse
Declaration
public void SetIDsForUse(byte[] idsForUse)
Argument
Description
Keep the ID as a target for use and associate it with the model number.
By having DynamixelForUnity retain the servomotor ID and model number, it is possible to send commands using only the data field names, or to write concisely when sending commands to all servomotors.
DisconnectDynamixel
Declaration
public void DisconnectDynamixel()
Description
Close the port.
CloseAndReopenPort
Declaration
public void CloseAndReopenPort(bool withSetBaudRate = true)
Argument
Description
Close and reopen the port.
RebootDynamixel
Declaration
public void RebootDynamixel(byte[] ids = null)
Argument
Description
Reboot the Dynamixel servomotor.
FactoryResetDynamixel
Declaration
public void FactoryResetDynamixel(DynamixelFactoryResetMode mode, byte[] ids = null)
Argument
Description
Reset the Dynamixel servomotor to the factory defaults.
SetBaudRate
Declaration
public bool SetBaudRate(BaudRate baudRate)
Argument
Returns
Returns true if successful, false otherwise.
Description
Set the baudrate of the port.
SetData
Declaration
public bool SetData(ushort ADDR, ushort LEN, uint data, byte id)
Argument
Returns
Returns true if successful, false otherwise.
Description
Writes data to the Dynamixel servomotor with the specified ID.
Check the Contorol Table from the ROBOTIS e-Manual of each Dynamixel servomotor for the address and length of the data field.
Declaration
public bool SetData(ControlTableAddressInfo addressInfo, uint data, byte id)
Argument
Returns
Returns true if successful, false otherwise.
Description
SetData(ushort ADDR, ushort LEN, uint data, byte id) is used to write data to the Dynamixel servomotor with the specified ID. If the data field is read-only (e.g. present position), this method will not execute the command.
Declaration
public bool SetData(string dataName, uint data, byte id)
Argument
Returns
Returns true if successful, false otherwise.
Description
SetData(ushort ADDR, ushort LEN, uint data, byte id) is used to write data to the Dynamixel servomotor with the specified ID. If the data field is read-only, it is not executed.
d4u.SyncGetSignedDataGroupMultiModels("GoalPosition").ToActualNumber(UNIT.POSITION).ToFloatArray(), ct);
The ID and model number must be retained by the SetUp or SetIDsForUse method to be used.
SetSignedData
Declaration
public bool SetSignedData(ushort ADDR, ushort LEN, uint data, byte id)
public bool SetSignedData(ControlTableAddressInfo addressInfo, int data, byte id)
public bool SetSignedData(string dataName, int data, byte id)
Description
Writes signed data to the Dynamixel servomotor with the specified ID, see Description of SetData.
GetData
Declaration
public uint GetData(ushort ADDR, ushort LEN, byte id)
Argument
Returns
Data read. Returns 0 if an error occurs.
Description
Reads the data of the Dynamixel servomotor with the specified ID.
Check the Contorol Table from the ROBOTIS e-Manual of each Dynamixel servomotor for the address and length of the data field.
Declaration
public uint GetData(ControlTableAddressInfo addressInfo, byte id)
Argument
Returns
Data read. Returns 0 if an error occurs.
Description
GetData(ushort ADDR, ushort LEN, byte id) is used to read data of a servomotor by specifying it’s ID.
Declaration
public uint GetData(string dataName, byte id)
Argument
Returns
Data read. Returns 0 if an error occurs.
Description
GetData(ushort ADDR, ushort LEN, byte id) is used to read data from a servomotor by specifying it’s ID.
The ID and model number must be created in using either the SetUp method or SetIDsForUse method to be used.
GetSignedData
Declaration
public int GetSignedData(ushort ADDR, ushort LEN, byte id)
public int GetSignedData(ControlTableAddressInfo addressInfo, byte id)
public int GetSignedData(string dataName, byte id)
Description
Reads the signed data of the Dynamixel servomotor with the specified ID, see Description of GetData.
SyncSetDataGroup
Declaration
public bool SyncSetDataGroup(ushort ADDR, ushort LEN, uint[] data, byte[] ids = null)
public bool SyncSetDataGroup(ControlTableAddressInfo addressInfo, uint[] data, byte[] ids = null)
Argument
Returns
Returns true if successful, false otherwise.
Description
Writes data to multiple servomotors simultaneously using GroupSyncWrite.
SyncSetDataGroupMultiModels
Declaration
public bool SyncSetDataGroupMultiModels(string dataName, uint[] data, byte[] ids = null)
Description
Writes data to multiple servomotors at the same time using GroupSyncWrite method. If the item names on the ControlTable are the same, the data will be sent to different addresses. In that case, call SyncSetDataGroup for each unique address; see Description of SyncSetDataGroup.
The ID and model number must be retained by the SetUp or SetIDsForUse method to be used.
SyncSetSignedDataGroup
Declaration
public bool SyncSetSignedDataGroup(ushort ADDR, ushort LEN, int[] data, byte[] ids = null)
public bool SyncSetSignedDataGroup(ControlTableAddressInfo addressInfo, int[] data, byte[] ids = null)
Description
Writes signed data to multiple servomotors simultaneously using GroupSyncWrite; see SyncSetDataGroup Description.
SyncSetSignedDataGroupMultiModels
Declaration
public bool SyncSetSignedDataGroupMultiModels(string dataName, int[] data, byte[] ids = null)
Description
Write signed data to multiple servomotors simultaneously using GroupSyncWrite method, see Description of SyncSetDataGroupMultiModels.
The ID and model number must be retained by the SetUp or SetIDsForUse method to be used.
SyncGetDataGroup
Declaration
public uint[] SyncGetDataGroup(ushort ADDR, ushort LEN, byte[] ids = null)
public uint[] SyncGetDataGroup(ControlTableAddressInfo addressInfo, byte[] ids = null)
Argument
Returns
uint array containing the read after executing the SyncGetDataGroup.
Description
Read data from multiple servomotors simultaneously using GroupSyncRead.
SyncGetDataGroupMultiModels
Declaration
public uint[] SyncGetDataGroupMultiModels(string dataName, byte[] ids = null)
Description
Simultaneously read data from multiple servomotors using GroupSyncRead method. If the item names on the ControlTable are the same, the data will be sent to different addresses. In that case, call SyncSetDataGroup for each unique address; see Description of SyncGetDataGroup.
The ID and model number must be retained by the SetUp or SetIDsForUse method to be used.
SyncGetSignedDataGroup
Declaration
public int[] SyncGetSignedDataGroup(ushort ADDR, ushort LEN, byte[] ids = null)
public int[] SyncGetSignedDataGroup(ControlTableAddressInfo addressInfo, byte[] ids = null)
Description
Read signed data to multiple servomotors simultaneously using GroupSyncRead, see Description of SyncGetDataGroup.
SyncGetSignedDataGroupMultiModels
Declaration
public int[] SyncGetSignedDataGroupMultiModels(string dataName, byte[] ids = null)
Description
Read signed data to multiple servomotors simultaneously using GroupSyncRead, see Description of SyncGetDataGroupMultiModels.
The ID and model number must be retained by the SetUp or SetIDsForUse method to be used.
BulkSetDataGroup
Declaration
public BulkWritePacket BulkSetDataGroup()
Returns
BulkWritePacket object.
Description
Returns a BulkWritePacket object for writing data to multiple servomotors at once using GroupBulkWrite.
GroupBulkWrite is described in a method chain mediated by BulkWritePacket.
BulkGetDataGroup
Declaration
public BulkReadPacket BulkGetDataGroup()
Returns
BulkReadPacket object.
Description
Returns a BulkReadPacket object for reading data in batches to multiple servomotors using GroupBulkRead.
GroupBulkRead is described in a method chain mediated by BulkReadPacket.
Using the Control Table
We created a text file to represent the control table of each Dynamixel servomotor. The control tables map each property name to the corresponding register number within for servomotor model.
The control tables correspond to the servomotor control tables found in ROBOTIS e-Manual.
Please check the control table data under D4U HatsuMuv/DynamixelForUnity/Resources/ControlTables/ and find the corresponding servomotor, as shown in the screenshot below:
The control tables can be used as parameters in a variety of methods in D4U, where you can pass the parameter name as a string to control or get feedback from various servomotors, as shown in the example below
// you may pass a control table parameter to read in the below method, where the control table parameter corresponds to the string representation of the register you need to set/read. // This example uses wet a group of data through sync method SyncGetDataGroupMultiModels("GoalPosition");
Using BulkWritePacket
Executing bulk write includes the following steps:
1- Initiate struct to hold bulk write parameters.
2- Add parameters to the struct.
3- Send the bulkwrite command.
4- (Options) read result of executing the command.
The BulkWritePacket object is used to execute the above four steps by settings its properties and calling its methods as highlighting explained below.
Step 1. Initiate Struct
To initiate the struct to hold the parameters for the writing packet, you must first declare and initialize the relevant BulkWritePacket objects as follows:
// bulk write packet BulkWritePacket writePacket = dynamixelForUnity.BulkSetDataGroup();
Step 2. Adding Parameters
Upon creating the BulkWritePacket object, the data to be written should be added to the created object as parameters. This can be done as follows:
writePacket.AddParam(addressInfo1, idArray1, data1); // you may add as many parameters as needed writePacket.AddParam(addressInfo2, idArray2, data2); writePacket.AddParam(addressInfo3, idArray3, data3);
Step 3. Sending BulkWrite Command
Upon adding the parameters, the command can be executed by calling the BulkWritePacket object’s Send() method, as shown below:
Step 4. (Optional) Checking results of BulkWrite Command Execution
You may optionally check the status of the command, whether it was successfully executed or not. You can check the property “AllSuccess” which is set to true if the command is successfully executed.
if(writePacket.AllSuccess) Debug.Log("Successful");
Alternatively, you can directly place the BulkPacket object in an ‘if’ conditional to check if the command was successful.
if(writePacket) Debug.Log("Successful");
Overall, you may execute the four steps in one line efficiently as follows:
Example:
if(dynamixelForUnity .BulkSetDataGroup() .AddParam(addressInfo1, idArray1, data1) .AddParam(addressInfo2, idArray2, data2) .AddParam(addressInfo3, idArray3, data3) .Send()) Debug.Log("Successful");
Properties
AddParam
Declaration
public BulkWritePacket AddParam(ushort ADDR, ushort LEN, uint[] data, byte[] ids = null)
Argument
Returns
Itself.
Description
The information and data of the data field to be written are stored in IDParamPair.
Declaration
public BulkWritePacket AddParam(ControlTableAddressInfo addressInfo, uint[] data, byte[] ids = null)
Argument
Returns
Itself.
Description
AddParam(ushort ADDR, ushort LEN, uint[] data, byte[] ids = null) is used to store the information and data of the data field to be written in IDParamPair. If the data field is read-only, it is not executed.
AddParamSigned
Declaration
public BulkWritePacket AddParamSigned(ushort ADDR, ushort LEN, int[] data, byte[] ids = null)
public BulkWritePacket AddParamSigned(ControlTableAddressInfo addressInfo, int[] data, byte[] ids = null)
Description
Stores information and signed data of the data field to be written in IDParamPair; see Description in AddParam.
Send
Declaration
public BulkWritePacket Send(bool discardAllWhenErrorHappen = false)
Argument
Returns
Itself.
Description
Send GroupBulkWrite command to servomotors based on IDParamPair.
ResetStatus
Declaration
public void ResetStatus()
Description
Reset communication results and transmission flags. The data to be written is not deleted.
Using BulkReadPacket
Executing bulk read includes the following steps:
1- Initiate struct to hold bulkread parameters.
2- Add parameters to the struct.
3- Send the bulkread command.
4- (Options) read result of executing the command.
5- Reading returned values from the servomotors.
The BulkReadPacket object is used to execute the above four steps by settings its properties and calling its methods as highlighting explained below.
Step 1. Initiate Struct
To initiate the struct to hold the parameters for the reading packet, you must first declare and initialize the relevant BulkdReadPacket object as follows:
// bulk read packet BulkReadPacket readPacket = dynamixelForUnity.BulkGetDataGroup();
Step 2. Adding Parameters
Upon creating the BulkReadPacket object, the data to be read should be added to the created object as parameters. This can be done as follows:
readPacket.AddParam(addressInfo1, idArray1); // you may add as many parameters as needed readPacket.AddParam(addressInfo2, idArray2); readPacket.AddParam(addressInfo3, idArray3);
Step 3. Sending BulkRead Command
Upon adding the parameters, the command can be executed by calling the BulkReadPacket object’s Send() method, as shown below:
Step 4. (Optional) Checking results of BulkRead Command Execution
You may optionally check the status of the command, whether it was successfully executed or not. You can check the property “AllSuccess” which is set to true if the command is successfully executed.
if(readPacket.AllSuccess) Debug.Log("Successful");
Alternatively, you can directly place the BulkPacket object in an ‘if’ conditional to check if the command was successful.
if(readPacket) Debug.Log("Successful");
Step 5. Reading returned values from the servomotors.
To read the data that was read from the servomotors after executing the bulkread command, you can use the method GetData() of the BulkReadPacket as follows:
Overall, you may execute the five steps and print out the results as follows:
Example:
if(var readPacket = dynamixelForUnity .BulkGetDataGroup() .AddParam(addressInfo1, idArray1) .AddParam(addressInfo2, idArray2) .AddParam(addressInfo3, idArray3) .Send()) { Debug.Log("Successful"); uint[] data = readPacket.GetData(); Debug.Log("Data: " + string.Join(", ", data)); }
Property
AddParam
Declaration
public BulkReadPacket AddParam(ushort ADDR, ushort LEN, byte[] ids = null)
Argument
Returns
Itself.
Description
The information and data of the data field to be read are stored in IDParamPair.
Declaration
public BulkReadPacket AddParam(ControlTableAddressInfo addressInfo, byte[] ids = null)
Argument
Returns
Itself.
Description
AddParam(ushort ADDR, ushort LEN, byte[] ids = null) is used to store information about the data field to be read in IDParamPair.
Send
Declaration
public BulkReadPacket Send(bool discardAllWhenErrorHappen = false)
Argument
Returns
Itself.
Description
Send GroupBulkRead command to Dynamxiel servomotor based on IDParamPair.
GetData
Declaration
public uint[] GetData(bool resetStatus = false)
Argument
Returns
Data array read.
Description
Retrieve the read data array.
GetSignedData
Declaration
public int[] GetSignedData(bool resetStatus = false)
Argument
Returns
Data array read.
Description
Retrieve the signed data array that was read.
ResetStatus
Declaration
public void ResetStatus()
Description
Reset communication results and transmission flags. The read data is also deleted.
ParamInfo
Class representing data fields in BulkWritePacket and BulkReadPacket.
Variable
ControlTables
A class that stores the Control Table for each servomotor; the Control Table is initialized by putting text written in the specified format into the constructor argument. The constructor takes either string[] or TextAsset[] as an argument.
Text files of Control Table for DynamxielForUnity compatible models are located in Assets/HatsuMuv/DynamixelForUnity/Resources/ControlTables. See ControlTableInjectorFromResources for usage examples.
ControlTables is the ControlTable of the servomotor to be used during initialization. The first line describes the model name and model number with “:” in between. The other lines describe the itemName, address, length, and access.
ItemName is derived from the item name in the ControlTable on Dynamixel’s model page, with spaces removed.
If the access is read-only, specify ‘R’; if writable, specify ‘RW’.
Lines beginning with “#” or “//” are ignored as comments.
Property
GetAddrssInfo
Declaration
public ControlTableAddressInfo GetAddrssInfo(int modelNumber, string dataName)
public ControlTableAddressInfo this[int modelNumber, string dataName]
Argument
Returns
ControlTableAddressInfo type representing data field information.
Description
Returns a ControlTableAddressInfo type representing the data field information from the specified model number and data name. The indexer [int modelNubmer, string dataName] also produces the same result.
GetControlTable
Declaration
public Dictionary<string, ControlTableAddressInfo> GetControlTable(int modelNumber)
public Dictionary<string, ControlTableAddressInfo> this[int modelNumber]
Argument
Returns
Dictionary<string, ControlTableAddressInfo> type representing the control table.
Description
Returns a Dictionary<string, ControlTableAddressInfo> type representing the control table from the specified model number. The indexer [int modelNubmer] produces the same result.
Contains
Declaration
public bool Contains(int modelNumber)
Argument
Returns
Returns true if the Control Table with the specified model number exists, otherwise returns false.
Description
Returns whether the Control Table with the specified model number exists.
Declaration
public bool Contains(int modelNumber, string dataName)
Argument
Returns
Returns true if the Control Table with the specified model number exists and the data field with the specified data name exists, otherwise returns false.
Description
Returns whether a data field with a data name of the specified model number exists.
GetModelsContains
Declaration
public int[] GetModelsContains(string dataName)
Argument
Returns
An array of model numbers with data fields of the specified data name in the Control Table.
Description
Returns an array of model numbers that have data fields with the specified data name in the Control Table.
ControlTableAddressInfo
A structure representing information about data fields in the Control Table.
Variable
IControlTableUser
An Interface to inject control tables, implemented by DynamixelForUnity.
SetControlTables
public void SetControlTables(ControlTables controlTables)
Core
Dynamixel SDK compatible class. Put a HatsuVerif object in the constructor and create an instance.
6. Explanation of Example Scene
A sample scene is located within: HatsuMuv/DynamixelForUnity/Example/ExampleScene_x64.unity
This scene has a sample graphical-user interface (GUI) application using that uses DynamixelForUnity to open a com port, scan for servomotors, connect to servomotors, control servomotors and read various information from servomotors that are all displayed on the GUI.
Screen Explanation
In Inspector window, you can find a component called DynamixelForUnity. Enter your Email and SN, and the USB serial port which connected to your Dynamixel servomotor in the Device Name field. (You can find the port name from your Device manager, e.g. “COM3”).
(Optional) If you know the baudrate of the servomotor you want to operate, set the Baud Rate in the inspector of DynamixelForUnity beforehand. If you don’t know, leave it blank, D4U will scan for you. (Which can be time comsuming)
After setup DynamxielForUnity components, click play, Dynamixel4Unity will automatically attempt to open the designated port and connect to available servomotors.
The screen lists the connected Dynamixel servomotors. The connected baud rate is displayed at the top of the screen.
The read-only data items at the bottom are constantly updated (such as present position) .
The other items are updated when there is a change in the inserted data (for example, to set a new servomotor position).
Hint: If values differ from the actual value, try press the Refresh button to retrieve the data again.
Implementation Explanation
D4UExampleController
Start()
private async void Start() { NeedWait = true; if (d4u == null) { Debug.LogError("[DynamixelForUnitySample] DynamixelForUnity is not assigned!"); return; } cancellationTokenSource = new CancellationTokenSource(); var connectResult = await Task.Run(() => InitializeDynamixel(cancellationTokenSource.Token)); if (connectResult) StartMotorMetrics(); NeedWait = false; }
The NeedWait property is externally referenced to play the screen load animation.
DynamixelForUnity (d4u) is expected to be assigned by Inspector.
The cancellationTokenSource is created to interrupt asynchronous tasks.
Connect to the servomotor and execute the initialization method InitializeDynamixel asynchronously and wait for it.
Once the Dynamixel servomotor is connected by InitializeDynamixel, the StartMotorMetricsm method starts a loop that continuously measures the state of the servomotor.
InitializeDynamixel(CancellationToken ct)
private async Task<bool> InitializeDynamixel(CancellationToken ct) { if (d4u == null) { Debug.LogError("[DynamixelForUnitySample] DynamixelForUnity is not assigned!"); return false; } if (!d4u.ConnectStatus) { var connectResult = d4u.ConnectDynamixel(); if (!connectResult) { Debug.LogError("[DynamixelForUnitySample] Dynamixel is not connected. Connect it first."); return false; } await d4u.SetUpAsync(cancellationToken:ct); } servomotors = new List<DynamixelMotor>(); ids = d4u.IDsForUse; if (ids.Length == 0) return false; await GetAllMotorProperty(ct); return true; }
The d4u.ConnectDynamixel method connects to the servomotor. You can also specify a port name and baudrate as arguments. In this case, the values entered in the Unity3D Inspector are ignored.
The SetUpAsync method calls two methods to scan the servomotor and hold the IDs found at once.
DynamixelForUnity retain servomotor IDs and model numbers, it is possible to send commands using only the data field names, and functions can be written to be concise when sending commands to all the servomotors.
Next, we use get all servomotor properties by calling GetAllMotorProperty method and create a DynamixelMotor instance.
GetAllMotorProperty(CancellationToken ct)
private async Task GetAllMotorProperty(CancellationToken ct) { OperatingMode[] operatingModes = await Task.Run(() => d4u.SyncGetDataGroupMultiModels("OperatingMode") .Select(d => (OperatingMode)d) .ToArray(), ct); float[] homingOffsets = await Task.Run(() => d4u.SyncGetSignedDataGroupMultiModels("HomingOffset").ToActualNumber(UNIT.POSITION).ToFloatArray(), ct); ... for (int i = 0; i < ids.Length; i++) { DynamixelMotor m; if (motors.Count < i + 1) { m = new DynamixelMotor(ids[i]); servomotors.Add(m); } else { m = servomotors[i]; } m.OperatingMode = operatingModes[i]; m.HomingOffset = homingOffsets[i]; ... } }
Each and every property of the DynamixelMotor class is obtained by the method SyncGetSignedDataGroupMultiModels. One property is explained using an example.
float[] homingOffsets = await Task.Run( () => d4u.SyncGetSignedDataGroupMultiModels("HomingOffset") .ToActualNumber(UNIT.POSITION) .ToFloatArray(), ct );
The line that initializes homingOffsets has a line break for clarity.
The second line, Task.Run method, executes the function of the first argument asynchronously in a separate thread.
From the third line, it is the function you want to execute in a separate thread.
d4u.SyncGetSignedDataGroupMultiModels(“HomingOffset”) retrieves the value of the “HomingOffset” data field for all servomotors stored in DynamixelForUnity.
ToActualNumber(UNIT.POSITION) applies units to the raw data obtained from the SyncGetSignedDataGroupMultiModels.
ToFloatArray() converts a double[] to a float[].
MotorMetrics is a similar method that strips some data from GetAllMotorProperty.
StartMotorMetrics()
servomotorMetricsLoop(CancellationToken ct)
StopMotorMetrics()
private void StartMotorMetrics() { if (!d4u.ConnectStatus) return; cancellationTokenSource = cancellationTokenSource ?? new CancellationTokenSource(); var cancellationToken = cancellationTokenSource.Token; metricsLoop = servomotorMetricsLoop(cancellationToken); } private async Task servomotorMetricsLoop(CancellationToken ct) { while (true) { if (ct.IsCancellationRequested) return; Debug.Log("[SampleController] Metrics"); try { await servomotorMetrics(ct); } catch (OperationCanceledException) { Debug.Log("[SampleController] Metrics canceled"); return; } catch (Exception e) { Debug.LogError(e); return; } } } private async Task StopMotorMetrics() { if (cancellationTokenSource != null && !cancellationTokenSource.IsCancellationRequested) { cancellationTokenSource.Cancel(); cancellationTokenSource.Dispose(); cancellationTokenSource = null; if(metricsLoop != null) await metricsLoop; } }
MotorMetricsLoop continues to call servomotorMetrics until it is canceled by CancellationToken. StopMotorMetrics cancels servomotorMetrics and waits for the process to finish.
D4UExampleUI
Generate UI elements. Generates a panel for each servomotor from D4UExampleController and updates those data.
D4UExampleUIElement
It directly controls the fields in each panel; when it receives input from a UI element, it passes the value to D4UExampleContorller.