three_js_urdf_parser 0.1.0 copy "three_js_urdf_parser: ^0.1.0" to clipboard
three_js_urdf_parser: ^0.1.0 copied to clipboard

A urdf parser extension for three_dart that also includes a dae/stl loader.

example/lib/main.dart

import 'dart:async';
import 'dart:math';
import 'dart:ui';

import 'package:flutter/material.dart';
import 'package:three_js/three_js.dart' as three;

import 'package:three_js_urdf_parser/three_js_urdf_parser.dart';

void main(List<String> args) {
  runApp(
    const MaterialApp(
      debugShowCheckedModeBanner: false,
      home: ExamplePage(),
    ),
  );
}

class ExamplePage extends StatefulWidget {
  const ExamplePage({Key? key}) : super(key: key);

  @override
  State<ExamplePage> createState() => _ExamplePageState();
}

class _ExamplePageState extends State<ExamplePage> with WidgetsBindingObserver {
  bool loading = true;
  late three.ThreeJS threeJs;
  URDFRobot? robot;

  @override
  void initState() {
    Future.delayed(const Duration(seconds: 1), () {
      setState(() {
        loading = false;
      });
      threeJs = three.ThreeJS(
        onSetupComplete: () {
          setState(() {});
        },
        setup: setup,
      );
    });
    super.initState();
  }

  @override
  void dispose() {
    threeJs.dispose();
    three.loading.clear();
    super.dispose();
  }

  FutureOr<void> setup() async {
    threeJs.scene = three.Scene();
    threeJs.scene.autoUpdate = true;
    threeJs.scene.background = three.Color(204, 204, 204);

    threeJs.camera = three.PerspectiveCamera(60, threeJs.width / threeJs.height, 1, 2000);
    threeJs.camera.position.setValues(200, 100, 0);

    final ambientLight = three.AmbientLight(0xffffff, 0.3);
    threeJs.scene.add(ambientLight);

    final pointLight = three.PointLight(0xffffff, 0.1);

    pointLight.position.setValues(0, 0, 0);

    threeJs.camera.add(pointLight);
    threeJs.scene.add(threeJs.camera);

    threeJs.camera.lookAt(threeJs.scene.position);

    // --- Controls ---
    var controls = three.OrbitControls(threeJs.camera, threeJs.globalKey);

    controls.enableDamping = true; // an animation loop is required when either damping or auto-rotation are enabled
    controls.dampingFactor = 0.05;

    controls.screenSpacePanning = false;

    controls.minDistance = 10;
    controls.maxDistance = 1000;

    // --- World ---

    // axis
    three.Mesh xMesh = three.Mesh(
        three.CylinderGeometry(0.5, 0.5, 100), three.MeshPhongMaterial({three.MaterialProperty.color: 0xff0000, three.MaterialProperty.flatShading: false}));
    xMesh.position = three.Vector3(60, 0, 0);
    xMesh.setRotationFromEuler(three.Euler(0, 0, pi / 2));
    threeJs.scene.add(xMesh);

    three.Mesh yMesh = three.Mesh(
        three.CylinderGeometry(0.5, 0.5, 100), three.MeshPhongMaterial({three.MaterialProperty.color: 0x00ff00, three.MaterialProperty.flatShading: false}));
    yMesh.position = three.Vector3(0, 60, 0);
    threeJs.scene.add(yMesh);

    three.Mesh zMesh = three.Mesh(
        three.CylinderGeometry(0.5, 0.5, 100), three.MeshPhongMaterial({three.MaterialProperty.color: 0x0000ff, three.MaterialProperty.flatShading: false}));
    zMesh.position = three.Vector3(0, 0, 60);
    zMesh.setRotationFromEuler(three.Euler(pi / 2, 0, 0));
    threeJs.scene.add(zMesh);

    // URDF
    robot = await URDFLoader.parse(
      "assets/T12/urdf/T12.URDF",
      "assets/T12",
      URDFLoaderOptions(
        materialCb: (linkName, visualNode, material) {
          return three.MeshStandardMaterial({
            three.MaterialProperty.color: material.color,
            three.MaterialProperty.flatShading: material.flatShading,
            three.MaterialProperty.roughness: 0.3,
            three.MaterialProperty.metalness: 0.8,
          });
        },
      ),
    );

    robot!.transform.scale = three.Vector3(30, 30, 30);

    // robot!.transform.printHierarchy();

    threeJs.scene.add(robot!.getObject());

    // --- Lights ---
    var dirLight1 = three.DirectionalLight(0xffffff);
    dirLight1.position.setValues(30, 30, 30);
    threeJs.scene.add(dirLight1);

    var dirLight2 = three.DirectionalLight(0x3C8488);
    dirLight2.position.setValues(-30, -30, -30);
    threeJs.scene.add(dirLight2);

    threeJs.addAnimationEvent(
      (dt) {
        controls.update();
        animate();
      },
    );
  }

  void animate() {
    if (robot == null) {
      return;
    }

    int t1 = DateTime.now().millisecondsSinceEpoch;
    double time = t1 / 3e2;

    // robot animation
    for (int i = 1; i <= 6; i++) {
      double offset = i * pi / 3;
      double ratio = max(0, sin(time + offset));

      robot!.trySetAngle("HP$i", lerpDouble(30, 0, ratio)! * three.MathUtils.deg2rad);
      robot!.trySetAngle("KP$i", lerpDouble(90, 150, ratio)! * three.MathUtils.deg2rad);
      robot!.trySetAngle("AP$i", lerpDouble(-30, -60, ratio)! * three.MathUtils.deg2rad);

      robot!.trySetAngle("TC${i}A", lerpDouble(0, 0.065, ratio)!);
      robot!.trySetAngle("TC${i}B", lerpDouble(0, 0.065, ratio)!);

      robot!.trySetAngle("W$i", t1 * 0.000001);
    }

    threeJs.render();
  }

  @override
  Widget build(BuildContext context) => loading ? const Center(child: CircularProgressIndicator()) : threeJs.build();
}
1
likes
130
points
9
downloads

Documentation

API reference

Publisher

verified publisherdebuggerx.com

Weekly Downloads

A urdf parser extension for three_dart that also includes a dae/stl loader.

Repository (GitHub)
View/report issues

License

Apache-2.0 (license)

Dependencies

collection, flutter, path, three_js, xml

More

Packages that depend on three_js_urdf_parser