General_Robotics - RicoJia/notes GitHub Wiki

========================================================================

Forward Kinodynamics

========================================================================

  1. Roll-Pitch-Yaw are euler angles (Tait-Bryan). 2 orders:

    • XYZ (x pointing forward, mobile vehicle)
    • ZYX (z pointing forward, gripper)
  2. Angular Velocity R_dot = w x R

    • The write them in a group:

  3. Another way to prove R_dot = w x R due to rotation is from rodrigue's formula, R = e^(w theta). Notice the use of skew-matrix

  4. Additive rule of angular velocity: when two frames are rotating at the same time, the angular velocity at each moment is the sum

  5. DH parameters: rotation around x (alpha), distance along x (ai), distance along z (di), rotation around z (theta)

    1. E.g, PUMA 560

    2. DH formula: rotate z -> translate along z -> translate along x -> rotate x

    3. Finally, it's

========================================================================

Behvaviors

========================================================================

  1. Behavior Tree

  2. Intro

    • executable nodes are: conditional node (1 tick), and executable node
      • leaf nodes = executable nodes
      • Tree starts from left to right. If root returns failure, then it's a failure
    • 4 types of control nodes:
      1. sequence (all nodes must return true)
      2. fallback (one node returns true)
      3. Parallel (nodes will execute in parallel, not necessarily true parallelism)
      4. Decorator (modifies result of child), can invert, force a result, or repeat
        • Only one child!
    • Infrastructure
      1. Blackboard:

  3. Pros and Cons:

    • reactivity: check if battery is okay at every single step. Easier to do it wtih state machines, than with BT
    • So finite state machine with bt in it.
  4. The combo: py_trees, py_trees_ros, rqt_py_trees

    • py_trees_ros publishes all nodes in tick()

Py trees

  1. pytree ros

    1. Installation: py_trees need ot be pip install .
  2. Code review (read the behavior tree example first)

    1. 5 elements: Selectors, Sequences, Parallels (these are composites), Decorator, and Behavior

    2. Behavior

      • behavior.attach_blackboard_client: create blackboard client, store it, and return it
      • Setup_with_descendents: call setup() on descendents too
        • Alternatively: py_trees.trees.BehaviourTree.setup()
      • tick():
        1. call initialise() if not running
        2. call update()
        3. update status
        4. yield itself. So you must use for ...
      • tick_once():
        1. for _ in self.tick()
      • iterate(): yield the leaf child nodes first, then finally itself.
      • stop(): calls terminate(). terminate(new_status)
        • terminate() is called when a behavior ends
      • had_parent_with_name(): searches through all parents
      • Behaviors:
        ConditionalBlackboardSet: generic condicitonal that writes values to blackboard on success/failure of the outcome.
            - In init: 
                - get blackboard keys, success_write (function(blackboard)), default None, and failure_write
                - get ```condition(blackboard)```
        
            - In update:
                - Check condition(blackboard). If success, then try checking success_write if defined. Else, try failure_write 
        
    3. composites: Selector(Fallback), Sequences, Parallels

      • Selector: keeps going until one succeeds
      • Sequence: keeps going until one fails
        • memory: if previous tick is RUNNING, resume from there.
      • Parallel:
        • in one tick, all behaviors are ticked (though sequentially, on a single thread)
        • Note that if one child fails, SuccessOnOne doesn't work (it only works with child that that's invalid/success)
    4. render dot tree:/home/rjia/third_party_installs/py_trees/py_trees/demos/context_switching.py

    5. decorators:

      decorator class: 
          - Init
              1. check if child are Behaviour
              2. has children (only one child?). decorated is its first child
          - tick:
              1. initialise  itself
              2. call decorated.tick() (all its children too)
              3. self.update()
      Condition(Decorator):
          - self.update():
              1. check if decorated is in a desire state (default is SUCCESS). 
                  - If so, return SUCCESS
                  - Else: return FAILURE
      SUCCESS_IS_X:
          - self.update(): returns X when state becomes SUCCESS
      FAILURE_IS_X:
          - self.update(): returns X when state becomes FAILURE
      Inverter:
          - self.update(): returns not(state)
      Oneshot: 
          1. self.tick(): ticks through all children. When final_state is set, call self.update(), and calls self.stop() 
          2. self.update(): keep running and return decorated status until final_state is set. 
          - self.terminate(): called when decorated status is not RUNNING. 
              - Then check if final_state is set, and check if it's policy value. Set final_state
      Timeout:
          - self.update(): when time is up, return failure
      StatusToBlackboard: 
          - init: creates a blackboard, gets a variable, rip the variable's first part before '.', 
          - update: set blackboard variable to value: child.status (success/failure)
      EternalGuard?
      
    6. Blackboard: fake "Singleton" by using class variables and static methods

      1. client = Behaviour.attach_blackboard_client: create Client object: -> Blackboard.clients[Client.unique_identifier ] = Client.name
      2. client.register_key("number_of_noodles", Access.write): Blackboard.metadata[remapped_key].write.write.add() # write is actually a Set object. this param is added to this set
      3. self.state.number_of_noodles = 32 # now you can write to this param, Note, you are calling this __getattr__ func, so the attr will be fetched from here
      
    7. tree:

      1. behaviour_tree = py_trees.trees.BehaviourTree( root=root): just setting vars
      
      2. behaviour_tree.setup(timeout=15)
      
      3. behaviour_tree.tick_tock(
              period_ms=500,
              number_of_iterations=py_trees.trees.CONTINUOUS_TICK_TOCK,
              pre_tick_handler=None,
              post_tick_handler=print_tree
          )
      tick_tock is to call self.tick(pre_tick_handler, post_tick_handler), until interruption -> tick: 
          1. call all pre-handlers (can be a list)
              - calls all visitor.initialise() 
          2. Call all ticks: (let all visitors to visit?)
              - call all ticked node.visit(visitor)
          3. call iterate on all tree nodes
              - calls all iterated nodes.visit()
          4. Calls all visitor.finalise()
          5. call post_tick_handler
      
    8. Additionals

      1. Conditional
        conditional_behavior = Conditional(
            condition=check_blackboard_predicate,
            blackboard_keys={'board_waypoint'}
        

      )

       class Conditional(py_trees.behaviour.Behaviour):
           def __init__(self, name: str, condition, blackboard_keys: Union[List[str], Set[str]]):
               super(Conditional, self).__init__(name)
               self.blackboard = py_trees.blackboard.Client(name=name)
               for key in blackboard_keys:
                   print(f"registering {key} for read access")
                   self.blackboard.register_key(key, py_trees.common.Access.READ)
               self.condition = condition
      
           def update(self):
               return self.condition(self.blackboard)
       ```
      
      1. Visitors:
        1. class SnapshotVisitor()
            - initialize visited, previously visited ()
            - And a bunch of other variables
        
        2. def post_tick_handler(snapshot_visitor, behaviour_tree):
            print(
                tree_str = py_trees.display.unicode_tree(
                    behaviour_tree.root,
                    visited=snapshot_visitor.visited,
                    previously_visited=snapshot_visitor.visited
                )
            )
            - This displays a tree.
        3. behaviour_tree.add_post_tick_handler( functools.partial(post_tick_handler, snapshot_visitor))
            - This binds snapshot_visitor to post_tick_handler
            - adds the print as post_tick_handler
        4. behaviour_tree.visitors.append(snapshot_visitor)
        5. behaviour_tree.tick_tock()

========================================================================

Motor

========================================================================

General

  1. all motors work by magnets being attracted to & propelled from each other.

Servo

  1. Nice vid

    • velocity is defined: 60 deg/time. Usually 0.11-0.21/60deg
    • Voltage: 4.8v, 6v. Higher the voltage, the better torque
    • Current, usually not provided, but usually no load: <400mA, with load > 1A. Of course, motor near the ee has lower current. 6v, 5A power source is good.
      • If on battery, need LDO (Linear regulator); 同时可能要稳压
    • gear box is to reduce speed, and increase torque.
      • 行星减速箱, planetary gears: transform very large torque in compact form.

      • at the ee, use 谐波减速器, harmonic gear drive
      • harmonic drive: misaligned stator and output rings' teeth will become a wedge. Inserting the flex's tooth into them will cause the the two rings aligned.

  2. Disadvantages:

    1. Closed loop control is pretty coarse: encoder needs to be more precise;
      • deadzone (or deadband) is certain input, but zero output
    2. closure can be aluminum, better cooling
    3. metal gear is harder
  3. Nice article for troubleshooting see article

Stepper Motor

  1. When one teeth is energized (usually as north), the rotor will come

  2. Can do half stepping by energizing two neighboring teeth.

  3. In a full on motor, 1.8 deg is quite common. With Half stepping, it can be 0.9 deg

  4. Advantages:

    • Open loop control, ok precision, good torque, so cheap
    • Accuracy: errors don't add up
    • cheap
    • Torque is good for slow speed

    • has "detent torque", will hold things in place
    • Only the shaft bearing will wear out
  5. Disadvantages:

    • torque will plummet as speed goes up
    • need to overcome detent torque, which draws a lot of current
    • Can be noisy.
    • Cannot accelerate very rapidly
  6. Zero-gravity?

    1. In low gravity, Korioli force and M are small. Only consider Gravity & friction terms v2-845a6a3743095cd8b574f45e297d44f9_1440w
    2. H(G) is a matrix of trigonometric functions of joint angles. v2-93d5ab6e9c4a3c337f7b0fc3e395ee16_1440w
    3. There's a solution to H. But we need to estimate Pi_G. So we let the joint travel at very low speed, forward and backward, measure the torques. Then we can get an estimate of Pi_G as the psudo-inverse as shown below v2-c00760df5cc59d02d573b7539feca8ea_1440w v2-3fe25632e7e1f6706a4ff4223e016f23_1440w

========================================================================

Sensors

========================================================================

  1. torque sensor: there are two types: using "serial elastic actuator" (联动轴) and emasure angular differences, or measure strain with resistive strain gauge

  2. LIDAR technology
    • Tech
      • HDDM: high definition distance measurement; 1.5km retro-reflective tape
      • Laser (Light Amplification by Stimulated Emission of Radiation) can operate in IR range.
      • Sick: tim571, 0.05m - 25m, Hokuyo: 10m
    • diffuse reflectors, like matte surface, or reflective tape, scatter light in many directions
    • specular reflectors, like a mirror, reflect infrared in different angles. So you may not get a signal at all.
    • glasses, light rays can be refracted and bend light travel paths
  3. Ethernet cable is better than USB:
    • more physically robust
    • More robust in electrically noisy env
    • faster speed: Ethercat can do real time. USB3.1 10Gbps, 3.2 20Gbps; ethernet: 10, 25, 40, 100 Gbps
    • Power over Ethernet

========================================================================

3D Printing

========================================================================

  1. You need a "slicer" to convert stl to steps. https://www.learnrobotics.org/blog/convert-stl-g-code-3d-printing/

  2. Things to check for 3D printing:

    1. Y-axis bolts. (bottom)
    2. Bed should be loose.
    3. Bed motion should be smooth
      • Check rollers below the bed. Rollers should be loose
    4. Lower the nozzle to the lowest. There should be a gap between the nozzle and the bed.
  3. Work flow:

    1. Connect to power.
      • Preheat PLA
    2. prepare -> autohome
    3. move-> Z to zero
    4. Disable stepper motor
    5. move -> manually change z offset to fit a piece of paper underneath
      • Springs should turn to the right to lower the bed
    6. Auto leveling
      • It goes to 4x4 positions to find the level spot
  4. Nozzle cleaning:

    1. The 90 deg method
      1. heat up your nozzle to 200.
      2. go to control, change nozzle temp to 90
      3. when it hits 90, pull the filament out.
  5. Misc:

    1. Tnut

========================================================================

Misc

========================================================================

  1. docking & undocking: kobuki has some interesting stuff there. http://wiki.ros.org/kobuki/Tutorials/Automatic%20Docking

  2. Simulators:

    • Gazebo: Physics Engine, ODE, bullet, simbody, DART -> OGRE(object-oriented graphics rendering engine)
    • Webots come as a close second
  3. robot code:

    • Know what can fail: Manip, perception ..., and add error handling
    • Important rule: LOG EVERYTHING: the world is more hairy than you think. Reproducing the issue
    • Have different types of errors, not just a simple return True
    • Decorator: on high level of the stack, we need to wait for hardware to respond, etc., time spent gets lost in noise
    • If it's training, save the intermediate results in a rolling buffer (if something breaks)
  4. Snapshot-logger Kafka: Say we have /point_cloud on the robot.

    1. serialize the message using protobuf.
    2. ros bridge: -> kafka topics
    3. On the server, need java to run kafka, and the zoo keeper (sync)
    4. create kafka topic using a kafka script
      • What does a kafka log look like? Stored as ordered, immutable partitions, which then are ordered, immutable segments in files: each segment has .index and .log Each .log has records timestamp, key-value, metadata
      • store events as logs temporarily with a retention policy. Otherwise, you have to have a huge monolith database.
      • timescale db to permanently store; else, Amazon S3.
      • Can read with an index
    5. Kafka consumer subscribes to the topic.
  • What you get from kafka:
    • retention
    • Fault tolerance
    • Partition: a topic can be broken down to different partitions
      • from a list of brokers, the zoo keeper elects the leader broker, the broker that handles the current partition
      • So consumers' reading can be parallelized
⚠️ **GitHub.com Fallback** ⚠️