File size: 5,924 Bytes
09a6f7f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
HULL_POLYGONS = [
    [[-30, +9], [+6, +9], [+34, +1], [+34, -8], [-30, -8]]
];
HULL_BOTTOM_WIDTH = 64;
const SPEED_HIP = 4;
const SPEED_KNEE = 6;

/**
 * @classdesc Bipedal Walker morphology.
 */
class ClassicBipedalBody extends WalkerAbstractBody {
    /**
     * @constructor
     * @param scale {number} - Scale of the environment
     * @param motors_torque {number}
     * @param nb_steps_under_water {number}
     * @param reset_on_hull_critical_contact {boolean}
     */
    constructor(scale, motors_torque=80, nb_steps_under_water=600, reset_on_hull_critical_contact=false) {
        super(scale, motors_torque, nb_steps_under_water);

        this.LEG_DOWN = 3 / this.SCALE; // 0 = center of hull
        this.LEG_W = 8 / this.SCALE;
        this.LEG_H = 34 / this.SCALE;
        this.TORQUE_PENALTY = 0.00035;
        this.reset_on_hull_critical_contact = reset_on_hull_critical_contact;

        this.AGENT_WIDTH = HULL_BOTTOM_WIDTH / this.SCALE;
        this.AGENT_HEIGHT = 17 / this.SCALE + this.LEG_H * 2 - this.LEG_DOWN;
        this.AGENT_CENTER_HEIGHT = this.LEG_H * 2 + this.LEG_DOWN;

        this.old_morphology = false;
    }

    draw(world, init_x, init_y, force_to_center){
        let HULL_FIXTURES = [];
        let fd_polygon;
        let vertices;
        let y_offset = 0;//10/this.SCALE;

        for(let polygon of HULL_POLYGONS){
            fd_polygon = new b2.FixtureDef();
            fd_polygon.shape = new b2.PolygonShape();
            vertices = [];
            for(let vertex of polygon){
                vertices.push(new b2.Vec2(vertex[0] / this.SCALE, vertex[1] / this.SCALE));
            }
            fd_polygon.shape.Set(vertices, polygon.length);
            fd_polygon.density = 5.0;
            fd_polygon.friction = 0.1;
            fd_polygon.filter.categoryBits = 0x20;
            fd_polygon.filter.maskBits = 0x000F; // 0.99 bouncy
            HULL_FIXTURES.push(fd_polygon);
        }

        let LEG_FD = new b2.FixtureDef();
        LEG_FD.shape = new b2.PolygonShape();
        LEG_FD.shape.SetAsBox(this.LEG_W / 2, this.LEG_H / 2);
        LEG_FD.density = 1.0;
        LEG_FD.restitution = 0.0;
        LEG_FD.filter.categoryBits = 0x20;
        LEG_FD.filter.maskBits = 0x000F;

        let LOWER_FD = new b2.FixtureDef();
        LOWER_FD.shape = new b2.PolygonShape();
        LOWER_FD.shape.SetAsBox(0.8 * this.LEG_W / 2, this.LEG_H / 2);
        LOWER_FD.density = 1.0;
        LOWER_FD.restitution = 0.0;
        LOWER_FD.filter.categoryBits = 0x20;
        LOWER_FD.filter.maskBits = 0x000F;

        let hull_bd = new b2.BodyDef();
        hull_bd.type = b2.Body.b2_dynamicBody;
        hull_bd.position.Set(init_x, init_y + y_offset);
        let hull = world.CreateBody(hull_bd);
        for(let fd of HULL_FIXTURES){
            hull.CreateFixture(fd);
        }
        hull.color1 = "#806682"; // [0.5, 0.4, 0.9]
        hull.color2 = "#4D4D80"; // [0.3, 0.3, 0.5]
        hull.ApplyForceToCenter(new b2.Vec2(force_to_center, 0), true);
        hull.SetUserData(new CustomBodyUserData(true, this.reset_on_hull_critical_contact, "hull"));
        this.body_parts.push(hull);
        this.reference_head_object = hull;

        // Leg and lower bodies and joints
        for(let i of [-1, +1]){

            // Leg body
            let leg_bd = new b2.BodyDef();
            leg_bd.type = b2.Body.b2_dynamicBody;
            leg_bd.position.Set(init_x, init_y - this.LEG_H / 2 - this.LEG_DOWN + y_offset);
            //leg_bd.angle = i * 0.05; // 2°
            let leg = world.CreateBody(leg_bd);
            leg.CreateFixture(LEG_FD);
            leg.color1 = i == -1 ? "#9C4F82" : "#964A7D"; // [0.61, 0.31, 0.51] : [0.59, 0.29, 0.49]
            leg.color2 = i == -1 ? "#69364F" : "#63304A"; // [0.41, 0.21, 0.31] : [0.39, 0.19, 0.29]
            leg.SetUserData(new CustomBodyUserData(false, false,"leg"));
            this.body_parts.push(leg);

            // Leg joint motor
            let leg_rjd = new b2.RevoluteJointDef();
            leg_rjd.Initialize(hull, leg, new b2.Vec2(init_x, init_y - this.LEG_DOWN + y_offset));
            leg_rjd.enableMotor = true;
            leg_rjd.enableLimit = true;
            leg_rjd.maxMotorTorque = this.MOTORS_TORQUE;
            leg_rjd.motorSpeed = i;
            leg_rjd.lowerAngle = - 0.8;
            leg_rjd.upperAngle = 1.1;
            let joint_motor = world.CreateJoint(leg_rjd);
            joint_motor.SetUserData(new CustomMotorUserData("hip", SPEED_HIP, false));
            this.motors.push(joint_motor);

            // lower body
            let lower_bd = new b2.BodyDef();
            lower_bd.type = b2.Body.b2_dynamicBody;
            lower_bd.position.Set(init_x, init_y - this.LEG_H * 3 / 2 - this.LEG_DOWN + y_offset);
            //lower_bd.angle = i * 0.05; // 2°
            let lower = world.CreateBody(lower_bd);
            lower.CreateFixture(LOWER_FD);
            lower.color1 = i == -1 ? "#9C4F82" : "#964A7D"; // [0.61, 0.31, 0.51] : [0.59, 0.29, 0.49]
            lower.color2 = i == -1 ? "#69364F" : "#63304A"; // [0.41, 0.21, 0.31] : [0.39, 0.19, 0.29]
            lower.SetUserData(new CustomBodyUserData(true, false,"lower"));
            this.body_parts.push(lower);

            // lower joint motor
            let lower_rjd = new b2.RevoluteJointDef();
            lower_rjd.Initialize(leg, lower, new b2.Vec2(init_x, init_y - this.LEG_DOWN - this.LEG_H + y_offset));
            lower_rjd.enableMotor = true;
            lower_rjd.enableLimit = true;
            lower_rjd.maxMotorTorque = this.MOTORS_TORQUE;
            lower_rjd.motorSpeed = 1;
            lower_rjd.lowerAngle = - 1.6;
            lower_rjd.upperAngle = -0.1;
            joint_motor = world.CreateJoint(lower_rjd);
            joint_motor.SetUserData(new CustomMotorUserData("knee", SPEED_KNEE, true, 1.0, lower));
            this.motors.push(joint_motor);
        }
    }
}