;(function() { window.createMeasureObserver = (measureName) => { var markPrefix = `_uol-measure-${measureName}-${new Date().getTime()}`; performance.mark(`${markPrefix}-start`); return { end: function() { performance.mark(`${markPrefix}-end`); performance.measure(`uol-measure-${measureName}`, `${markPrefix}-start`, `${markPrefix}-end`); performance.clearMarks(`${markPrefix}-start`); performance.clearMarks(`${markPrefix}-end`); } } }; /** * Gerenciador de eventos */ window.gevent = { stack: [], RUN_ONCE: true, on: function(name, callback, once) { this.stack.push([name, callback, !!once]); }, emit: function(name, args) { for (var i = this.stack.length, item; i--;) { item = this.stack[i]; if (item[0] === name) { item[1](args); if (item[2]) { this.stack.splice(i, 1); } } } } }; var runningSearch = false; var hadAnEvent = true; var elementsToWatch = window.elementsToWatch = new Map(); var innerHeight = window.innerHeight; // timestamp da última rodada do requestAnimationFrame // É usado para limitar a procura por elementos visíveis. var lastAnimationTS = 0; // verifica se elemento está no viewport do usuário var isElementInViewport = function(el) { var rect = el.getBoundingClientRect(); var clientHeight = window.innerHeight || document.documentElement.clientHeight; // renderizando antes, evitando troca de conteúdo visível no chartbeat-related-content if(el.className.includes('related-content-front')) return true; // garante que usa ao mínimo 280px de margem para fazer o lazyload var margin = clientHeight + Math.max(280, clientHeight * 0.2); // se a base do componente está acima da altura da tela do usuário, está oculto if(rect.bottom < 0 && rect.bottom > margin * -1) { return false; } // se o topo do elemento está abaixo da altura da tela do usuário, está oculto if(rect.top > margin) { return false; } // se a posição do topo é negativa, verifica se a altura dele ainda // compensa o que já foi scrollado if(rect.top < 0 && rect.height + rect.top < 0) { return false; } return true; }; var asynxNextFreeTime = () => { return new Promise((resolve) => { if(window.requestIdleCallback) { window.requestIdleCallback(resolve, { timeout: 5000, }); } else { window.requestAnimationFrame(resolve); } }); }; var asyncValidateIfElIsInViewPort = function(promise, el) { return promise.then(() => { if(el) { if(isElementInViewport(el) == true) { const cb = elementsToWatch.get(el); // remove da lista para não ser disparado novamente elementsToWatch.delete(el); cb(); } } }).then(asynxNextFreeTime); }; // inicia o fluxo de procura de elementos procurados var look = function() { if(window.requestIdleCallback) { window.requestIdleCallback(findByVisibleElements, { timeout: 5000, }); } else { window.requestAnimationFrame(findByVisibleElements); } }; var findByVisibleElements = function(ts) { var elapsedSinceLast = ts - lastAnimationTS; // se não teve nenhum evento que possa alterar a página if(hadAnEvent == false) { return look(); } if(elementsToWatch.size == 0) { return look(); } if(runningSearch == true) { return look(); } // procura por elementos visíveis apenas 5x/seg if(elapsedSinceLast < 1000/5) { return look(); } // atualiza o último ts lastAnimationTS = ts; // reseta status de scroll para não entrar novamente aqui hadAnEvent = false; // indica que está rodando a procura por elementos no viewport runningSearch = true; const done = Array.from(elementsToWatch.keys()).reduce(asyncValidateIfElIsInViewPort, Promise.resolve()); // obtém todos os elementos que podem ter view contabilizados //elementsToWatch.forEach(function(cb, el) { // if(isElementInViewport(el) == true) { // // remove da lista para não ser disparado novamente // elementsToWatch.delete(el); // cb(el); // } //}); done.then(function() { runningSearch = false; }); // reinicia o fluxo de procura look(); }; /** * Quando o elemento `el` entrar no viewport (-20%), cb será disparado. */ window.lazyload = function(el, cb) { if(el.nodeType != Node.ELEMENT_NODE) { throw new Error("element parameter should be a Element Node"); } if(typeof cb !== 'function') { throw new Error("callback parameter should be a Function"); } elementsToWatch.set(el, cb); } var setEvent = function() { hadAnEvent = true; }; window.addEventListener('scroll', setEvent, { capture: true, ive: true }); window.addEventListener('click', setEvent, { ive: true }); window.addEventListener('resize', setEvent, { ive: true }); window.addEventListener('load', setEvent, { once: true, ive: true }); window.addEventListener('DOMContentLoaded', setEvent, { once: true, ive: true }); window.gevent.on('allJSLoadedAndCreated', setEvent, window.gevent.RUN_ONCE); // inicia a validação look(); })();
  • AssineUOL
Topo

Robô vira terceiro braço no corpo, e pesquisadores usam para dar porrada

Thiago Varella

Colaboração para Tilt

14/06/2020 04h00

Em algum momento da sua vida, você já deve ter desejado um braço e uma mão a mais. Sabe na volta do mercado, com um monte de sacolas para tirar do carro, filho pequeno para segurar sua mão e ainda você precisando abrir a porta de casa? Então... Pois pesquisadores da Universidade de Sherbrooke, no Canadá, podem ter resolvido esse problema. Eles criaram um braço robótico para ser usado por humanos.

Chamada de braço robótico supernumerário, a invenção faz com que a pessoa que a vista na cintura tenha um braço extra no corpo com destreza para colher frutas, por exemplo. Mas para testes, ele foi usado para várias outras atividades que exigem braços e mãos, como usar a raquete para um jogo de bton, pintar parede ou até dar socos para destruir paredes (?), como mostra um vídeo de demonstração do robô.

O braço é controlado por um sistema hidráulico conectado ao usuário por meio de um cabo. O único problema é que quem está vestindo o braço não o controla. É preciso uma outra pessoa para determinar o que o robô irá fazer.

Mas os pesquisadores já estão estudando maneiras de instalar sensores ou usar inteligência artificial para que o usuário consiga controlar o braço, ou até mesmo que a invenção aprenda a realizar tarefas de modo independente.

"Se queremos que o braço robótico seja multifuncional, é necessário que haja alguma inteligência artificial ou controlador inteligente para detectar o que o humano deseja fazer e como o braço pode ser complementar ao usuário (e agir como um colega de trabalho). Então há muitas coisas para explorar nesse vasto campo", disse Catherine Véronneau, pesquisadora-líder da Universidade de Sherbrooke, ao site IEEE Spectrum.

Segundo a reportagem, o braço robótico pesa pouco mais de 4 kg, ou seja, o peso de um braço humano, e consegue levantar até 5 kg.

O braço robótico possui garras magneto-reológicas que conseguem reagir rapidamente e podem ser removidas a tempo de não machucar um humano.