Math to rotate according to gravity

Does anyone have the math ready written to work out what to pass to rotate() so that render2D() output visually appears static regardless of rotation of the device? (Using SB 1.0 data)

In other words, I’d like to display a 2D pattern where gravity orients the pattern.

I started to read through glowflow/Accelerometer Tilt 3D at master · Roger-random/glowflow · GitHub which seems to be the most complete example of reacting to gravity, but, it’s a 3D pattern and maybe is specifically for tubes rather than planes, so I’m worried even if I do manage to understand it, it won’t apply to what I’m doing in a way that I myself can convert over.

1 Like

How many degrees of freedom does your matrix have? Will it be pivoting around a single axis only, or can it rotate around more than one axis?

It’s a flat panel wearable on a necklace - actually using a battery system inspired by you! - but held in position against the body so it can rotate around Z as the person leans left and right. Rotation around Y and X can be ignored. This means that X, Y, or between them will be pointing downwards. X at 0.020 (1g) when that’s pointing down, or Y when that is (https://electromage.com/docs/sensor-expansion-board#accelerometer)

I can probably go from javascript - Trigonometry calculate tilt angle from accelerometer data - Stack Overflow to what I need, so I’ll give that a go today or tomorrow and see if I can work it out (if anyone has it ready-to-go in a copy/paste format, I’d still gratefully accept that and leave my learning for some other part!)

Hi @nick ,
The atan2(y, x) function has 90% what you need. It will return an angle in rads.

export var accelerometer
var angleCorrectionRads

//show a gauge as a level
export function gaugeLevel() {
  return 1 - abs(angleCorrectionRads / PI)
}

export function beforeRender(delta) {
  //measure the angle of the current accelerometer force
  var currentAngleRads = atan2(accelerometer[0], accelerometer[1])
  
  //you may need to reverse this angledepending on the 
  //sensor board orientation relative to the LEDs
  currentAngleRads = -currentAngleRads
  
  //smooth this out a little to reduce noise in the accelerometer samples
  angleCorrectionRads = mix(angleCorrectionRads, currentAngleRads, .02)
  
  //apply this angle as a rotation
  //first reset the transform
  resetTransform()
  //center coordinates so we rotate around the center, not the corner
  translate(-.5, -.5) 
  //rotate by the correction angle
  rotate(angleCorrectionRads)
}

export function render2D(index, x, y) {
  //draw a vertical line
  var v = clamp(1 - abs(y*5), 0, 1)
  hsv(x + .5, 1, v*v)
}

Accelerometer level example.epe (7.5 KB)

3 Likes

Thank you @wizard , and especially this pattern has a few tips in that are very useful to know about! The mix() for smoothing is great, and useful to be reminded of the gauge feature to help debugging. I also hadn’t realised (read properly) that a resetTransform() and translate() would be necessary so useful to see that.

It’s working well, thank you!

2 Likes