CHANGELOG
This file records the change history of this project.
v0.1.2 - 2026-09-09
Fixed
Corrected motion execution result handling for the Dobot MG400.
Fixed an issue where
move()was considered successful solely because aJointMovJ,MovJ, orMovLcommand had been accepted.For blocking motion, the robot’s error state is now checked after
Sync(), andFalseis returned if an alarm occurs during execution.Execution errors occurring after command acceptance are now detected using the Feedback
ErrorStatusandGetErrorID().Failed responses from the motion commands themselves continue to be treated as failures.
Corrected retrieval and display of Dobot alarm information.
The
GetErrorID()response is now parsed while preserving the Controller / Servo distinction, rather than flattening it into a simple integer sequence.Fixed an implementation in which alarm definitions could overwrite each other when Controller and Servo alarms shared the same alarm ID.
Error messages now include the alarm ID and its source.
Japanese text from the alarm definition’s
jpfield is preferred; when unavailable, the existing language is used as a fallback.Both
descriptionandsolutionare now retrieved and displayed.Only information actually present in alarm definitions is displayed; missing information is neither inferred nor fabricated.
Cleaned up raw
GetErrorID()response logging.Nested arrays used for internal parsing are no longer written to normal
INFOlogs.Raw
GetErrorID()responses are now logged atDEBUGlevel.Normal operation displays parsed and formatted alarm information.
Refactored
Moved error handling previously concentrated in
dobot_tcp.pyintodobot_error.py.Added
DobotErrorManager.Separated retrieval and parsing of
GetErrorID().Separated identification of Controller / Servo alarms.
Separated loading and indexing of alarm JSON data.
Separated generation of error descriptions.
Separated motion error detection using Feedback
ErrorStatus.Separated error monitoring immediately after motion commands.
Preserved compatibility of the public error APIs of
DobotTcp:get_error()get_error_code()get_error_count()get_error_info()get_error_description()get_current_error_info()error_codeerror_description
These APIs remain available; only their internal implementation is delegated to
DobotErrorManager.
Compatibility
The vendor-supplied
dobot_api.pyremains unchanged.The existing public interface of
DobotTcpis preserved.
v0.1.1 - 2026-09-09
Changes
Reorganized acquisition of actual MG400 robot state.
current_positionis obtained from Dashboard APIGetPose().current_angleis obtained from Dashboard APIGetAngle().servo_onis obtained from FeedbackEnableStatus.busy_statusis determined from FeedbackRunningStatus/JogStatus.state()uses FeedbackRunningStatusas the basic running state.DOBOT-specific
RobotMode()is handled separately rather than being confused with the running state.
Reorganized conversion between the MG400’s four-axis coordinates and the public six-component representation.
Cartesian coordinates
[x, y, z, r]are represented as[x, y, z, 0, 0, rz].The MG400’s four joint values are converted to the six-component interface, with J5/J6 set to
0.0.Implemented conversions of User / Tool coordinate-system definitions appropriate to the four-axis MG400.
Implemented Tool coordinate-system operations.
Implemented
set_tool_define()/set_tool().Implemented
get_tool_define()/get_tool().When retrieving a Tool definition, the current Tool index is saved, the target Tool is selected and read from Feedback, and the original Tool is restored.
Implemented and reorganized Work coordinate systems using the MG400 User coordinate systems.
Adapted retrieval and configuration of User coordinate-system definitions to the MG400 coordinate representation.
Reorganized speed-related interfaces.
SpeedLis used for the linear motion speed percentage.SpeedJis used for the joint motion speed percentage.SpeedFactoris used for the global speed multiplier.Stopped returning dummy values for deceleration and extended acceleration/deceleration features for which no semantically equivalent MG400 API has been confirmed.
Implemented
approach()as motion relative to a reference position plus an offset.Clarified the roles of digital I/O.
Digital inputs are read using
DI().Corrected the confusion between reading outputs and reading inputs.
Clarified handling of unsupported interfaces.
Unimplemented functions no longer return dummy values such as
None,0, or an empty string in a way that makes them appear implemented.Features with no confirmed equivalent in the MG400 API are explicitly marked unsupported.
DOBOT-specific functions are not mechanically mapped to similarly named common-interface functions when their semantics differ.
Corrected
take_arm()/give_arm()to be compatibility no-ops for the MG400.Because the MG400 has no separate operation for acquiring or releasing arm-control authority, these methods return
Truewithout sending commands to the robot.They are not incorrectly mapped to
EnableRobot()/DisableRobot().
Cleaned up comments and docstrings in the Dobot implementation.
Removed names and explanations specific to other robots, controllers, and APIs.
Standardized comments and docstrings to describe only the specifications and behavior of the MG400/Dobot implementation.
Design policy
Implement DOBOT API mappings according to the semantics of the common interface, not merely similarities between API names.
Where the MG400 lacks an equivalent function, do not substitute another function and change the intended meaning.
Distinguish intentional compatibility no-ops from unimplemented features.
Keep vendor-supplied code unchanged; implement necessary behavior and conversions in the Dobot control layer.
v0.1.0 - 2026-09-08
Starting from v0.0.0, the architecture for controlling the DOBOT MG400 through a common interface was reorganized, and basic motion control was verified on actual hardware.
Common interface and implementation layers
Organized
DobotCtrlas the common public robot-control interface.Separated the MG400-specific implementation into
DobotTcp.DOBOT-specific functionality is handled by
DobotTcp, preserving the common interface exposed byDobotCtrl.Standardized Cartesian poses as
[x, y, z, rx, ry, rz]in the common interface, converting to the MG400’s[x, y, z, r]withr = rz.Also organized conversion between the common joint-pose representation and the MG400’s four-axis representation.
Official DOBOT API and extended API
Used vendor-supplied
dobot_api.pywithout modification.Introduced
DobotApiExt,DobotApiDashboardExt, andDobotApiMoveExtas inheritance/extension layers over the vendor classes.DobotTcpaccesses the official DOBOT API through the extended API layer.Organized connections for Dashboard (29999), Move (30003), and real-time status (30004).
Integrated API communication into the logger using
[DobotApi][CONN],[DobotApi][TX], and[DobotApi][RX].Distinguished
DobotTcpcontrol logs from API-level communication logs.
Basic control
Made
EnableRobot()/DisableRobot()available through the common interface.Connected speed and acceleration settings to the MG400 Dashboard API.
Mapped PTP / LINE motion to MG400
MovJ()/MovL().Organized handling of TCP/IP command responses so that command acceptance results are returned to the caller.
Work / User coordinate systems
Organized the mapping between common Work coordinates and MG400 User coordinates.
Implemented
change_work()using MG400User(index).Mapped definition and retrieval of MG400 User coordinate systems to common Work coordinate-system operations.
Motion control
move()accepts a six-component pose from the common interface, converts it to the MG400’s four-component pose, and sends it to the robot.is_asyncselects blocking or non-blocking execution.wait_for_complete()uses the independentSync()command on the TCP/IP Move port.
Final correction of blocking / non-blocking behavior
During development, an implementation was introduced that sent SYNC=0 / SYNC=1 from DobotStudio Pro script instructions as dynamic arguments to MovJ() / MovL() on TCP/IP port 30003.
On actual hardware, the TCP/IP response to MovJ(...,SYNC=1) returned immediately, failing to provide the blocking behavior required by the common interface. That approach was therefore abandoned.
The v0.1.0 implementation is:
is_async=True
MovJ(...) / MovL(...)
-> Command accepted
-> return
is_async=False
MovJ(...) / MovL(...)
-> Command accepted
-> Sync()
-> Motion completed
-> return
This separates the SYNC option in DobotStudio Pro scripts from the independent Sync() command in the TCP/IP API.
Hardware verification as of v0.1.0
Local direct-control blocking example: verified working.
Local direct-control non-blocking example: verified working.
These examples serve as the reference implementations for basic motion control in v0.1.0.
v0.0.0
Initial development release.
Began developing the DOBOT MG400 control-code architecture, common interface, TCP/IP communication, and motion control.
2026-09-08 - Initial record
This initial changelog entry summarizes the design, implementation, and corrections completed up to this point for the DOBOT MG400 control package.
Separation of the common interface and MG400 implementation
The public control interface was separated into DobotCtrl and the MG400-specific implementation into DobotTcp.
DobotCtrl
Common public interface
|
v
DobotTcp
MG400-specific implementation
DobotCtrl is responsible only for exposing the common interface. It delegates TCP/IP API selection, coordinate conversion, and real-time status retrieval to DobotTcp.
DOBOT-specific features that do not belong in the common interface are kept in DobotTcp.
Changed architecture to avoid direct modifications to vendor dobot_api.py
The dobot_api.py supplied by DOBOT is retained unchanged as vendor code.
Additional processing is implemented in derived classes:
DobotApiExt
DobotApiDashboardExt
DobotApiMoveExt
Connection handling and logger-based TX/RX/CONN output were separated from vendor code.
Implemented the three MG400 port connections
DobotTcp manages three connections:
29999 Dashboard
30003 Motion
30004 Real-time status
Port 30004 is received by a dedicated thread. The implementation accumulates and parses 1440-byte frames and maintains the latest state.
Standardized logging through a logger
All control-layer output uses the logger.
[DobotApi][CONN]
[DobotApi][TX]
[DobotApi][RX]
[DobotTcp]
[DobotStatus]
These prefixes distinguish connections, transmissions, receptions, state changes, and errors.
Mapped motor ON/OFF to the MG400 API
Common motor operations are mapped as follows:
turn_on_motor() -> EnableRobot()
turn_off_motor() -> DisableRobot()
reset_error() -> ClearError()
take_arm() / give_arm() are separate from motor ON/OFF.
No concept equivalent to TakeArm / GiveArm has been confirmed in the MG400 TCP/IP API, so these are no-ops preserving the common interface.
Standardized common coordinates to six components
The common Cartesian interface uses:
[x, y, z, rx, ry, rz]
The MG400 uses four components:
[x, y, z, r]
Conversion is defined as:
r = rz
rx = 0
ry = 0
Coordinates returned from the MG400 are expanded to:
[x, y, z, 0, 0, r]
The common joint interface also uses six components. Four MG400 joint values are expanded to:
[j1, j2, j3, j4, 0, 0]
Implemented MG400 conversion in move()
Basic motion mappings were implemented:
P + PTP -> MovJ
P + LINE -> MovL
J + PTP -> JointMovJ
The MG400 API’s SYNC was mapped to the common interface’s is_async:
is_async=True -> SYNC=0
is_async=False -> SYNC=1
Separated motion_mode from path_blend
The trajectory types PTP / LINE / CIRCLE / SPLINE and the path-passing condition path_blend were clarified as separate concepts.
Because DOBOT’s CP does not have the same meaning as the common interface’s path_blend, no automatic path_blend -> CP conversion is performed.
Implemented motion-completion detection
Using execution state from port 30004, the following methods were implemented:
motion_complete()
get_motion_complete()
wait_for_complete()
Successful command acceptance is distinguished from completion of physical motion.
Implemented current position and joint-angle retrieval
The following fields are read from port 30004:
tool_vector_actual
q_actual
Values are converted to the six-component common interface before being returned.
Implemented forward and inverse kinematics
The following mappings use the MG400 API:
p2j() -> InverseSolution()
j2p() -> PositiveSolution()
Implemented Work coordinates using User coordinates
The common Work coordinate system was defined to use the MG400 User coordinate system.
Responsibilities are separated as follows:
set_work() Define a User coordinate system
change_work() Select an existing User coordinate system
get_current_work_no() Get the current User index
get_work() Retrieve a User coordinate-system definition
change_work() uses:
User(index)
get_current_work_no() uses the userCoordinate field on port 30004.
get_work() uses the user field on port 30004.
set_work() was implemented using the command defined in the MG400 manual:
SetUser(index,{x,y,z,r})
Even if vendor dobot_api.py has no Python wrapper for SetUser(), the vendor file remains unchanged; DobotTcp sends the TCP/IP command directly.
The six-component Work definition:
[x, y, z, rx, ry, rz]
is converted to the MG400 representation:
{x,y,z,r}
with r = rz.
Work coordinate systems with nonzero rx or ry are rejected because the four-axis MG400 cannot represent them.
Implemented Tool coordinate-system selection
Selecting and retrieving the current Tool index is mapped to:
Tool(index)
toolCoordinate
Reading or changing Tool definitions themselves was not yet implemented.
Implemented I/O
Common I/O methods are mapped to:
get_IO() -> 30004 digital_input_bits
set_IO() -> DO(index,status)
Implemented error retrieval and description display
Error IDs are retrieved using GetErrorID(), and descriptions are looked up in DOBOT-supplied alarm JSON files.
If the first return value of an API command is not 0, the error ID and description are written to the logger.
Reorganized the FastAPI layer
DobotCtrl is passed as a device class to FastAPI’s automatic dispatch.
Synchronous and asynchronous clients are distinguished by their HTTP calling mechanisms. This is separate from the is_async setting for robot motion.
Split test scripts by interface
Individual executable scripts were prepared to verify each public method and property.
Because PyCharm recognizes test_*.py as automated tests, scripts intended for hardware verification were renamed to use check_*.py.
Each script is independently executable and does not depend on a shared helper.
Explicitly documented unimplemented interfaces
The reason for an unimplemented or partially implemented interface is documented in a comment immediately before the corresponding method.
In particular, the documentation distinguishes:
Features physically impossible with the MG400’s mechanical configuration.
Features for which no direct equivalent has been confirmed in the currently exposed API.
Semantic conversions that have not yet been implemented.
Features that are simply not yet implemented.
Main currently identified unimplemented or partially implemented features
halt()hand_stop()Mapping
path_blendto actual MG400 behaviorIndependent
decelExternal-axis speed, acceleration, and deceleration
Full coordinate-conversion semantics of
dev()CIRCLE/SPLINEinmove()approach()rotate()Project-name resolution in
run_script()Hand control
autocal()Controller / servo log interfaces
Reading and setting Tool definitions
direct_modetaskobjectRetrieving the actual robot version
Hardware verification on 2026-09-08
Successful connection to MG400 10.170.10.63, EnableRobot(), SpeedFactor(30), AccL(30), and AccJ(30) were confirmed.
It was also confirmed that the current position can be obtained from real-time status in a form such as:
[x, y, z, 0.0, 0.0, rz]
An earlier local example passed four-component MG400-native coordinates:
[x, y, z, r]
to move(), and was confirmed to be rejected by the common interface’s six-component validation.
Future examples use:
[x, y, z, 0, 0, rz]