comparison thesis/cortex.org @ 466:da311eefbb09

finish body -- needs more work, but whatever.
author Robert McIntyre <rlm@mit.edu>
date Fri, 28 Mar 2014 13:16:37 -0400
parents e4104ce9105c
children ade64947d2bf
comparison
equal deleted inserted replaced
465:e4104ce9105c 466:da311eefbb09
19 #+caption: 19 #+caption:
20 #+caption: 20 #+caption:
21 #+caption: 21 #+caption:
22 #+name: name 22 #+name: name
23 #+ATTR_LaTeX: :width 10cm 23 #+ATTR_LaTeX: :width 10cm
24 [[./images/Eve.jpg]] 24 [[./images/aurellem-gray.png]]
25 25
26 26
27 27
28 * COMMENT Empathy and Embodiment as problem solving strategies 28 * COMMENT Empathy and Embodiment as problem solving strategies
29 29
528 engine, and must also be easy to rig with =CORTEX='s senses. 528 engine, and must also be easy to rig with =CORTEX='s senses.
529 529
530 While trying to find a good compromise for body-design, one option 530 While trying to find a good compromise for body-design, one option
531 I ultimately rejected is to use blender's [[http://wiki.blender.org/index.php/Doc:2.6/Manual/Rigging/Armatures][armature]] system. The idea 531 I ultimately rejected is to use blender's [[http://wiki.blender.org/index.php/Doc:2.6/Manual/Rigging/Armatures][armature]] system. The idea
532 would have been to define a mesh which describes the creature's 532 would have been to define a mesh which describes the creature's
533 entire body. To this you add an skeleton which deforms this 533 entire body. To this you add a skeleton which deforms this mesh
534 mesh. This technique is used extensively to model humans and create 534 (called rigging). This technique is used extensively to model
535 realistic animations. It is hard to use for my purposes because it 535 humans and create realistic animations. It is not a good technique
536 is difficult to update the creature's Physics Collision Mesh in 536 for physical simulation, because deformable surfaces are hard to
537 tandem with its Geometric Mesh under the influence of the 537 model. Humans work like a squishy bag with some hard bones to give
538 armature. Without this the creature will not be able to grab things 538 it shape. The bones are easy to simulate physically, but they
539 in its environment, and it won't be able to tell where its physical 539 interact with thr world though the skin, which is contiguous, but
540 body is by using its eyes. Also, armatures do not specify any 540 does not have a constant shape. In order to simulate skin you need
541 rotational limits for a joint, making it hard to model elbows, 541 some way to continuously update the physical model of the skin
542 shoulders, etc. 542 along with the movement of the bones. Given that bullet is
543 optimized for rigid, solid objects, this leads to unmanagable
544 computation and incorrect simulation.
543 545
544 Instead of using the human-like ``deformable bag of bones'' 546 Instead of using the human-like ``deformable bag of bones''
545 approach, I decided to base my body plans on multiple solid objects 547 approach, I decided to base my body plans on multiple solid objects
546 that are connected by joints, inspired by the robot =EVE= from the 548 that are connected by joints, inspired by the robot =EVE= from the
547 movie WALL-E. 549 movie WALL-E.
584 586
585 #+caption: View of the hand model in Blender showing the main ``joints'' 587 #+caption: View of the hand model in Blender showing the main ``joints''
586 #+caption: node (highlighted in yellow) and its children which each 588 #+caption: node (highlighted in yellow) and its children which each
587 #+caption: represent a joint in the hand. Each joint node has metadata 589 #+caption: represent a joint in the hand. Each joint node has metadata
588 #+caption: specifying what sort of joint it is. 590 #+caption: specifying what sort of joint it is.
591 #+name: blender-hand
589 #+ATTR_LaTeX: :width 10cm 592 #+ATTR_LaTeX: :width 10cm
590 [[./images/hand-screenshot1.png]] 593 [[./images/hand-screenshot1.png]]
591 594
592 595
593 596 =CORTEX= creates a creature in two steps: first, it traverses the
594 597 nodes in the blender file and creates physical representations for
595 598 any of them that have mass defined.
596 599
600 #+caption: Program for iterating through the nodes in a blender file
601 #+caption: and generating physical jMonkeyEngine3 objects with mass
602 #+caption: and a matching physics shape.
603 #+name: name
604 #+begin_listing clojure
605 #+begin_src clojure
606 (defn physical!
607 "Iterate through the nodes in creature and make them real physical
608 objects in the simulation."
609 [#^Node creature]
610 (dorun
611 (map
612 (fn [geom]
613 (let [physics-control
614 (RigidBodyControl.
615 (HullCollisionShape.
616 (.getMesh geom))
617 (if-let [mass (meta-data geom "mass")]
618 (float mass) (float 1)))]
619 (.addControl geom physics-control)))
620 (filter #(isa? (class %) Geometry )
621 (node-seq creature)))))
622 #+end_src
623 #+end_listing
624
625 The next step to making a proper body is to connect those pieces
626 together with joints. jMonkeyEngine has a large array of joints
627 available via =bullet=, such as Point2Point, Cone, Hinge, and a
628 generic Six Degree of Freedom joint, with or without spring
629 restitution. =CORTEX='s procedure for binding the creature together
630 with joints is as follows:
631
632 - Find the children of the "joints" node.
633 - Determine the two spatials the joint is meant to connect.
634 - Create the joint based on the meta-data of the empty node.
635
636 The higher order function =sense-nodes= from =cortex.sense=
637 simplifies finding the joints based on their parent ``joints''
638 node.
639
640 #+caption: Retrieving the children empty nodes from a single
641 #+caption: named empty node is a common pattern in =CORTEX=
642 #+caption: further instances of this technique for the senses
643 #+caption: will be omitted
644 #+name: get-empty-nodes
645 #+begin_listing clojure
646 #+begin_src clojure
647 (defn sense-nodes
648 "For some senses there is a special empty blender node whose
649 children are considered markers for an instance of that sense. This
650 function generates functions to find those children, given the name
651 of the special parent node."
652 [parent-name]
653 (fn [#^Node creature]
654 (if-let [sense-node (.getChild creature parent-name)]
655 (seq (.getChildren sense-node)) [])))
656
657 (def
658 ^{:doc "Return the children of the creature's \"joints\" node."
659 :arglists '([creature])}
660 joints
661 (sense-nodes "joints"))
662 #+end_src
663 #+end_listing
664
665 To find a joint's targets targets, =CORTEX= creates a small cube,
666 centered around the empty-node, and grows the cube exponentially
667 until it intersects two /physical/ objects. The objects are ordered
668 according to the joint's rotation, with the first one being the
669 object that has more negative coordinates in the joint's reference
670 frame. Since the objects must be physical, the empty-node itself
671 escapes detection. Because the objects must be physical,
672 =joint-targets= must be called /after/ =physical!= is called.
673
674 #+caption: Program to find the targets of a joint node by
675 #+caption: exponentiallly growth of a search cube.
676 #+name: joint-targets
677 #+begin_listing clojure
678 #+begin_src clojure
679 (defn joint-targets
680 "Return the two closest two objects to the joint object, ordered
681 from bottom to top according to the joint's rotation."
682 [#^Node parts #^Node joint]
683 (loop [radius (float 0.01)]
684 (let [results (CollisionResults.)]
685 (.collideWith
686 parts
687 (BoundingBox. (.getWorldTranslation joint)
688 radius radius radius) results)
689 (let [targets
690 (distinct
691 (map #(.getGeometry %) results))]
692 (if (>= (count targets) 2)
693 (sort-by
694 #(let [joint-ref-frame-position
695 (jme-to-blender
696 (.mult
697 (.inverse (.getWorldRotation joint))
698 (.subtract (.getWorldTranslation %)
699 (.getWorldTranslation joint))))]
700 (.dot (Vector3f. 1 1 1) joint-ref-frame-position))
701 (take 2 targets))
702 (recur (float (* radius 2))))))))
703 #+end_src
704 #+end_listing
705
706 Once =CORTEX= finds all joints and targets, it creates them using a
707 simple dispatch on the metadata of the joint node.
708
709 #+caption: Program to dispatch on blender metadata and create joints
710 #+caption: sutiable for physical simulation.
711 #+name: joint-dispatch
712 #+begin_listing clojure
713 #+begin_src clojure
714 (defmulti joint-dispatch
715 "Translate blender pseudo-joints into real JME joints."
716 (fn [constraints & _]
717 (:type constraints)))
718
719 (defmethod joint-dispatch :point
720 [constraints control-a control-b pivot-a pivot-b rotation]
721 (doto (SixDofJoint. control-a control-b pivot-a pivot-b false)
722 (.setLinearLowerLimit Vector3f/ZERO)
723 (.setLinearUpperLimit Vector3f/ZERO)))
724
725 (defmethod joint-dispatch :hinge
726 [constraints control-a control-b pivot-a pivot-b rotation]
727 (let [axis (if-let [axis (:axis constraints)] axis Vector3f/UNIT_X)
728 [limit-1 limit-2] (:limit constraints)
729 hinge-axis (.mult rotation (blender-to-jme axis))]
730 (doto (HingeJoint. control-a control-b pivot-a pivot-b
731 hinge-axis hinge-axis)
732 (.setLimit limit-1 limit-2))))
733
734 (defmethod joint-dispatch :cone
735 [constraints control-a control-b pivot-a pivot-b rotation]
736 (let [limit-xz (:limit-xz constraints)
737 limit-xy (:limit-xy constraints)
738 twist (:twist constraints)]
739 (doto (ConeJoint. control-a control-b pivot-a pivot-b
740 rotation rotation)
741 (.setLimit (float limit-xz) (float limit-xy)
742 (float twist)))))
743 #+end_src
744 #+end_listing
745
746 All that is left for joints it to combine the above pieces into a
747 something that can operate on the collection of nodes that a
748 blender file represents.
749
750 #+caption: Program to completely create a joint given information
751 #+caption: from a blender file.
752 #+name: connect
753 #+begin_listing clojure
754 #+begin_src clojure
755 (defn connect
756 "Create a joint between 'obj-a and 'obj-b at the location of
757 'joint. The type of joint is determined by the metadata on 'joint.
758
759 Here are some examples:
760 {:type :point}
761 {:type :hinge :limit [0 (/ Math/PI 2)] :axis (Vector3f. 0 1 0)}
762 (:axis defaults to (Vector3f. 1 0 0) if not provided for hinge joints)
763
764 {:type :cone :limit-xz 0]
765 :limit-xy 0]
766 :twist 0]} (use XZY rotation mode in blender!)"
767 [#^Node obj-a #^Node obj-b #^Node joint]
768 (let [control-a (.getControl obj-a RigidBodyControl)
769 control-b (.getControl obj-b RigidBodyControl)
770 joint-center (.getWorldTranslation joint)
771 joint-rotation (.toRotationMatrix (.getWorldRotation joint))
772 pivot-a (world-to-local obj-a joint-center)
773 pivot-b (world-to-local obj-b joint-center)]
774 (if-let
775 [constraints (map-vals eval (read-string (meta-data joint "joint")))]
776 ;; A side-effect of creating a joint registers
777 ;; it with both physics objects which in turn
778 ;; will register the joint with the physics system
779 ;; when the simulation is started.
780 (joint-dispatch constraints
781 control-a control-b
782 pivot-a pivot-b
783 joint-rotation))))
784 #+end_src
785 #+end_listing
786
787 In general, whenever =CORTEX= exposes a sense (or in this case
788 physicality), it provides a function of the type =sense!=, which
789 takes in a collection of nodes and augments it to support that
790 sense. The function returns any controlls necessary to use that
791 sense. In this case =body!= cerates a physical body and returns no
792 control functions.
793
794 #+caption: Program to give joints to a creature.
795 #+name: name
796 #+begin_listing clojure
797 #+begin_src clojure
798 (defn joints!
799 "Connect the solid parts of the creature with physical joints. The
800 joints are taken from the \"joints\" node in the creature."
801 [#^Node creature]
802 (dorun
803 (map
804 (fn [joint]
805 (let [[obj-a obj-b] (joint-targets creature joint)]
806 (connect obj-a obj-b joint)))
807 (joints creature))))
808 (defn body!
809 "Endow the creature with a physical body connected with joints. The
810 particulars of the joints and the masses of each body part are
811 determined in blender."
812 [#^Node creature]
813 (physical! creature)
814 (joints! creature))
815 #+end_src
816 #+end_listing
817
818 All of the code you have just seen amounts to only 130 lines, yet
819 because it builds on top of Blender and jMonkeyEngine3, those few
820 lines pack quite a punch!
821
822 The hand from figure \ref{blender-hand}, which was modeled after my
823 own right hand, can now be given joints and simulated as a
824 creature.
825
826 #+caption: With the ability to create physical creatures from blender,
827 #+caption: =CORTEX= gets one step closer to a full creature simulation
828 #+caption: environment.
829 #+name: name
830 #+ATTR_LaTeX: :width 15cm
831 [[./images/physical-hand.png]]
832
597 833
598 ** Eyes reuse standard video game components 834 ** Eyes reuse standard video game components
599 835
600 ** Hearing is hard; =CORTEX= does it right 836 ** Hearing is hard; =CORTEX= does it right
601 837