2b-t / myactuator_rmd Goto Github PK
View Code? Open in Web Editor NEWC++ and Python SDK for controlling actuators of the MyActuator RMD-X series, written in C++ with Python bindings
License: MIT License
C++ and Python SDK for controlling actuators of the MyActuator RMD-X series, written in C++ with Python bindings
License: MIT License
The python bindings fail when creating new driver.
Python 3.12.3 (main, June 19 2024, 05:33:47) [GCC 13.2.0]
Type 'copyright', 'credits' or 'license' for more information
IPython 8.20.0 -- An enhanced Interactive Python. Type '?' for help.
In [1]: import myactuator_rmd_py as myactuator_rmd
In [2]: driver1 = myactuator_rmd.Driver('can0', 1)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[2], line 1
----> 1 driver1 = myactuator_rmd.Driver('can0', 1)
TypeError: myactuator_rmd_py.Driver: No constructor defined!
In [3]: dir(myactuator_rmd)
Out[3]:
['ActuatorException',
'ActuatorInterface',
'CanDriver',
'Driver',
'ProtocolException',
'ValueRangeException',
'__doc__',
'__file__',
'__loader__',
'__name__',
'__package__',
'__spec__',
'actuator_constants',
'actuator_state',
'can']
Hello, thanks for the amazing work.
I am trying to compile the project in a Rpi4 and getting the following error:
(venv_strummer) metal@raspberrypi:~/Documents/strummer/myactuator_rmd/build $ make -j $(nproc)
[ 25%] Building CXX object CMakeFiles/myactuator_rmd.dir/src/protocol/responses.cpp.o
[ 25%] Building CXX object CMakeFiles/myactuator_rmd.dir/src/protocol/requests.cpp.o
[ 37%] Building CXX object CMakeFiles/myactuator_rmd.dir/src/driver.cpp.o
In file included from /home/metal/Documents/strummer/myactuator_rmd/include/myactuator_rmd/protocol/single_motor_message.hpp:17,
from /home/metal/Documents/strummer/myactuator_rmd/include/myactuator_rmd/protocol/requests.hpp:20,
from /home/metal/Documents/strummer/myactuator_rmd/src/protocol/requests.cpp:1:
/home/metal/Documents/strummer/myactuator_rmd/include/myactuator_rmd/protocol/message.hpp:94:77: error: redefinition of default argument for ‘std::enable_if_t<is_integral_v<T> >* <anonymous>’
94 | template <typename T, typename std::enable_if_t<std::is_integral_v<T>>* = nullptr>
| ^~~~~~~
In file included from /home/metal/Documents/strummer/myactuator_rmd/include/myactuator_rmd/protocol/single_motor_message.hpp:17,
from /home/metal/Documents/strummer/myactuator_rmd/include/myactuator_rmd/protocol/responses.hpp:23,
from /home/metal/Documents/strummer/myactuator_rmd/src/protocol/responses.cpp:1:
/home/metal/Documents/strummer/myactuator_rmd/include/myactuator_rmd/protocol/message.hpp:94:77: error: redefinition of default argument for ‘std::enable_if_t<is_integral_v<T> >* <anonymous>’
94 | template <typename T, typename std::enable_if_t<std::is_integral_v<T>>* = nullptr>
| ^~~~~~~
/home/metal/Documents/strummer/myactuator_rmd/include/myactuator_rmd/protocol/message.hpp:65:81: note: original definition appeared here
65 | template <typename T, typename std::enable_if_t<std::is_integral_v<T>>* = nullptr>
| ^~~~~~~
/home/metal/Documents/strummer/myactuator_rmd/include/myactuator_rmd/protocol/message.hpp:65:81: note: original definition appeared here
65 | template <typename T, typename std::enable_if_t<std::is_integral_v<T>>* = nullptr>
| ^~~~~~~
/home/metal/Documents/strummer/myactuator_rmd/include/myactuator_rmd/protocol/message.hpp:103:77: error: redefinition of default argument for ‘std::enable_if_t<is_integral_v<T> >* <anonymous>’
103 | template <typename T, typename std::enable_if_t<std::is_integral_v<T>>* = nullptr>
| ^~~~~~~
/home/metal/Documents/strummer/myactuator_rmd/include/myactuator_rmd/protocol/message.hpp:103:77: error: redefinition of default argument for ‘std::enable_if_t<is_integral_v<T> >* <anonymous>’
103 | template <typename T, typename std::enable_if_t<std::is_integral_v<T>>* = nullptr>
| ^~~~~~~
/home/metal/Documents/strummer/myactuator_rmd/include/myactuator_rmd/protocol/message.hpp:79:81: note: original definition appeared here
79 | template <typename T, typename std::enable_if_t<std::is_integral_v<T>>* = nullptr>
| ^~~~~~~
/home/metal/Documents/strummer/myactuator_rmd/include/myactuator_rmd/protocol/message.hpp:79:81: note: original definition appeared here
79 | template <typename T, typename std::enable_if_t<std::is_integral_v<T>>* = nullptr>
| ^~~~~~~
In file included from /home/metal/Documents/strummer/myactuator_rmd/include/myactuator_rmd/protocol/node.hpp:18,
from /home/metal/Documents/strummer/myactuator_rmd/include/myactuator_rmd/driver.hpp:26,
from /home/metal/Documents/strummer/myactuator_rmd/src/driver.cpp:1:
/home/metal/Documents/strummer/myactuator_rmd/include/myactuator_rmd/protocol/message.hpp:94:77: error: redefinition of default argument for ‘std::enable_if_t<is_integral_v<T> >* <anonymous>’
94 | template <typename T, typename std::enable_if_t<std::is_integral_v<T>>* = nullptr>
| ^~~~~~~
/home/metal/Documents/strummer/myactuator_rmd/include/myactuator_rmd/protocol/message.hpp:65:81: note: original definition appeared here
65 | template <typename T, typename std::enable_if_t<std::is_integral_v<T>>* = nullptr>
| ^~~~~~~
/home/metal/Documents/strummer/myactuator_rmd/include/myactuator_rmd/protocol/message.hpp:103:77: error: redefinition of default argument for ‘std::enable_if_t<is_integral_v<T> >* <anonymous>’
103 | template <typename T, typename std::enable_if_t<std::is_integral_v<T>>* = nullptr>
| ^~~~~~~
/home/metal/Documents/strummer/myactuator_rmd/include/myactuator_rmd/protocol/message.hpp:79:81: note: original definition appeared here
79 | template <typename T, typename std::enable_if_t<std::is_integral_v<T>>* = nullptr>
| ^~~~~~~
make[2]: *** [CMakeFiles/myactuator_rmd.dir/build.make:118: CMakeFiles/myactuator_rmd.dir/src/protocol/responses.cpp.o] Error 1
make[2]: *** Waiting for unfinished jobs....
make[2]: *** [CMakeFiles/myactuator_rmd.dir/build.make:104: CMakeFiles/myactuator_rmd.dir/src/protocol/requests.cpp.o] Error 1
make[2]: *** [CMakeFiles/myactuator_rmd.dir/build.make:132: CMakeFiles/myactuator_rmd.dir/src/driver.cpp.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:85: CMakeFiles/myactuator_rmd.dir/all] Error 2
make: *** [Makefile:136: all] Error 2
Hello,
I'm trying to install as a Python package, but I'm getting an error I don't know how to resolve when I do pip3 install .
. I think the key error is /home/user/ContinuO_Python/myactuator_rmd/src/can/node.cpp:150:13: error: ‘struct can_frame’ has no member named ‘len’
, but I'm not certain.
I'm on Ubuntu 20.04, and I should have all dependencies installed (I had to compile cmake >= 3.20 from source and install as a DEB package). One caveat is that I'm on a lowlatency kernel and when I attempt to execute sudo apt-get install linux-modules-extra-$(uname -r)
I get E: Package 'linux-modules-extra-5.15.0-110-lowlatency' has no installation candidate
.
My output:
Processing /home/user/ContinuO_Python/myactuator_rmd
Installing build dependencies ... done
Getting requirements to build wheel ... done
Preparing metadata (pyproject.toml) ... done
Building wheels for collected packages: myactuator_rmd_py
Building wheel for myactuator_rmd_py (pyproject.toml) ... error
error: subprocess-exited-with-error
× Building wheel for myactuator_rmd_py (pyproject.toml) did not run successfully.
│ exit code: 1
╰─> [110 lines of output]
running bdist_wheel
running build
running build_ext
-- The C compiler identification is GNU 9.4.0
-- The CXX compiler identification is GNU 9.4.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found Python: /home/user/ContinuO_Python/.venv/bin/python3 (found version "3.8.10") found components: Interpreter Development Development.Module Development.Embed
CMake Deprecation Warning at /usr/lib/cmake/pybind11/pybind11Tools.cmake:8 (cmake_minimum_required):
Compatibility with CMake < 3.5 will be removed from a future version of
CMake.
Update the VERSION argument <min> value or use a ...<max> suffix to tell
CMake that the project does not need compatibility with older versions.
Call Stack (most recent call first):
/usr/lib/cmake/pybind11/pybind11Config.cmake:100 (include)
CMakeLists.txt:56 (find_package)
CMake Warning (dev) at /usr/lib/cmake/pybind11/FindPythonLibsNew.cmake:60 (find_package):
Policy CMP0148 is not set: The FindPythonInterp and FindPythonLibs modules
are removed. Run "cmake --help-policy CMP0148" for policy details. Use
the cmake_policy command to set the policy and suppress this warning.
Call Stack (most recent call first):
/usr/lib/cmake/pybind11/pybind11Tools.cmake:16 (find_package)
/usr/lib/cmake/pybind11/pybind11Config.cmake:100 (include)
CMakeLists.txt:56 (find_package)
This warning is for project developers. Use -Wno-dev to suppress it.
-- Found PythonInterp: /home/user/ContinuO_Python/.venv/bin/python (found version "3.8.10")
-- Found PythonLibs: /usr/lib/x86_64-linux-gnu/libpython3.8.so
-- Performing Test HAS_FLTO
-- Performing Test HAS_FLTO - Success
-- LTO enabled
-- Configuring done (0.5s)
-- Generating done (0.0s)
-- Build files have been written to: /home/user/ContinuO_Python/myactuator_rmd/build/temp.linux-x86_64-cpython-38/myactuator_rmd_py
[ 12%] Building CXX object CMakeFiles/myactuator_rmd.dir/src/can/node.cpp.o
/home/user/ContinuO_Python/myactuator_rmd/src/can/node.cpp: In member function ‘void myactuator_rmd::can::Node::write(uint32_t, const std::array<unsigned char, 8>&)’:
/home/user/ContinuO_Python/myactuator_rmd/src/can/node.cpp:150:13: error: ‘struct can_frame’ has no member named ‘len’
150 | frame.len = 8;
| ^~~
make[2]: *** [CMakeFiles/myactuator_rmd.dir/build.make:76: CMakeFiles/myactuator_rmd.dir/src/can/node.cpp.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:85: CMakeFiles/myactuator_rmd.dir/all] Error 2
make: *** [Makefile:136: all] Error 2
Traceback (most recent call last):
File "/home/user/ContinuO_Python/.venv/lib/python3.8/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py", line 353, in <module>
main()
File "/home/user/ContinuO_Python/.venv/lib/python3.8/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py", line 335, in main
json_out['return_val'] = hook(**hook_input['kwargs'])
File "/home/user/ContinuO_Python/.venv/lib/python3.8/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py", line 251, in build_wheel
return _build_backend().build_wheel(wheel_directory, config_settings,
File "/tmp/pip-build-env-fib9wcpr/overlay/lib/python3.8/site-packages/setuptools/build_meta.py", line 415, in build_wheel
return self._build_with_temp_dir(
File "/tmp/pip-build-env-fib9wcpr/overlay/lib/python3.8/site-packages/setuptools/build_meta.py", line 397, in _build_with_temp_dir
self.run_setup()
File "/tmp/pip-build-env-fib9wcpr/overlay/lib/python3.8/site-packages/setuptools/build_meta.py", line 497, in run_setup
super().run_setup(setup_script=setup_script)
File "/tmp/pip-build-env-fib9wcpr/overlay/lib/python3.8/site-packages/setuptools/build_meta.py", line 313, in run_setup
exec(code, locals())
File "<string>", line 56, in <module>
File "/tmp/pip-build-env-fib9wcpr/overlay/lib/python3.8/site-packages/setuptools/__init__.py", line 103, in setup
return distutils.core.setup(**attrs)
File "/tmp/pip-build-env-fib9wcpr/overlay/lib/python3.8/site-packages/setuptools/_distutils/core.py", line 184, in setup
return run_commands(dist)
File "/tmp/pip-build-env-fib9wcpr/overlay/lib/python3.8/site-packages/setuptools/_distutils/core.py", line 200, in run_commands
dist.run_commands()
File "/tmp/pip-build-env-fib9wcpr/overlay/lib/python3.8/site-packages/setuptools/_distutils/dist.py", line 969, in run_commands
self.run_command(cmd)
File "/tmp/pip-build-env-fib9wcpr/overlay/lib/python3.8/site-packages/setuptools/dist.py", line 976, in run_command
super().run_command(command)
File "/tmp/pip-build-env-fib9wcpr/overlay/lib/python3.8/site-packages/setuptools/_distutils/dist.py", line 988, in run_command
cmd_obj.run()
File "/tmp/pip-build-env-fib9wcpr/overlay/lib/python3.8/site-packages/setuptools/command/bdist_wheel.py", line 373, in run
self.run_command("build")
File "/tmp/pip-build-env-fib9wcpr/overlay/lib/python3.8/site-packages/setuptools/_distutils/cmd.py", line 316, in run_command
self.distribution.run_command(command)
File "/tmp/pip-build-env-fib9wcpr/overlay/lib/python3.8/site-packages/setuptools/dist.py", line 976, in run_command
super().run_command(command)
File "/tmp/pip-build-env-fib9wcpr/overlay/lib/python3.8/site-packages/setuptools/_distutils/dist.py", line 988, in run_command
cmd_obj.run()
File "/tmp/pip-build-env-fib9wcpr/overlay/lib/python3.8/site-packages/setuptools/_distutils/command/build.py", line 132, in run
self.run_command(cmd_name)
File "/tmp/pip-build-env-fib9wcpr/overlay/lib/python3.8/site-packages/setuptools/_distutils/cmd.py", line 316, in run_command
self.distribution.run_command(command)
File "/tmp/pip-build-env-fib9wcpr/overlay/lib/python3.8/site-packages/setuptools/dist.py", line 976, in run_command
super().run_command(command)
File "/tmp/pip-build-env-fib9wcpr/overlay/lib/python3.8/site-packages/setuptools/_distutils/dist.py", line 988, in run_command
cmd_obj.run()
File "/tmp/pip-build-env-fib9wcpr/overlay/lib/python3.8/site-packages/setuptools/command/build_ext.py", line 93, in run
_build_ext.run(self)
File "/tmp/pip-build-env-fib9wcpr/overlay/lib/python3.8/site-packages/setuptools/_distutils/command/build_ext.py", line 359, in run
self.build_extensions()
File "/tmp/pip-build-env-fib9wcpr/overlay/lib/python3.8/site-packages/setuptools/_distutils/command/build_ext.py", line 479, in build_extensions
self._build_extensions_serial()
File "/tmp/pip-build-env-fib9wcpr/overlay/lib/python3.8/site-packages/setuptools/_distutils/command/build_ext.py", line 505, in _build_extensions_serial
self.build_extension(ext)
File "<string>", line 52, in build_extension
File "/usr/lib/python3.8/subprocess.py", line 516, in run
raise CalledProcessError(retcode, process.args,
subprocess.CalledProcessError: Command '['cmake', '--build', '.']' returned non-zero exit status 2.
[end of output]
note: This error originates from a subprocess, and is likely not a problem with pip.
ERROR: Failed building wheel for myactuator_rmd_py
Failed to build myactuator_rmd_py
ERROR: ERROR: Failed to build installable wheels for some pyproject.toml based projects (myactuator_rmd_py)
If I instead attempt to build as a C++ library with Python bindings on, I get a similar error after make
:
(.venv) user@ContinuO-Laptop-Linux:~/ContinuO_Python/myactuator_rmd/build$ make -j $(nproc)
[ 12%] Building CXX object CMakeFiles/myactuator_rmd.dir/src/can/node.cpp.o
[ 25%] Building CXX object CMakeFiles/myactuator_rmd.dir/src/can/utilities.cpp.o
[ 37%] Building CXX object CMakeFiles/myactuator_rmd.dir/src/protocol/requests.cpp.o
[ 50%] Building CXX object CMakeFiles/myactuator_rmd.dir/src/protocol/responses.cpp.o
[ 62%] Building CXX object CMakeFiles/myactuator_rmd.dir/src/actuator_interface.cpp.o
/home/user/ContinuO_Python/myactuator_rmd/src/can/utilities.cpp: In function ‘std::ostream& operator<<(std::ostream&, const can_frame&)’:
/home/user/ContinuO_Python/myactuator_rmd/src/can/utilities.cpp:11:29: error: ‘const struct can_frame’ has no member named ‘len’
11 | for (int i = 0; i < frame.len; i++) {
| ^~~
make[2]: *** [CMakeFiles/myactuator_rmd.dir/build.make:90: CMakeFiles/myactuator_rmd.dir/src/can/utilities.cpp.o] Error 1
make[2]: *** Waiting for unfinished jobs....
/home/user/ContinuO_Python/myactuator_rmd/src/can/node.cpp: In member function ‘void myactuator_rmd::can::Node::write(uint32_t, const std::array<unsigned char, 8>&)’:
/home/user/ContinuO_Python/myactuator_rmd/src/can/node.cpp:150:13: error: ‘struct can_frame’ has no member named ‘len’
150 | frame.len = 8;
| ^~~
make[2]: *** [CMakeFiles/myactuator_rmd.dir/build.make:76: CMakeFiles/myactuator_rmd.dir/src/can/node.cpp.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:85: CMakeFiles/myactuator_rmd.dir/all] Error 2
make: *** [Makefile:136: all] Error 2
Thank you for your assistance, I'm a novice.
Hi Tobit,
I am still investigating, but when using closed-loop position control for path-following (with commands every time step), my system tends to accrue many myactuator_rmd.can.BusError
exceptions regardless of the time step size used (typically 2 ms but with other time step sizes also). I'm handling the exceptions and it doesn't appear to have a significant effect on path following performance, but after executing a path later individual commands often return a myactuator_rmd_py.ProtocolException: Unexpected response
of the kind used by the path following, e.g.:
>>> motor[5].setAcceleration(5000, pos_accel)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
myactuator_rmd_py.ProtocolException: Unexpected response '0xa4'
In this case monitoring the CAN socket reveals a correct (0x43
) message and response, and the motor does execute the command to write the new acceleration, but it is problematic when you need to read the correct response (e.g., with getMultiTurnAngle()
). It is as though responses to commands which receive a BusError
accrue in a buffer and then are inappropriately read by later commands.
Also, though more rarely, a BusError
will occur on a command that is not repeated each time step, which I think may cause the command to fail to be sent to the motor (to be confirmed) - potentially disrupting a program. Anecdotally, I think the likelihood of this may increase as more BusError
's have been accrued (e.g., following execution of a path).
As I mentioned I'm still investigating, so I'm not certain whether the bus errors are a result of something in my system or something in the code. I haven't yet dug into your code sufficiently to see what might cause the bus errors there, but maybe you have a better idea? In any case, I wonder if there is a way to clear the response buffer so later commands don't get unexpected responses?
I will continue to look into this on my return at the end of the month, but just wanted to bring it up now in case you have a chance to start thinking about it.
Cheers,
Stefan
Hello again Tobit,
I have been trying to use closed-loop position control commands (using your repo installed as a python package) to get a motor to follow a smooth position curve: as a simple test, a sin(t) curve with a typical time step of 1 ms (though I have tried various step sizes up to 0.1 s and down to 0.1 ms). Like this:
startup_pos = {}
for id in motor_IDs:
startup_pos[id] = motor[id].getMultiTurnAngle()
t = 0
dt = 0.001
def sin_pos(t):
max_angle = 30 # degrees
freq = 0.5 # Hz
return startup_pos[5] + max_angle * math.sin(2 * math.pi * freq * t)
while True:
fr_knee.sendPositionAbsoluteSetpoint(sin_pos(t), 500)
time.sleep(dt)
t += dt
However, this results in my motor jumping to various positions along the expected curve and stopping at each for a moment (maybe about a half-second), like it is only receiving some of the commands and ignoring the others. The frequency of the jumps does not seem to vary with time step size that I can tell. Have you experienced similar? Do you know if there is a substantial delay between when these motors will accept new closed-loop position commands? I'm using several RMD-X8-Pro-H V3, and each I've tested has done the same.
I have also tried various max velocity inputs, which as expected changes the speed at which the motor jumps from one position to the other, but otherwise is the same.
I'm aware this may be an issue with the motor rather than with your repo, so I apologize if this is an inappropriate forum for this discussion. I just figured you may be knowledgeable, so it was worth asking. I have reached out to myactuator for comment also. If this is just a behaviour of the motor for this control mode, I would like to try Motion Control Mode as an alternative, thus #9.
Thanks again,
Stefan
Hello! I was wondering if there were any example projects, or example CmakeLists.txt that show how to use this library. Thanks!
This is actually not an issue. I just wanted to say thank you for making this repository and for your incredible work. 🙌
(feel free to close it)
.../myactuator_rmd/src/can/utilities.cpp:11:29: error: 'const struct can_frame' has no member named 'len'
Hello,
I noticed a small inconsistency regarding the constants of the X8-Pro-H V3 motor, which seems very low to me. In the X8ProHV3 class, the torque constant of 0.29 Nm/A probably corresponds to the motor torque without a reducer.
The technical specifications also specify "motor" for this value,
while for the X8ProV2, the torque of 2.6 Nm/A is expressed without "motor".
This change in reference also seems to apply to the entire V3 range.
What do you think?
Best regards,
Hi Tobit,
I'm looking into ways to implement Motion Mode Control (i.e., send desired position and velocity with kp and kd and feedforward torque - 0x400 + ID in the control protocol). I've installed your repo as a python package and used it for position and velocity closed loop control, but unless I'm missing something the motion mode control command is not yet implemented. I've tried to puzzle out how I might modify your source to add the feature, but I'm a C++ novice so I haven't been able to figure it out (yet). Do you have any interest in developing this feature, or do you have any advice as to how I might get started doing so?
I'm aware this would at least require:
Thank you,
Stefan
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.