[[PageOutline(2-5, Table of Contents, floated)]] = User guide (git) = ''This documentation tries to follow the developement version of Py4bot. It may or may not be up-to-date.'' For installation instructions, see [InstallationGuide here]. == Usage overview == As Py4bot is a framework, you will find here a description of the main things you need to understand to write your own applications. Refer to the [htdocs:api/index.html complete API] for more details about classes/methods used. == Architecture == The main parts of the framwork are: * the '''robot''' itself; * the '''gait sequencer'''; * one or more '''remote controllers'''. [[Image(design_simple.png​, 300px)]] Each of these parts runs as separate thread. For now, the robot does nothing in its main loop, ans so, can be used for further devs (automatic stabilization...). == Geometry definition == There are several coordinates systems involved when computing maths in order to make a robot walk; it is important to understand how they are defined. All these systems are cartesian. In the image below, X axis is in cyan, Y axis is in magenta, and Z axis is in yellow: [[Image(coordinates_systems.png, 300px)]] === Robot coordinates system === This coordinates system is attached to the robot itself: * the origin is at the center of the robot, in the ground plane * X and Y axes are in the ground plane * Y axis is the back-to-front axis of the robot * Z axis points up === Body coordinates system === This coordinates system is attached to the body. It is defined from the robot coordinates system: * the origin is at the center of the body * X and Y axes define a plane parallel to the body * Y axis is the back-to-front axis of the body * Z define the top side of the body This system is used to define the position of the body in the robot coordinates system, allowing it to move along the 6 DoF (3 translations, 3 rotations). === Legs coordinates systems === These coordinates systems are attached to the legs, so each leg has its own coordinates system. They are defined from the body coordinates system: * the origin is at the coxa joint * X and Y axes define a plane parallel to the body * X axis is along the coxa of the leg * Z points up To summurize, from the body coordinate system, the legs coordinates systems are translated by '''(x, y)''' and rotated by '''gamma0''' arround Z: [[Image(body_legs.png, 300px)]] ''Todo: improve drawing'' === Feet coordinates systems === They are the last coordinates systems used in this framework, and they are used by the gaits, to make to robot walk. They are defined from the robot coordinates system: * the origins are at the center of the feet, in the ground plane * X and Y axes are in the ground plane * Y axis is the back-to-front axis of the robot * Z axis points up To summurize, from the robot coordinate system, the gaits coordinates systems are translated by '''(x, y)'''. === Inverse Kinematic === The Inverse kinematic is the the kinematic equations of a robot to determine the joints parameters that provide a desired position of leg (foot). Here are the angles involved: ==== 3 DoF leg ==== * '''gamma''': angle of the leg in the the body X/Y plane (angle between body X axis and leg X axis) * '''alpha''': angle of the femur in the leg X/Z plane (angle between coxa and femur) * '''beta''': angle of the tibia in the leg X/Z plan (angle between femur and tibia) [[Image(IK3DoF.png, 300px)]] ==== 4 DoF leg ==== * '''tars''': angle of the tars in the leg X/Z plan (angle between tibia and tars) [[Image(IK4DoF.png, 300px)]] == Robot == The '''robot''' is responsible for all static computation, ie implements the '''inverse Kinematic'''. It also manages the body position, which can move along the 3 axes, and rotate arround 3 axes. As shown in the [[Tutorials|tutorials]], to implement a custom robot, you need to write a new class which inherits from {{{Robot}}}, and overload several methods: * {{{_createBody(self)}}} * {{{_createLegs(self)}}} * {{{_createActuatorPool(self)}}} This is where you choose how many legs your robot has, and how many degrees of freedon (Dof) each leg has. The {{{Robot}}} object has some usefull methods you will have to use in order to make your robot do smart things: * {{{setBodyPosition(self, x=None, y=None, z=None, yaw=None, pitch=None, roll=None)}}} This method can only be called when the robot is in ''idle'' state. It translates/rotates the body, and the new position is kept. * {{{incBodyPosition(self, dx=0., dy=0., dz=0., dyaw=0., dpitch=0., droll=0.)}}} This methods can be called in any robot state. Like the previous method, you can adjust the body position, by little steps. * {{{setBodyExtraPosition(self, x=None, y=None, z=None, yaw=None, pitch=None, roll=None)}}} This method can only be called when the robot is in ''idle'' state. Like the first method, you can translate/rotate the body. The resulting position of the body is the combination of the bodyPosition and the bodyExtraPosition. The {{{setBodyPosition()}}} is mainly used at startup, to set a pre-defined position of the body. The {{{setBodyExtraPosition()}}}, however, can be usefull to move the body arround its default position, without loosing it. * incFeetNeutral(self, dneutral) This method can only be called when the robot is in ''idle'' state. It allows you to extend/reduce the ''length'' of the legs. Each time this method is called, the robot will do a ''static walk'', in order to put all feet to there new neutral position. == Actuators, Pools and Drivers == {{{Actuator}}}s are the objects which really move the {{{Joint}}}s. {{{Pool}}}s are used to group {{{Actuator}}}s, mainly to moved them in a synchronized way. It is possible to have the same {{{Actuator}}} in several {{{Pool}}}s, but, of course, you won't be able to drive both {{{{Pool}}}s at the same time. A {{{Pool}}} uses a {{{Driver}}} to really make the {{{Actuator}}}s move. === Servos calibration === There are different reasons why you need to calibrate your servos, depending on: * how you attached your servos to the robot * what servos your actually use * how accurate servos are You can use the '''{{{py4bot-gui-servocal.py}}}''' to fine tune your servos calibration, and generate the {{{SERVOS_CALIBRATION}}} dict. [[Image(py4bot-gui-servocal.png, 300px)]] Most servos have a range of 180°. So, it is important to mount them on the robot so the servo neutral position (''SNP'') matches the joint neutral position (''JNP''). Here is the leg neutrals usually used for a 3 DoF leg: [[Image(IK3DoF_neutral.png, 300px)]] This position should be reached when servos pulses are 1500µs (1500µs is the neutral pulse of hobby servos). It may vary a little bit, and you can fine tune this value by scanning the mechanical range of the servo, and take the middle value (neutral_pulse = (min_pulse + max_pulse) / 2). A little servo tester can be helpful. In the above position, ''SNP'' are all 90°, as it is standard servo neutral position for 1500µs. Looking how '''Py4bot''' internally manages angles ([[UserGuideGit#a3DoFlegs]]), we can see that in this position, ''JNP'' are: * coxa = 0° * femur = 180° * tibia = 90° This means that there will be some offset between the servo angles and the framework angles. Another thing to tune is the ratio between pulse variation and real servo displacement. This ratio varies a lot from a brand to another. And even for a same model, it varies from a servo to another. This is especially true for low cost servos. Offsets and ratios are defined in the {{{SERVO_CALIBRATION}}} table. This table also has a '''pulse90''' param, to fine tune the ''SNP'' (it is not always possible to mount the servo so 1500µs is the perfect ''JNP''). Here is how to use '''{{{py4bot-gui-servocal.py}}}'''. We first need to enable the servo, by clicking the '''Enable''' checkbox. Then, we need to check if the servo rotates the right direction: increasing the pulse value should increase the joint angle (= make in turn in the trigonometric sense in the leg coordinate system). If it is not the case, click the '''Invert''' checkbox (usually, coxa joints are all the same, and other joints should be inverted for legs of one side, but it depends if there is a symmetry in the mechanics or not). Note that from within this tool, the servo direction won't change! But the ratio is inverted, so '''Py4bot''' will compute angles the right way. We are now ready to fine tune the ''SNP'', and set its matching ''JNP''. To do this, we move the '''Pulse''' slider until we mechanically reach the ''JNP''. Then, we move the '''Joint neutral''' slider to match the theoretical ''JNP'' for that specific joint (as we seen, coxa = 0°, femur = 180°, tibia = 90°). Then, we click the '''Set pulse''' button of the joint neutral setting. This recomputes the '''offset''' and '''pulse90''' params of the {{{SERVO_CALIBRATION}}} table. Then, we need to tune the ratio. This step is a little bit harder, as we need to measure the angle the joint really moves. The best way is to move up to +-90°, as it is visually easy to see, but it is not always mechanically possible, and we can restrict the range to +-45°. So, we move the 'Angle min' slider to -45°. Then, we move the '''Pulse''' slider so our joint really reaches -45°. Last, we click the '''Set pulse''' button of the '''Angle min'' slider to recompute the ratio. We of course need to repeat the procedure for the angle max. After both have been tuned, the ratio should be correct. And we need to repeat the entire procedure for each servo/joint, which can be tedious for a 4 DoF hexapod :o/ But after that, our robot should walk better ;o) Note that if we already have a '''{{{settings.py}}}''' module, we can launch '''{{{py4bot-gui-servocal.py}}}''' from the directory containing that module in order to reload the previous values. == Gaits and !GaitSequencer == The '''Gaits''' and '''!GaitSequencer''' implement the dynamic part of the movements, ie the gait itself. It computes the successive feet positions in order to make the robot walk. [[Image(design_gait.png, 300px)]] == Remote controllers == The {{{RemoteControl}}} translates user orders to {{{Robot}}}/{{{GaitSequencer}}} methods calls. [[Image(design_remote-control.png, 300px)]] As you can see on the UML diagram, a {{{RemoteControl}}} object is build with {{{Components}}}; a {{{Component}}} can be a {{{Button}}}, a {{{Analog}}} axis, or a {{{Joystick}}}, which is several {{{Analog}}} axes bound together. === Using Mappers === '''Mappers''' are simple objects helping to adapt params from '''!RemoteControl''' '''Components''' output to '''Robot'''/'''!GaitSequencer''' methods input. For example, to control the robot walk, we can create a '''Joystick''' component with 3 axes: X, Y, RZ. But the '''!GaitSequencer''' '''walk()''' method expects '''speed''', '''direction''', '''length''' and '''angle''' params. Using the '''!MapperWalk''' mapper, you can compute all these params from X/Y/RZ axes, and send them to the '''walk()''' method. That's what we did in the [[Tutorials|tutorials]]. See [source:/py4bot/inputs/mappers/mapper.py] to see how this mapper is defined. Of course, you can define your own '''Mappers'''. === Add a new Frontend === {{{Frontend}}}s are responsible of generating states. This is where specific controllers implementation live. There are some usefull {{{Frontend}}}s defined in '''Py4bot''', mainly USB-based, using ''event'' interface.