Software Movement and animations - makerforgetech/modular-biped GitHub Wiki
Introduction
The movement of the leg and neck servos is managed directly by the Arduino. The range of each servo is defined in code and can be calibrated manually. See the MakerForge.tech post and video for more information.
The Arduino sketch includes basic inverse kinematics to calculate the leg height and also integrates with an MPU6050 inertial measurement unit (IMU) to balance the relative angle of the body. These aspects are also controlled directly by the Arduino when needed.
The Arduino can assume complete control of the robot's movement to trigger random movement and animation, or can receive instructions via serial from the Raspberry Pi or other single board computer (SBC).
Raspberry Pi Controlled Movement
The Raspberry Pi can assume control of the servos by issuing instructions over serial.
In order to send instructions to the Arduino for movement, the Raspberry Pi utilises the robust_serial
library wrapped in a custom module ArduinoSerial
located within modules/network/arduinoserial.py
.
However, the default approach to managing servos is using the Servo
module which subscribes to the pubsub topics servo:[identifier]:mvabs
and servo:[identifier]:mv
for absolute and relative servo positioning respectively.
pub.sendMessage('servo:[identifier]:mvabs', percentage)
: Move servo [identifer]
to an absolute position (0 - 100)
pub.sendMessage('servo:[identifier]:mv', percentage)
: Move servo [identifer]
to a position relative to the current position (0 - 100)
Identifiers are defined as the index in the config/servos.yml
:
servos:
enabled: true
path: "modules.actuators.servo.Servo" # Include class name here
instances:
- name: "leg_l_hip"
id: 0
pin: 9
range: [0, 180]
start: 40
- name: "leg_l_knee"
id: 1
pin: 10
range: [0, 180]
start: 10
- name: "leg_l_ankle"
id: 2
pin: 11
range: [5, 165]
start: 100
- name: "leg_r_hip"
id: 3
pin: 6
range: [0, 180]
start: 60
- name: "leg_r_knee"
id: 4
pin: 7
range: [0, 180]
start: 90
- name: "leg_r_ankle"
id: 5
pin: 8
range: [10, 180]
start: 0
- name: "tilt"
id: 6
pin: 2
range: [60, 120]
start: 50
- name: "pan"
id: 7
pin: 3
range: [30, 150]
start: 50
For example, the above can be used to manage precise servo movement, such as object tracking:
pub.sendMessage('servo:pan:mv', percentage=[amount])
pub.sendMessage('servo:tilt:mv', percentage=[amount])
This approach delegates pin management, servo identification and range management to the configuration file.
(Note that the range and start position should match the values programmed in the Arduino sketch.)
Animations
As servo positioning can be complex, a preset list of animations are available via the animate
pubsub topic.
pub.sendMessage('animate', action='celebrate')
Each animation is stored in the animations
directly, simply pass the name of the .json
to the animate
topic's action
parameter.
Examples
# Start
print('Moving')
# Full Right
pub.sendMessage('servo:pan:mvabs', percentage=0)
sleep(5)
# Full Left
pub.sendMessage('servo:pan:mvabs', percentage=100)
sleep(5)
# Center
pub.sendMessage('servo:pan:mvabs', percentage=50)
sleep(5)
# Down
pub.sendMessage('servo:tilt:mvabs', percentage=100)
sleep(5)
# Up
pub.sendMessage('servo:tilt:mvabs', percentage=0)
sleep(5)
# Down a little
pub.sendMessage('servo:tilt:mv', percentage=10)
sleep(1)
# Down a little more
pub.sendMessage('servo:tilt:mv', percentage=10)
sleep(1)
# Down a little more
pub.sendMessage('servo:tilt:mv', percentage=10)
sleep(1)
# Center
pub.sendMessage('servo:tilt:mvabs', percentage=50)
sleep(5)
# Shake Head
pub.sendMessage('animate', action='head_shake')
sleep(5)
# Legs
# Stand
pub.sendMessage('animate', action='stand')
# sleep(2)
# Sit
# pub.sendMessage('animate', action='sit')
sleep(2)
print('Done')
ArduinoSerial
The Servo module should be used to send servo instructions, but the option exists to bypass this module and utilise the ArduinoSerial module to send instructions to the Arduino directly.
When initialised, the ArduinoSerial module allows data to be sent to the Arduino via serial, using the pubsub topic serial
, passing an identifier and message:
pub.sendMessage('serial', type, identifier, message)
Note: The Servo module maps the identifier to an ID automatically. If interacting with the servos directly via the serial
topic this must be done manually. The identifier is not the pin, the mapping to pin from ID takes place in the Arduino ServoManager sketch.
Message types
The following types are possible:
ArduinoSerial.DEVICE_SERVO
: Instructions for servo movementArduinoSerial.DEVICE_SERVO_READ
: Instructions for servo movement, relative to current position.ArduinoSerial.DEVICE_PIN
: Instruction to change pin valueArduinoSerial.DEVICE_PIN_READ
: Read pin value (such as battery voltage)ArduinoSerial.DEVICE_LED
: Instructions for neopixels connected to the Arduino (not currently in use)
Servo Movement
When a servo type is passed (either absolute or relative), the identifier should include the identifier of the servo or list of identifiers to move.
The message should then be a value between 0 and 100 representing the percentage value (or change, if relative) of the servo.
Pi Servo Control
The head also has a single servo connected that is controlled directly by the Raspberry Pi. This is managed by the PiServo
module located in modules/actuators/piservo.py
.
This module currently controls a single servo but could be adapted to control multiple servos if required (assuming pin availability).