open-dynamic-robot-initiative / master-board Goto Github PK
View Code? Open in Web Editor NEWHardware and Firmware of the Solo Quadruped Master Board
License: BSD 2-Clause "Simplified" License
Hardware and Firmware of the Solo Quadruped Master Board
License: BSD 2-Clause "Simplified" License
As the moment, nothing prevent a user to launch several instances of a controller. This could cause hardware issue if the control jumps back and forth between the two controllers.
I'm not sure how to handle this properly.
Check for control packets on the network socket?
A lock file ?
Hello everyone,
Thanks for providing this usefull SDK. I'm using Ubuntu 18.04 that has been connected to a network for internet connection. I had a problem of Ethernet connection that was showing "connecting" and after a while a failing connection error.
I solved this problem by setting the IP address and Netmask in the Ethernet connection setting and I add some screenshot of my settings, it may be useful for other users if they face the similar issue::
The word usage "master" and "slave" is considered problematic and these days people use different terminologies.
Please update the terminology in the repo.
See similar issue in machines-in-motion/synchronizer#2
We could provide compiled version of the firmware for easier flashing on different system without having to install a particular esp-idf version.
Hello all,
I am using the Python bindings of the MasterBoardInterface in a Python script to test some P_controller on the robot. The experimentation runs well but when arriving at the line MasterBoardInterface(name_interface).Stop()
, I get errors such as Error in 'python3' : double free or corruption (out)
or Error in 'python3' : free() : invalid pointer
as well as Segmentation fault
, which make me think that there is an issue with the allocation memory in the C++ file.
Could someone solve this problem ?
Thanks,
When converting floating point host numbers to fixed-point integers for sending to the masterboard, there's no consideration of overflow. This is somewhat difficult to prevent at the higher level, since the numbers are all multiplied by gear ratios and encoder counts before being converted to fixed-point.
For instance, Kp overflows at about 5.1 for the Solo12 robot, but you have to know several other parameters in order to calculate that. The overflow point isn't far from reasonable values people might want to use (I currently use 4.0). Kd overflows at 0.4, when a common value is 0.2.
command_packet.dual_motor_driver_command_packets[i].kp[0] = FLOAT_TO_D16QN(2. * M_PI * motor_drivers[i].motor1->kp, UD_QN_KP);
...
#define UD_QN_KP 11
...
#define FLOAT_TO_D16QN(a,n) ((int16_t) ((a) * (1<<(n))))
...
motors_[i]->set_kp(desired_gains[i] / (gear_ratios_[i] * gear_ratios_[i] * motor_constants_[i]));
I suggest clamping these values to within the representable range, rather than overflowing to negative numbers. Something like:
#define FLOAT_TO_D16QN(a,n) ((int16_t) (min(max((a) * (1<<(n)), -32765.0), +32765.0))
Right now it's possible to start a control program, power down the robot, power on the robot again and the same control program takes over the robot again. This is dangerous as the user might not expect the controller to run on the controller right away.
As a safety, the sdk should check if the master-board is responsive or not. If a timeout is reached and the master-board is not responding, the robot_if should shutdown (with possibility to re-enable by the user if desired but needs to be an explicit behavior).
The IMU transmit via UART accelerometer and gyros at 1khz and atitude estimate at 500Hz.
The UART Driver except two types of packets:
Acc+gyr
Acc+gyr+EKF
but sometimes EKF comes in a different packet (Acc+Gyr and then EKF alone)
The driver is not handling this so the EKF field are not updated
It seems there is no way to get the IMU data via Python yet.
Error code from uDriver should be documented. From the uDriver firmware:
/* sensor packet -> status -> ERROR : values */
//! \brief No error
#define SPI_SENSOR_STATUS_ERROR_NO_ERROR 0
//! \brief Encoder error too high
#define SPI_SENSOR_STATUS_ERROR_ENCODER 1
//! \brief Timeout for receiving current references exceeded
#define SPI_SENSOR_STATUS_ERROR_SPI_RECV_TIMEOUT 2
//! \brief Motor temperature reached critical value
//! \note This is currently unused as no temperature sensing is done.
#define SPI_SENSOR_STATUS_ERROR_CRIT_TEMP 3 // currently unused
//! \brief Some error in the SpinTAC Position Convert module
#define SPI_SENSOR_STATUS_ERROR_POSCONV 4
//! \brief Position Rollover occured
#define SPI_SENSOR_STATUS_ERROR_POS_ROLLOVER 5
//! \brief Some other error
#define SPI_SENSOR_STATUS_ERROR_OTHER 7
For the connection between the master-board and the IMU a custom wire is used. So far is no documentation on how the wire is produced / the pins are connected and which connectors are used (one end is a 7-pin female Hirose connector, but I am not sure about the other side).
Right now the C++ classes are defined at the top level. To avoid bloating the global namespace, let's add a namespace like namespace blmc_master_board {
.
We have a repeatable segfault using the master_board_sdk.
This is causing trouble on the use of the robot as it prevent the proper destruction of the managing class. So some logs are not available.
When installing the SDK library for python3, the .so goes in /usr/local/lib/python3/dist-packages
on Ubuntu. This is not the standard, and python will not find the library by default.
A temporary fix is:
sudo sh -c "echo /usr/local/lib/python3/dist-packages >> /usr/local/lib/python3.5/dist-packages/local.pth"
In ~1/4 of the cases lately the IMU returns only zeros. I am not sure what is going on but assume that something with setting up the IMU goes wrong and the master board is not receiving any packages from the IMU.
Has someone else observed this?
@thomasfla any idea how this could be fixed or did you observe this as well?
Hi there, I have a few questions:
The core while loop receiving new messages from an interface is defined here:
This runs in a thread, which is non-realtime.
The suggestion is to spawn this thread as an rt-preempt realtime thread. We have a nice abstraction for launching realtime threads in our real-time-tools package: If a thread is launched on a non-realtime / non-rtpreempt linux kernel, then a "normal" non-realtime thread is created.
Motors encoders are not absolute, but incremental + index.
The consequence is that at startup, user have no way to get the absolute position of the joints.
an active calibration procedure is needed to find the INDEX of the encoder.
With the choices that have been made, the calibration could be done with a state machine:
1 Wait for alignment to finish (motor ready?)
2 Do position control to find an index (given a direction of search from the user, or going half a turn in a direction, half a turn in the other, or something else...)
Watch the index detected flag, and go to 3 when detected.
3 Disable position control, and set current to 0A. Enable the index compensation in the uDriver, wait for it to be enabled.
4 The motor is now referenced with respect to the index from the encoder.
5 Optionally, user could give an additional offset to represent a physical offset between the index position and the zero of the robot joint.
All this machinery could be coded in the SDK itself, but to stay in the spirit of the sdk, the calibration function should not be blocking the thread. It is still up to the user to call the send commands and parse packet:
The user will have to write: a loop that is calling:
robot_if.ParseSensorData();
robot_if.DoEncoderCalibration();
robot_if.SendCommand();
@MaximilienNaveau @jviereck @paLeziart what do you think?
Hello,
I am trying to run the example motor control code on Raspberry Pi, but I couldn't cmake on it. Do you know how to do that?
When working with wireless, we need to get some link quality estimate. There is fields in the protocol to measure packet loss. We need to compute and expose this quantities in the SDK.
Currently, the sdk is a simple C code, with global variables. This should be turned into a c++ class, with a cleaner interface: I will use this Issue to list the changes to be made:
Output of sudo PYTHONPATH=. python3 example/example.pyc -i eth0
Traceback (most recent call last):
File "/home/dmitriy/git/master-board/sdk/master_board_sdk/example/example.py", line 7, in <module>
from time import clock
ImportError: cannot import name 'clock' from 'time' (unknown location)
As described in "Flashing the firmware", the esp chip needs the RST and GPIO-0 pins lowered to enter the flash mode. On the WeMos D1 mini board, this is done by two transistors shown here. This circuit could be directly implemented on a new generation of the solo's master board. With this, it should be possible to program the master board without any additional hardware and just using the DTR and RTS pins from a usb-serial-connector.
I don't know if this is feasible, so feel free to comment the idea.
The inductor L1 is LPS6235-153MRB, not LPS6235-682MRB.
The inductor L is not to be populated, but simply to be shorten by solder (this was a optional filtering)
When the master_board stays powered on, it's not possible to reconnect to it from the PC. Is this supposed to be the case?
For example, in our experimental setup we have:
@thomasfla , any idea if this should work? I wonder if there is a timeout on the master board that shuts it down once it detects the communication to the PC at 3) is closed as well.
Hello,
We want to manufacture Master boards in another manufacturer (that isn't Beta layout). We’ve analyzed the manufacturing files, and we found two problems:
For the C4 to C9 capacitors and the R17 resistor, the BOM indicates that the package is 0603 (imperial size) and the "Component Placement File" indicates that it is 0402 (imperial size). What is the correct size for these components?
The model of the U$3 component (HR911105A, Ethernet connector) doesn’t fit with the footprint. Could you regenerate the manufacturing files to change the footprint by the correct one?
Thanks!
Yaiza
This is a long/known issue with the velocity reported by the cards. Basically, when passing the zero position of the motor, the velocity jumps and a spike shows up in the velocity plot. See the plot enclosed which is from squatting motions on solo12 using a slider box.
On the micro drivers we are running a velocity estimator. My best guess is that this estimator is buggy with respect to jumping at 2 pi angles.
Hello all,
my classmates and me are trying to order the master board from Beta Layout. Due to the ongoing supply chain issues, Beta Layout asked for alternatives for the following components:
Does anyone know what alternatives can be used to replace those components?
Thanks in advance!
Robin
Noticed there is a typo in this PR: connexion
-> connection
due to #30 (the typo shows up a few times).
Velocity is not in SI, (1000. / 60.) should be replaced by (2. * M_PI * 1000. / 60.) to convert krpm to rad/s.
Change should also affect velocity velocity_ref and kd
Nowadays if you are doing robotics of any kind you must have Boost installed and in particular Boost python ready for your system.
Hence I would be in favor to build the master_board_sk python bindings by default.
in the CMakeLists.txt
modify the default value of BUILD_PYTHON_INTERFACE
from False
to True
When using WiFi and IMU driver together, we get a core panic error that reboot the ESP32. Investigation is needed, but the problem is likely due to task accessing resources without proper mutex.
As for now, to use Wifi, the solution is to comment the imu_init() call.
Right now, only the nice value is set in the example. To avoid the user to launch the example with chrt
commands, we can add this directly in the code via a system call.
For example in python this works:
import os
os.sched_setscheduler(0,os.SCHED_FIFO,os.sched_param(99))
As reported by @wxmerkt in #89:
When standing perfectly still (zero-order hold), we have been seeing (1) significant outliers in the velocity signal (that are different from the position signal going to zero when the SPI frequency is too high) and (2) non-zero velocity even when the joint isn't moving (the raw uint is 1 and never decrements below).
For (1), we are using filtering that includes outlier rejection and this works well. For (2), this issue impacts state estimation quite a bit and we have a work-around that if the uint is 1, we consider it to be 0. Those two changes made state estimation quite stable.
We should look into this and try to fix it on the firmware level (either master board or udrivers).
Right now running the example.cpp
requires root access on Linux. It would be great to have a way to run the demo without need for root permissions.
We should instead get the host mac address from a system call given the interface name.
When I try run sudo PYTHONPATH=. python example/example.pyc -i eth0
I have got this error:
RuntimeError: Bad magic number in .pyc file
I realize that we might have poorly chosen the velocity resolution in the communication protocol.
Indeed, as documented here https://github.com/open-dynamic-robot-initiative/master-board/blob/master/documentation/BLMC_%C2%B5Driver_SPI_interface.md#data-representation
the velocity have a resolution of 2^-11 krpm witch correspond to a motor velocity 0,48 rad/s.
With a gearbox of 9:1 it is 0,00568 rad/s at the joint level.
The velocity is encoded with 16bits and the full scale is about -16000rpm to 16000rpm.
We should agree on a lower full scale in order to increase the resolution according to our application.
Once we agree on a new fixed point value for this data representation, the next issue is that we need to upgrade all our robot and drivers at the same time.
Indeed if the driver and the robot have different data representation, we will have highly overestimate velocities measurements and this can be dangerous for our controller.
I do not have yet a good solution on how to proceed, but ideally this update would be incompatible with the current firmwares so we can not miss interpret the data.
A mechanism like this is already implemented in the PC to master board protocol (it includes and check a protocol version)
but nothing is implemented for the masterboard to uDrivers com. We could maybe change the CRC seed ? It's important that we keep this messages as short as possible, and with the CRC solution we keep the same message length.
The CRC is not transmitted to the PC, so we will need to:
What do you think ?
From users, what is the optimal range for the velocity?
A temporary solution is to use this commit of the esp-idf:
git checkout 8d1a9c07a0ff90acc3bad7143ce5154774ec1643
git submodule update --init --recursive
We need to adapt to the new HAL of the ESP32...
When running on a hard realtime thread, using printf
can be problematic. At this point, the code is printing a message of ill-sized package length from
void MasterBoardInterface::callback(uint8_t src_mac[6], uint8_t *data, int len)
{
if (len != sizeof(sensor_packet_t))
{
printf("received a %d long packet\n", len);
return;
}
For the hard realtime scenario, it would be good to have a way to log these incidents but not print them.
The 5-60V to 3.3V regulator used in the first version of the master-board is limited to 300ma. Power demand while transmitting WiFi frame can produce pick demand > 300ma.
In the next revision, we should switch to a better regulator, and add more filtering capacitors.
The fact of running the connection through a protected socket is problematic as we need sudo rights to run the low level controllers on the robot.
I would like to start here a brainstorming on how to fix it.
I am ready to invest time to fix this issue.
Add a way to specify in the sdk a clamping on the current. E.g.:
motor.SetMaxCurrentReference(max_current)
Behavior:
max_current > 0
, turns on a clamping on the current specified by motor.SetCurrentReference
max_current == 0
, turns of the current clampingmax_current < 0
, throws an ValueException
error.output of python3 -c 'import libmaster_board_sdk_pywrap; print(libmaster_board_sdk_pywrap.__file__)'
:
/home/dmitriy/git/master-board/sdk/master_board_sdk/build/libmaster_board_sdk_pywrap.so
This in VSC:
no definition found for: libmaster_board_sdk_pywrap
This is probably due to the definition of the command structure that uses uint16_t instead of int16_t for the Is value. The number is interpreted as a uint, and the sign bit is not propagate properly during conversion.
Hello,
I am trying to run example codes using wifi.
I was able run example code a few times but now suddenly I am facing this issue below.
i ran the below prequisite commands also
sudo rfkill unblock wifi
sudo ./setup_wifi.sh wlp0s20f3 1
can someone please let us know what causes this issue?
follow up to this,
can we control the motors directly using setpositionref(val) function?
@luator reported that the communication fails around 17m 45s-50s after the boards are powered one.
At this point, the number of motor boards is defined at compile time as N_SLAVES_CONTROLED
. This variable is used over the entire project.
Because this value is hardcoded, it's not possible to support to master boards with different number of controlled boards. For instance, one master board might control a quadruped (using 6 motor boards) and the other master board controlling an arm with only 2 motor boards.
One way to fix this would be to use a second argument to MasterBoardInterface
like robot_if(argv[1], num_motor_boards)
.
At this point the motor.position
and motor.velocity
returns the quantities as they are reported by the udriver boards. The udriver/ti boards use the units position: [rotations]
and velocity: [kilo rotations / minute]
.
I strongly vote we change the values stored and returned by the SDK to SI unites. That is position: [rad]
and velocity: [rad/s]
.
Greetings,
I went to this for a long time and finally I was able to completely assemble your project.
I ran into a problem: I sometimes get an error while running example.cpp.
I cannot understand what the error might be related to. Sometimes an error occurs when torque is applied to the links. Sometimes it occurs when I send a position to a link.
I am trying to use the GetErrorCode() function, but I am not getting the desired result.
P.S. I only use half of the drivers and motors.
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.