<commit_before>#!/usr/bin/env python
# -*- coding: utf-8 -*-
import argparse
import random
import os
import time
import RPIO
import RPIO.PWM

import cherrypy

from ws4py.server.cherrypyserver import WebSocketPlugin, WebSocketTool
from ws4py.websocket import WebSocket
from ws4py.messaging import TextMessage

PWM_FREQUENCY = 50    # Hz

PWM_DMA_CHANNEL = 0
PWM_SUBCYLCLE_TIME_US = 1000/PWM_FREQUENCY * 1000
PWM_PULSE_INCREMENT_US = 5

PAN_PWM_PIN = 23
TILT_PWM_PIN = 24

ABSOLUTE_MIN_PULSE_WIDTH_US = 500
ABSOLUTE_MAX_PULSE_WIDTH_US = 2500



# Setup RPIO, and prepare for PWM signals
RPIO.setmode( RPIO.BCM )

RPIO.PWM.setup( pulse_incr_us=PWM_PULSE_INCREMENT_US )
RPIO.PWM.init_channel( PWM_DMA_CHANNEL, PWM_SUBCYLCLE_TIME_US )

#-------------------------------------------------------------------------------
class ServoPWM:

    #---------------------------------------------------------------------------
    def __init__( self, pwmPin, minAnglePulseWidthPair,
        midAnglePulseWidthPair, maxAnglePulseWidthPair ):

        # Check that the given angles are valid
        assert( minAnglePulseWidthPair[ 0 ] >= 0 )
        assert( midAnglePulseWidthPair[ 0 ] > minAnglePulseWidthPair[ 0 ] )
        assert( midAnglePulseWidthPair[ 0 ] < maxAnglePulseWidthPair[ 0 ] )
        assert( maxAnglePulseWidthPair[ 0 ] <= 180 )

        self.pwmPin = pwmPin
        self.minAnglePulseWidthPair = minAnglePulseWidthPair
        self.midAnglePulseWidthPair = midAnglePulseWidthPair
        self.maxAnglePulseWidthPair = maxAnglePulseWidthPair
        self.lastPulseWidthSet = None

    #---------------------------------------------------------------------------
    def setCommand( self, command ):

        # Work out whether the command is an angle, or a pulse width
        if command >= ABSOLUTE_MIN_PULSE_WIDTH_US:
            self.setPulseWidth( command )
        else:
            self.setAngle( command )

    #---------------------------------------------------------------------------
    def setPulseWidth( self, pulseWidth ):

        # Constrain the pulse width
        if pulseWidth < ABSOLUTE_MIN_PULSE_WIDTH_US:
            pulseWidth = ABSOLUTE_MIN_PULSE_WIDTH_US
        if pulseWidth > ABSOLUTE_MAX_PULSE_WIDTH_US:
            pulseWidth = ABSOLUTE_MAX_PULSE_WIDTH_US

        # Ensure that the pulse width is an integer multiple of the smallest
        # possible pulse increment
        pulseIncrementUS = RPIO.PWM.get_pulse_incr_us()
        numPulsesNeeded = int( pulseWidth/pulseIncrementUS )
        pulseWidth = numPulsesNeeded * pulseIncrementUS

        if pulseWidth != self.lastPulseWidthSet:

            RPIO.PWM.add_channel_pulse( PWM_DMA_CHANNEL, self.pwmPin, 0, numPulsesNeeded )
            self.lastPulseWidthSet = pulseWidth

    #---------------------------------------------------------------------------
    def movePulseIncrement( self, pulseIncrement ):

        if self.lastPulseWidthSet is None:
            command = self.midAnglePulseWidthPair[ 1 ] + pulseIncrement
        else:
            command = self.lastPulseWidthSet + pulseIncrement

        # Stop it going too far for this servo's settings.
        if command < self.maxAnglePulseWidthPair[ 1 ]:
            command = self.maxAnglePulseWidthPair[ 1 ]
        elif command >self.minAnglePulseWidthPair[ 1 ]:
            command = self.minAnglePulseWidthPair[ 1 ]

        self.setPulseWidth( command )

    #---------------------------------------------------------------------------
    def setAngle( self, angle ):

        # Constrain the angle
        if angle < self.minAnglePulseWidthPair[ 0 ]:
            angle = self.minAnglePulseWidthPair[ 0 ]
        if angle > self.maxAnglePulseWidthPair[ 0 ]:
            angle = self.maxAnglePulseWidthPair[ 0 ]

        # Convert the angle to a pulse width using linear interpolation
        if angle < self.midAnglePulseWidthPair[ 0 ]:

            angleDiff = self.midAnglePulseWidthPair[ 0 ] - self.minAnglePulseWidthPair[ 0 ]
            startPulseWidth = self.minAnglePulseWidthPair[ 1 ]
            pulseWidthDiff = self.midAnglePulseWidthPair[ 1 ] - self.minAnglePulseWidthPair[ 1 ]

            interpolation = float( angle - self.minAnglePulseWidthPair[ 0 ] ) / angleDiff

            pulseWidth = startPulseWidth + interpolation*pulseWidthDiff

        else:

            angleDiff = self.maxAnglePulseWidthPair[ 0 ] - self.midAnglePulseWidthPair[ 0 ]
            startPulseWidth = self.midAnglePulseWidthPair[ 1 ]
            pulseWidthDiff = self.maxAnglePulseWidthPair[ 1 ] - self.midAnglePulseWidthPair[ 1 ]

            interpolation = float( angle - self.midAnglePulseWidthPair[ 0 ] ) / angleDiff

            pulseWidth = startPulseWidth + interpolation*pulseWidthDiff

        print "Converted angle {0} to pulse width {1}".format( angle, pulseWidth )

        # Now set the pulse width
        self.setPulseWidth( pulseWidth )

#-------------------------------------------------------------------------------
# Create ServoPWM instances to control the servos
panServoPWM = ServoPWM( PAN_PWM_PIN,
    minAnglePulseWidthPair=( 50.0, 2100 ),
    midAnglePulseWidthPair=( 90.0, 1300 ),
    maxAnglePulseWidthPair=( 130.0, 800.0 ) )
tiltServoPWM = ServoPWM( TILT_PWM_PIN,
    minAnglePulseWidthPair=( 45.0, 2100 ),
    midAnglePulseWidthPair=( 90.0, 1800 ),
    maxAnglePulseWidthPair=( 135.0, 900.0 ) )

class ChatWebSocketHandler(WebSocket):
    def received_message(self, m):
        cherrypy.engine.publish('websocket-broadcast', m)
        # Process pixel data here...
        command = str(m)
        print "Command: " + command
        vector = command.split(',')
        panIncrement = int( vector[0].strip() )
        tiltIncrement = int( vector[1].strip() )

        #@todo if y is less than previous y, go down the difference etc...

        # Move camera...
        panServoPWM.movePulseIncrement( panIncrement )
        tiltServoPWM.movePulseIncrement( tiltIncrement )
        #time.sleep( 0.001 )

    def closed(self, code, reason="A client left the room without a proper explanation."):
        cherrypy.engine.publish('websocket-broadcast', TextMessage(reason))

class Root(object):
    def __init__(self, host, port, ssl=False):
        self.host = host
        self.port = port
        self.scheme = 'wss' if ssl else 'ws'

    @cherrypy.expose
    def index(self):
        return """<html>
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
 <link rel="stylesheet" href="css/main.css" />

      <script type='application/javascript' src='https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js'></script>
      <script type='application/javascript'>
        $(document).ready(function() {



          websocket = '%(scheme)s://%(host)s:%(port)s/ws';
          if (window.WebSocket) {
            ws = new WebSocket(websocket);
          }
          else if (window.MozWebSocket) {
            ws = MozWebSocket(websocket);
          }<commit_msg>Better movement control (needs calibrating px to increments)<commit_after>#!/usr/bin/env python
# -*- coding: utf-8 -*-
import argparse
import random
import os
import time
import RPIO
import RPIO.PWM

import cherrypy

from ws4py.server.cherrypyserver import WebSocketPlugin, WebSocketTool
from ws4py.websocket import WebSocket
from ws4py.messaging import TextMessage

PWM_FREQUENCY = 50    # Hz

PWM_DMA_CHANNEL = 0
PWM_SUBCYLCLE_TIME_US = 1000/PWM_FREQUENCY * 1000
PWM_PULSE_INCREMENT_US = 5

PAN_PWM_PIN = 23
TILT_PWM_PIN = 24

ABSOLUTE_MIN_PULSE_WIDTH_US = 500
ABSOLUTE_MAX_PULSE_WIDTH_US = 2500



# Setup RPIO, and prepare for PWM signals
RPIO.setmode( RPIO.BCM )
RPIO.PWM.set_loglevel(RPIO.PWM.LOG_LEVEL_ERRORS)
RPIO.PWM.setup( pulse_incr_us=PWM_PULSE_INCREMENT_US )
RPIO.PWM.init_channel( PWM_DMA_CHANNEL, PWM_SUBCYLCLE_TIME_US )

#-------------------------------------------------------------------------------
class ServoPWM:

    #---------------------------------------------------------------------------
    def __init__( self, pwmPin, minAnglePulseWidthPair,
        midAnglePulseWidthPair, maxAnglePulseWidthPair ):

        # Check that the given angles are valid
        assert( minAnglePulseWidthPair[ 0 ] >= 0 )
        assert( midAnglePulseWidthPair[ 0 ] > minAnglePulseWidthPair[ 0 ] )
        assert( midAnglePulseWidthPair[ 0 ] < maxAnglePulseWidthPair[ 0 ] )
        assert( maxAnglePulseWidthPair[ 0 ] <= 180 )

        self.pwmPin = pwmPin
        self.minAnglePulseWidthPair = minAnglePulseWidthPair
        self.midAnglePulseWidthPair = midAnglePulseWidthPair
        self.maxAnglePulseWidthPair = maxAnglePulseWidthPair
        self.lastPulseWidthSet = None
        self.lastPulseIncrement = 0
        self.lastJoystickInput = 0

    #---------------------------------------------------------------------------
    def setCommand( self, command ):

        # Work out whether the command is an angle, or a pulse width
        if command >= ABSOLUTE_MIN_PULSE_WIDTH_US:
            self.setPulseWidth( command )
        else:
            self.setAngle( command )

    #---------------------------------------------------------------------------
    def setPulseWidth( self, pulseWidth ):

        # Constrain the pulse width
        if pulseWidth < ABSOLUTE_MIN_PULSE_WIDTH_US:
            pulseWidth = ABSOLUTE_MIN_PULSE_WIDTH_US
        if pulseWidth > ABSOLUTE_MAX_PULSE_WIDTH_US:
            pulseWidth = ABSOLUTE_MAX_PULSE_WIDTH_US

        # Ensure that the pulse width is an integer multiple of the smallest
        # possible pulse increment
        pulseIncrementUS = RPIO.PWM.get_pulse_incr_us()
        numPulsesNeeded = int( pulseWidth/pulseIncrementUS )
        pulseWidth = numPulsesNeeded * pulseIncrementUS

        if pulseWidth != self.lastPulseWidthSet:

            RPIO.PWM.add_channel_pulse( PWM_DMA_CHANNEL, self.pwmPin, 0, numPulsesNeeded )
            self.lastPulseWidthSet = pulseWidth

    #---------------------------------------------------------------------------
    def movePulseIncrement( self, pulseIncrement ):

        self.lastPulseIncrement = pulseIncrement

        if self.lastPulseWidthSet is None:
            command = self.midAnglePulseWidthPair[ 1 ] + pulseIncrement
        else:
            command = self.lastPulseWidthSet + pulseIncrement

        # Stop it going too far for this servo's settings.
        if command < self.maxAnglePulseWidthPair[ 1 ]:
            command = self.maxAnglePulseWidthPair[ 1 ]
        elif command >self.minAnglePulseWidthPair[ 1 ]:
            command = self.minAnglePulseWidthPair[ 1 ]

        self.setPulseWidth( command )

    #---------------------------------------------------------------------------
    def joystickInput( self, px ):

        pulseIncrement = 0

        if px > 0:
            if px > self.lastJoystickInput:
                # Still going in the same direction
                pulseIncrement = px - self.lastJoystickInput
            else:
                # Now going in the reverse direction
                pulseIncrement = (self.lastJoystickInput - px) * -1

        if px < 0:
            if px < self.lastJoystickInput:
                # Still going in the same direction
                pulseIncrement = px - self.lastJoystickInput
            else:
                # Now going in the reverse direction
                pulseIncrement = (self.lastJoystickInput - px) * -1

        #print str(pulseIncrement) + " -- " + str(self.lastPulseIncrement) + " -- " + str(self.lastJoystickInput)
        print str(pulseIncrement)
        self.lastJoystickInput = px

        self.movePulseIncrement( pulseIncrement )


    #---------------------------------------------------------------------------
    def setAngle( self, angle ):

        # Constrain the angle
        if angle < self.minAnglePulseWidthPair[ 0 ]:
            angle = self.minAnglePulseWidthPair[ 0 ]
        if angle > self.maxAnglePulseWidthPair[ 0 ]:
            angle = self.maxAnglePulseWidthPair[ 0 ]

        # Convert the angle to a pulse width using linear interpolation
        if angle < self.midAnglePulseWidthPair[ 0 ]:

            angleDiff = self.midAnglePulseWidthPair[ 0 ] - self.minAnglePulseWidthPair[ 0 ]
            startPulseWidth = self.minAnglePulseWidthPair[ 1 ]
            pulseWidthDiff = self.midAnglePulseWidthPair[ 1 ] - self.minAnglePulseWidthPair[ 1 ]

            interpolation = float( angle - self.minAnglePulseWidthPair[ 0 ] ) / angleDiff

            pulseWidth = startPulseWidth + interpolation*pulseWidthDiff

        else:

            angleDiff = self.maxAnglePulseWidthPair[ 0 ] - self.midAnglePulseWidthPair[ 0 ]
            startPulseWidth = self.midAnglePulseWidthPair[ 1 ]
            pulseWidthDiff = self.maxAnglePulseWidthPair[ 1 ] - self.midAnglePulseWidthPair[ 1 ]

            interpolation = float( angle - self.midAnglePulseWidthPair[ 0 ] ) / angleDiff

            pulseWidth = startPulseWidth + interpolation*pulseWidthDiff

        print "Converted angle {0} to pulse width {1}".format( angle, pulseWidth )

        # Now set the pulse width
        self.setPulseWidth( pulseWidth )

#-------------------------------------------------------------------------------
# Create ServoPWM instances to control the servos
panServoPWM = ServoPWM( PAN_PWM_PIN,
    minAnglePulseWidthPair=( 50.0, 2100 ),
    midAnglePulseWidthPair=( 90.0, 1300 ),
    maxAnglePulseWidthPair=( 130.0, 800.0 ) )
tiltServoPWM = ServoPWM( TILT_PWM_PIN,
    minAnglePulseWidthPair=( 45.0, 2100 ),
    midAnglePulseWidthPair=( 90.0, 1800 ),
    maxAnglePulseWidthPair=( 135.0, 900.0 ) )

class ChatWebSocketHandler(WebSocket):
    def received_message(self, m):
        cherrypy.engine.publish('websocket-broadcast', m)
        # Process pixel data here...
        command = str(m)
        print "Command: " + command
        vector = command.split(',')
        panIncrement = int( vector[0].strip() )
        tiltIncrement = int( vector[1].strip() )

        # Move camera...
        panServoPWM.joystickInput( panIncrement )
        tiltServoPWM.joystickInput( tiltIncrement )
        time.sleep( 0.001 )

    def closed(self, code, reason="A client left the room without a proper explanation."):
        cherrypy.engine.publish('websocket-broadcast', TextMessage(reason))

class Root(object):
    def __init__(self, host, port, ssl=False):
        self.host = host
        self.port = port
        self.scheme = 'wss' if ssl else 'ws'

    @cherrypy.expose
    def index(self):
        return """<html>
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
 <link rel="stylesheet" href="css/main.css" />

      <script type='application/javascript' src='https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js'></script>
      <script type='application/javascript'>
        $(document).ready(function() {



          websocket = '%(scheme)s://%(host)s:%(port)s/ws';
          if (window.WebSocket) {
            ws = new WebSocket(websocket);
          }
          else if (window.MozWebSocket) {
            ws = MozWebSocket(websocket);
          }
{'fraction_non_alphanumeric': 0.15607580824972128, 'fraction_numerical': 0.01619778346121057, 'mean_word_length': 2.0665594208727125, 'pattern_counts': {'":': 0, '<': 33, '<?xml version=': 0, '>': 33, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1401665', 'n_tokens_mistral': 4744, 'n_tokens_neox': 4386, 'n_words': 993}