3D science fiction fan based on HTML5 WebGL

Posted by lopes_andre on Wed, 11 Dec 2019 12:01:49 +0100

Preface

For many centuries, wind turbine, like hydraulic machinery, has played an important role in the development of productivity as a power source to replace human and animal resources. The wide application of modern electromechanical power and the discovery of Middle East oil field in 1950s slowed down the development of fan generator.

In the early 1970s, due to the "oil crisis", there was a problem of energy shortage. People realized that the supply of conventional mineral energy was not stable and limited, so the search for clean renewable energy has become an important topic in the modern world. As a renewable and pollution-free natural energy, wind energy has attracted people's attention again.

Now I hope that we can use this wind turbine demo to show all the functions of the wind turbine in a short distance, so that you can know more about the wind turbine.

This demo uses HT for Web Product lightweight HTML5/WebGL modeling solution.

demo link: hightopo.com/demo/fan3d-...

Main functions of fan

Effect:

  

Function of surrounding environment:

1. Wind speed.

Virtual a wind speed value, the wind speed value will affect the power generation efficiency of the fan and the change of the pitch system.

2. Data statistics. * *

  

The graph percentage of ambient temperature, cabin temperature, gearbox temperature and wind speed will change with time.

3. Environmental monitoring. * *

  

Each parameter of the fan is monitored on the left side, and on the right side is the line chart of wind speed change.

Data monitoring. * *

  

The abnormal condition, fault location and time of the fan in the process of power generation. The collection of exception information is conducive to the analysis and handling of exceptions.

V. yaw system. * *

  

The yaw system, also known as the wind device, is a part of the wind turbine engine room. Its function is to quickly and smoothly aim at the wind direction when the direction of the wind speed vector changes, so that the wind turbine can obtain the maximum wind energy.

* VI. pitch system. *

  

As one of the core parts of the control system of large wind turbine, pitch system plays an important role in the safe, stable and efficient operation of the unit. Stable pitch control has become one of the hotspots and difficulties in the research of large-scale wind turbine control technology.

Pitch control technology is simply to control the aerodynamic torque and power captured by the wind turbine by adjusting the pitch angle of the blade and changing the angle of attack of the air flow on the blade.

Button control function:

Fan start stop:

  

Wireframe mode:

  

Cabin view:

  

Power generation process:

  

Sorting ideas:

Scene part:

Here 3D is nested in 2D scene as background.

In this way, when initializing the drawing, you can directly deserialize the 2D drawing.

Event part:

There are many buttons in the 2D drawing to control some animation in 3D.

The implementation idea is to mount 2D and 3D models and view objects to window s when deserializing drawings, so that corresponding data models can be obtained in different scenes.

Environment:

Wind speed, wind direction and pitch angle will be displayed in 2D and 3D, so they can be placed in the data pool for easy management.

Specific code implementation:

Scene Building: as mentioned above, we nest 3D as a background in 2D, so we only need to serialize 2D, which requires part of the code for background judgment.

Related pseudo code:

graphView.deserialize('displays/demo/Wind power generator/Wind turbine structure inspection.json', function (json, dm, gv, datas) {
  if (json.title) document.title = json.title
        if (json.a['json.background']) {
            var bgJSON = json.a['json.background']
            if (bgJSON.indexOf('displays') === 0) {
                var bgGv = new ht.graph.GraphView()
                bgGv.deserialize(bgJSON)
                bgGv.addToDOM()
                graphView.addToDOM(bgGv.getView())
            }
            else if (bgJSON.indexOf('scenes') === 0) {
                var bgG3d = new ht.graph3d.Graph3dView()
                bgG3d.deserialize(bgJSON)
                bgG3d.addToDOM()
                graphView.addToDOM(bgG3d.getView())
            }
            graphView.handleScroll = function () { }
        }

Simulated wind speed: every 30s, a value is randomly generated as the wind speed value.

Related pseudo code:

// Simulated wind speed
mockWindSpeed() {
  return 8 + Math.random() * 12
}

Data statistics: random transformation every 30s.

Effect:

Related pseudo code:

// The angle of the pointer and the blade rotation changes
var oldPointerValue = pitchSystem.a('pointer') || 0
// Rotation angle of fan blades and pitch system
var newRotateAngular = (this.windSpeed - 8) * 7.5 * translateAngularRadian.radian
var addPointerValue = newRotateAngular - oldPointerValue

var oldWindSpeedClip = environmentalData.a('windSpeedClip') || 0
var newWindSpeedClip = (this.windSpeed - 8) / 12
var addWindSpeedClip = newWindSpeedClip - oldWindSpeedClip

var anim = {
  duration: 1e3,
  easing: (v) => {
    return v * v
   },
  action: (v) => {
    var windSpeed = Number(this.windSpeed.toFixed(2))
    var Max = Number(MaxValue.toFixed(2))
    var average = Number(Aver.toFixed(2))
    var windSpeedClip = oldWindSpeedClip + (addWindSpeedClip * v)
    // Set generation parameter random data
     generator.a({ windSpeed })
    // Set up random data of environmental monitoring
    environmentalData.a({ windSpeed, windSpeedClip })
    // Set statistical parameter random data
    statisticalParam.a({ average, Max, windSpeed })
    // Set the pointer angle of the variable navigation system
    pitchSystem.a('pointer', oldPointerValue + (addPointerValue * v))
  }
}
ht.Default.startAnim(anim)

This involves the conversion of angles and radians. 1 ° = Math.PI / 180 °, 1rad = 180 ° / Math.PI, because the radian system is used in the scene, the random angle value needs to be converted into radians.

Explain the code here and get the current value first. Then add a random value - the current value. For example, if the current value is 16, there are two random values: 1: larger than the current value. 2: smaller than the current value.

If it is larger than the current value, such as 18, then it is 16 + (18 - 16) * V (the value after the easing function operation)

If it is smaller than the current value, such as 13, then it is 16 + (13 - 16) * V (the value after the easing function operation)

In this way, when it is random, it will smoothly change from the current value to the target value.

Data statistics: monitor the fault information of the current fan every 30s.

Effect:

The table.json file is used here to add real-time information by modifying the ht.dataSource property.

Related pseudo code:

var checkInternals = () => {
  /**
   * Fault information
   * Pitch system main shaft yaw system gearbox oil cooling device generator air cooling device
   */
    var FailureStatus = {
        // Normal condition
        status1: new Map([
            [0, ['The temperature in the cabin is normal and the pitch angle is normal.', 'i10']],
            [1, ['The temperature in the cabin is normal, and the rotation speed of the main shaft is normal.', 'i9']],
            [2, ['The yaw system is accurate.', 'i8']],
            [3, ['The gearbox temperature is normal.', 'i1']],
            [4, ['The temperature control meter of oil cooling device is normal.', 'i3']],
            [5, ['The generator power is normal.', 'i5']],
            [6, ['The air cooling device is normal.', 'i2']]
        ]),

        // Abnormal state
        status2: new Map([
            [0, ['Pitch angle is abnormal.', 'i10']],
            [1, ['The spindle speed is too high.', 'i9']],
            [2, ['Yaw system offset.', 'i8']],
            [3, ['The gearbox temperature is too high.', 'i1']],
            [4, ['There is too much dust in the oil cooling device.', 'i3']],
            [5, ['The generator current is too high.', 'i5']],
            [6, ['Insufficient heat dissipation of air cooling device.', 'i2']]
        ]),
    }

    // Return normal condition of device status 1: normal 2: abnormal
    var mockQquipmentFailure = (status) => {
        var { rangeRandom } = common
        var index = rangeRandom(7)

        // Return the random device condition
        return FailureStatus[`status${status}`].get(index)
    }

      var info = randomInfo[0]
      var targetTag = randomInfo[1]

      this.tableArr = table.a('ht.dataSource')
      var currentTimeFormat = DateUtil.formatHourTime(new Date())

  // The default value is normal. If the fault keyword is found, the value is abnormal
  var status = 'normal'
  var time = 0
 this.tableArr.push({ status, info, time: currentTimeFormat })
}

We need two Map arrays for easy access. One is the normal information array and the other is the exception information array. The random value is used as an index, and then the corresponding state information is taken and added to the table.

If the current status is normal, it means normal information; otherwise, it means abnormal information. In case of exception information, you can change its color to highlight it through the rendering callback function "drawCell": function(g, text, rect, option) {} of table.json.

Yaw system: during the rotation of the fan, the direction is changed through the yaw system according to the position of the wind.

Effect:

  

Related pseudo code:

/**
  * Random yaw system
  * @param { * }
  */
  randomYawSystem() {
    var { dm } = this
    var { d2d } = window
    var { rangeRandom } = common

    var poll = () => {
       // Random number 30 - 50
        var random = 30 + rangeRandom(20)
        var cabin = dm.getDataByTag('cabin')

        // Convert the angle degree into radian and multiply it by random number to realize random wind direction
        var randomDegrees = translateAngularRadian.radian * random
        var defaultDegress = translateAngularRadian.radian * 180

         ht.Default.startAnim({
           duration: 1e3,
           action: (v) => {
             var oldValue = cabin.getRotationY()
             var newValue = randomDegrees
             var addValue = newValue - oldValue

           cabin.setRotationY(oldValue + addValue * v)
         }
      })
    } }

As mentioned above, the angle radian conversion is performed. Here, the random angle is first converted into radian, and then assigned to rotate.

Pitch system: the change of wind speed affects the angle of fan blade.

Effect:

Related pseudo code:

var old3Value = whiteShell3Line.getRotationX()
var old4Value = whiteShell4Line.getRotationX()
var old5Value = whiteShell5Line.getRotationX()

// Changes in the angle of the pointer and blade rotation
var oldPointerValue = pitchSystem.a('pointer') || 0
// Rotation angle of fan blades and pitch system
var newRotateAngular = (this.windSpeed - 8) * 7.5 * translateAngularRadian.radian
var addPointerValue = newRotateAngular - oldPointerValue

whiteShell3Line.setRotationX(old3Value + ((newRotateAngular - oldPointerValue)))
whiteShell4Line.setRotationX(old4Value + ((newRotateAngular - oldPointerValue)))
whiteShell5Line.setRotationX(old5Value + ((newRotateAngular - oldPointerValue)))Copy code

First, obtain the current X-axis rotation value of each blade, and then obtain the angle value to be rotated for assignment.

Fan start stop: fan start and stop

Related pseudo code:

var fanWireframe = d3d.getDataByTag('fanWireframe')
fanWireframe.setRotationMode('zxy')
this.allAnimManage = new Map([['fanRotate', null]])
var fanRotating = (easeType) => {
  anim = ht.Default.startAnim({
    duration: 5e3,
    easing: (t) => easeIn(t),
    action: (v) => {
      fanWireframe.setRotationZ(fanWireframe.getRotationZ() + speed)

        // Fan hub rotation
        if (fanWireframe.getRotationZ() <= -6.28) {
          fanWireframe.setRotationZ(0)
        }

        // uv offset of fan blades
        for (let i = 1; i < 17; i++) {
          var node = d3d.getDataByTag(`q${i}`)
          node.s('shape3d.uv.offset', fanOffsetData(v)[i - 1])
        }

        // Suspension order
        if (isStop) {
          stopFanRotate(fanWireframe.getRotationZ())
          anim.pause()
          anim = null
        }
    },
      finishFunc: () => {
        fanRotating(false)
      }
    })

    this.allAnimManage.set('fanRotate', anim)
}

Because we can start and stop, we can achieve the effect by controlling the resume and pause of the return object of ht.Default.startAnim().

So I add the animation of fan rotation to the global object, which is convenient for calling.

The method of setrotationmode ('z x y ') is to set the three-dimensional rotation mode in the order of Z - > x - > y. first, rotate the z-axis, then rotate the x-axis, and finally rotate the y-axis. The purpose of setting is to avoid the influence of external rotation on the coordinate axis.

Wind direction: according to the angle of the wind, judge the current position of the wind.

Effect:

Related pseudo code:

// Wind direction
var windDirection = (rotate) => {
    let direction

    switch (true) {
    case rotate === 0:
        direction = 'south'
        break
    case rotate === 90:
        direction = 'east'
        break
    case rotate === 180:
        direction = 'north'
        break
    case rotate === 240:
        direction = 'west'
        break
    case rotate > 0 && rotate < 90:
        direction = 'Southeast'
        break
    case rotate > 90 && rotate < 180:
        direction = 'Northeast'
        break
    case rotate > 180 && rotate < 270:
        direction = 'Northwest'
        break
    case rotate > 270 && rotate < 360:
        direction = 'Southwest'
        break
    default:
        direction = 'No wind direction found'
    }

    return direction
}
// Determine which direction
var angular = randomDegrees * translateAngularRadian.angular
var direction = windDirection(angular)

Put the compass pointer angle to switch for judgment, and return if the corresponding wind direction is found.

summary

Wind power generation is a typical example of industrial Internet. We can analyze the wind turbine model or monitoring data to reduce the complexity of our work and help us quickly understand the internal structure and power generation function of power generation.

HT can do more than that, which requires our rich imagination and our own excellent technology. I hope that through this article, I can convey a kind of energy to you, make you more interested, burst out more fresh ideas, and do more fun things.

Topics: Front-end JSON angular html5