Initial design for the leg that I have been using for testing.
- Upper leg length: 55mm
- Lower leg length: 55mm
- More as I know them...
- Make an upper leg
- Make a lower leg
- Buy more servos for more legs
- New upper leg design so that there is some natural compliance at the joints
- Make 3 more legs
- Make the dogs body
- Position a single foot in Z space (Isosceles Triangle)
- Position a single foot in X space (Right Angled Triangle)
- Figure a clean way to add the "trim" or microsecond offset that is required to move the joints to the zero position
- Work out exact radians to servo microseconds mapping ranges
- Add smoothing to servos (should get this for free with interpolation and using an easing out curve like a sine curve)
- Add hal for RAMP library
- Use hal RAMP for interpolation
- Try slower max speed for servos or different curve to make movement smoother, or add an additional smoothing that has a bias for the previous value as the interpolation doesn't get to use the sine wave to ease out if the inputs constantly change. Keep interpolation for the gaits.
- Figure out how to make both joints get to the destination angle at the same time when using smoothing (This might actually happen for free because it uses percentages)
- Figure out the relationship in smoothing between the percentage of the previous value and how long it takes (and how many steps it takes) to get to the destination
- Change max height depending on forward/back amount?
- Set starting position of robot so we dont have to rely on center joysticks
- Make calculations mockable so the
two_axis_leg
tests are better (templatedconstrict
holding me back) - Take the servo pins in the constructor of the leg impls so the interfaces don't need to know how many pins a specific impl will need in the begin function?
- Should dog
set_position
invert the forward back position so that when you set the dog position forward the body goes forward and the leg goes back? - Write code to position all legs independently
- Make the event callback in
ps4_controller
return optional values, if its not updated it will return 0 which is not what we want. (No std::optional in C++14 :cry-face:) - Make
set_position
intwo_axis_leg
default to previousforward_back
and previousheight
if new ones aren't provided? (Createdset_height
andset_forward_back
that usesset_position
) - Document how I use triangles for the inverse kinematics
- Use an
executer
for the connected lights instead of manually creating a task to do it - Fix helper functions in
two_axis_leg_tests
to move the common code to a new function - Change knee joint range so that straight isn't max movement. As 180 degrees the other way is an impossible location
- If the movement type isn't the same as the movement type before do I need to clear down the smoother/interpolator? (No, starting the next movement type sets it to the new starting location and forgets what was there before)
- Do some research to see if I can use EEPROM along with the PS4 library
- Try and find out why the PS4 controller doesn't return correct button presses when using the events version. Do I have to change to to looping and checking? :( (There is a bug in the library, I have created a pull request with the fix)
- Add
dog_tests
that test the previous values - Add a smart algorithm that leans the opposite side more if the current side is already at max. For example, if the dog is standing full tall and it leans to the left, it will currently lower the left side and it can't raise the right as its at max height. It should lower the left side by double the amount in this case.
- Use
minimum_time_for_max_rotation_
- Better name for
has_position_changed_
and tests for it - Make gait to lift opposite legs
- Make gait to walk
- Statemachine for different modes controlled by the PS4 remote
- Remove travis integration?
- Position a single foot in Y space (Right Angled Triangle). Requires a hip design for the dog and more servos
- Add an event loop so that it is easier to control what happens on what
cores. Currently the gamepad calls a callback with the updated values, the
callback sets atomic variables that then are read by core
1
. This is abit "nasty" but if I call the leg/robot/controller functions in the callback they will be executed on core one, possibly slowing down reading from the gamepad.- This has been implemented here with a basic wrapper around the esp32 event loop
- Ideally I would like to make a really nice C++ wrapper for this that
would take events that carry the data and be able to just pass
std::function
s for the event_handlers. This is proving tricky and nastier than the version above. Initial implementation is here
- PS Button: Connects the controller to the dog
- Left Stick Left and Right: Move the body forward and back
- Left Stick Up and Down: Change the height of the dog
- Right Stick Left and Right: Lean the dog side to side
- Right Stick Up and Down: Lean the dog forward and back
- Options Button: Change to trimming mode
- Left Arrow: Trim active limbs knee joint to the left (looking from the side)
- Right Arrow: Trim active limbs knee joint to the right (looking from the side)
- L1: Trim active limbs shoulder joint to the left (looking from the side)
- R1: Trim active limbs shoulder joint to the right (looking from the side)
- Cross: Move to next limb
- Circle: Change to leaning mode without saving trim values
- Options Button: Change to leaning mode and save trim values
- Conan: Package manager for C++. Used to get GoogleTest for the unit tests
- 8 MG90S servos (12 if the stretch goal of positioning in Y space is met)
- ESP32 38 pin model, with 2 cores wroom-32 (Models with different amounts of pins should work, pins may/may not need changed for other models)
- Power supply for the servos (I use a 2 cell, 7.4v lipo regulated to 6v)
- 3D Printer
- PS4 Controller with a MAC address that you know or have reset
- Have a global shared pointer to a manager that is a state machine. Different
states would be different "modes".
- Mode for triming servos to correct angle.
- Mode for leaning.
- Mode for walking.
- Etc
- Simple Version
- On PS4 controller event call through to the manager with the event.
- This will happen on core
0
as the PS4 controller events run there.
- This will happen on core
- On core
1
continually call update on the robot. - Need to think whether the manager/dog/leg/interpolation/servo will be happy with this happening on 2 cores. Semaphore?
- On PS4 controller event call through to the manager with the event.
- Save to Atomic Variables
- Have atomic variables for stick position etc and only call through to
control the robot on core
1
using the atomic variables that would be set from core0
.
- Have atomic variables for stick position etc and only call through to
control the robot on core
- Event Loop
- Have an event loop (or 2) to run things on specific cores.
- Have event loop on core
1
at a higher priority than the updating robot task. Then when an interesting controller event happens, post the call on the event loop. Core1
can't run two things in parallel so theres no worries about "strange" things happening. Need to make sure that the event executes the events quickly even with the updating task being quite busy.