Python Forum

Full Version: Help in breaking bytes into bits through masking and shifting
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Hi all, I am new to Python programming and I need some help. I am currently working on a project for robots and I am being tasked by my supervisor to work on the number of bytes that we are going to transmit. I have a base station to send data to the robot.

So, I am sending cmd_vel which consists of linear and angular velocity. I have calculated the number of bits for each. They are both 7 bits. (X(3 bits). X (4bits)) (The first X values are from 0 to 2 (2 bits) and I used 1 bit as a sign bit to represent +/-)(For the second X value, it is from 0-9 (4 bits)). So in total, that would be 14 bits, so I have to use 1 byte for each.

The problem now is that my supervisor wants me to put these values into Python. He also wants me to send these data as bytes to the robot, and when the robot receives these data, he wants the bytes to be broken down into bits through masking and shifting.

I have no clue on how to do it and I would really appreciate if someone could help me out.
You could certainly do that. You might also look at the bitarray module which makes things easier.

For instance, if you are counting bits from the left and want to know bits 2, 3, and 4, you would
* create a byte with the right mask,
* & it with that mask
* examine or shift the bits.

mask = int('00111000', 2)
check = 178
ans = check & mask
ans = ans >> 3
print(f"{ans:b}")
Output:
110
If you're already familiar with bit operations in general, that should be enough to get you started, and you can ask more specific questions if you're having trouble.
Look at struct
(Nov-11-2020, 04:46 AM)deanhystad Wrote: [ -> ]Look at struct

I'm sorry, may I know what do you mean by look at struct?
Python struct library
Is there anything in struct that helps with bit manipulation? It's good for manipulating structs of bytes, but I don't know about working with bits or partial bytes.
You can encode this by using ordinary integer operations
def encode(sign, x, y):
    assert 0 <= x <= 2
    assert 0 <= y <= 9
    assert sign in (0, 1)
    return 64 * sign + 16 * x + y

def decode(n):
    m, y = divmod(n, 16)
    sign, x = divmod(m, 4)
    return sign, x, y

if __name__ == '__main__':
    from itertools import product
    for s, x, y in product(range(2), range(3), range(10)):
        n = encode(s, x, y)
        print(s, x, y, bin(n), decode(n))
Output:
0 0 9 0b1001 (0, 0, 9) 0 1 0 0b10000 (0, 1, 0) 0 1 1 0b10001 (0, 1, 1) 0 1 2 0b10010 (0, 1, 2) 0 1 3 0b10011 (0, 1, 3) 0 1 4 0b10100 (0, 1, 4) 0 1 5 0b10101 (0, 1, 5) 0 1 6 0b10110 (0, 1, 6) 0 1 7 0b10111 (0, 1, 7) 0 1 8 0b11000 (0, 1, 8) 0 1 9 0b11001 (0, 1, 9) 0 2 0 0b100000 (0, 2, 0) 0 2 1 0b100001 (0, 2, 1) 0 2 2 0b100010 (0, 2, 2) 0 2 3 0b100011 (0, 2, 3) 0 2 4 0b100100 (0, 2, 4) 0 2 5 0b100101 (0, 2, 5) 0 2 6 0b100110 (0, 2, 6) 0 2 7 0b100111 (0, 2, 7) 0 2 8 0b101000 (0, 2, 8) 0 2 9 0b101001 (0, 2, 9) 1 0 0 0b1000000 (1, 0, 0) 1 0 1 0b1000001 (1, 0, 1) 1 0 2 0b1000010 (1, 0, 2) 1 0 3 0b1000011 (1, 0, 3) 1 0 4 0b1000100 (1, 0, 4) 1 0 5 0b1000101 (1, 0, 5) 1 0 6 0b1000110 (1, 0, 6) 1 0 7 0b1000111 (1, 0, 7) 1 0 8 0b1001000 (1, 0, 8) 1 0 9 0b1001001 (1, 0, 9) 1 1 0 0b1010000 (1, 1, 0) 1 1 1 0b1010001 (1, 1, 1) 1 1 2 0b1010010 (1, 1, 2) 1 1 3 0b1010011 (1, 1, 3) 1 1 4 0b1010100 (1, 1, 4) 1 1 5 0b1010101 (1, 1, 5) 1 1 6 0b1010110 (1, 1, 6) 1 1 7 0b1010111 (1, 1, 7) 1 1 8 0b1011000 (1, 1, 8) 1 1 9 0b1011001 (1, 1, 9) 1 2 0 0b1100000 (1, 2, 0) 1 2 1 0b1100001 (1, 2, 1) 1 2 2 0b1100010 (1, 2, 2) 1 2 3 0b1100011 (1, 2, 3) 1 2 4 0b1100100 (1, 2, 4) 1 2 5 0b1100101 (1, 2, 5) 1 2 6 0b1100110 (1, 2, 6) 1 2 7 0b1100111 (1, 2, 7) 1 2 8 0b1101000 (1, 2, 8) 1 2 9 0b1101001 (1, 2, 9)
(Nov-11-2020, 09:09 AM)Gribouillis Wrote: [ -> ]You can encode this by using ordinary integer operations
def encode(sign, x, y):
    assert 0 <= x <= 2
    assert 0 <= y <= 9
    assert sign in (0, 1)
    return 64 * sign + 16 * x + y

def decode(n):
    m, y = divmod(n, 16)
    sign, x = divmod(m, 4)
    return sign, x, y

if __name__ == '__main__':
    from itertools import product
    for s, x, y in product(range(2), range(3), range(10)):
        n = encode(s, x, y)
        print(s, x, y, bin(n), decode(n))
Output:
0 0 9 0b1001 (0, 0, 9) 0 1 0 0b10000 (0, 1, 0) 0 1 1 0b10001 (0, 1, 1) 0 1 2 0b10010 (0, 1, 2) 0 1 3 0b10011 (0, 1, 3) 0 1 4 0b10100 (0, 1, 4) 0 1 5 0b10101 (0, 1, 5) 0 1 6 0b10110 (0, 1, 6) 0 1 7 0b10111 (0, 1, 7) 0 1 8 0b11000 (0, 1, 8) 0 1 9 0b11001 (0, 1, 9) 0 2 0 0b100000 (0, 2, 0) 0 2 1 0b100001 (0, 2, 1) 0 2 2 0b100010 (0, 2, 2) 0 2 3 0b100011 (0, 2, 3) 0 2 4 0b100100 (0, 2, 4) 0 2 5 0b100101 (0, 2, 5) 0 2 6 0b100110 (0, 2, 6) 0 2 7 0b100111 (0, 2, 7) 0 2 8 0b101000 (0, 2, 8) 0 2 9 0b101001 (0, 2, 9) 1 0 0 0b1000000 (1, 0, 0) 1 0 1 0b1000001 (1, 0, 1) 1 0 2 0b1000010 (1, 0, 2) 1 0 3 0b1000011 (1, 0, 3) 1 0 4 0b1000100 (1, 0, 4) 1 0 5 0b1000101 (1, 0, 5) 1 0 6 0b1000110 (1, 0, 6) 1 0 7 0b1000111 (1, 0, 7) 1 0 8 0b1001000 (1, 0, 8) 1 0 9 0b1001001 (1, 0, 9) 1 1 0 0b1010000 (1, 1, 0) 1 1 1 0b1010001 (1, 1, 1) 1 1 2 0b1010010 (1, 1, 2) 1 1 3 0b1010011 (1, 1, 3) 1 1 4 0b1010100 (1, 1, 4) 1 1 5 0b1010101 (1, 1, 5) 1 1 6 0b1010110 (1, 1, 6) 1 1 7 0b1010111 (1, 1, 7) 1 1 8 0b1011000 (1, 1, 8) 1 1 9 0b1011001 (1, 1, 9) 1 2 0 0b1100000 (1, 2, 0) 1 2 1 0b1100001 (1, 2, 1) 1 2 2 0b1100010 (1, 2, 2) 1 2 3 0b1100011 (1, 2, 3) 1 2 4 0b1100100 (1, 2, 4) 1 2 5 0b1100101 (1, 2, 5) 1 2 6 0b1100110 (1, 2, 6) 1 2 7 0b1100111 (1, 2, 7) 1 2 8 0b1101000 (1, 2, 8) 1 2 9 0b1101001 (1, 2, 9)
Hi sir, is it possible to help me out with the encoding and decoding of the GPS latitude and longitude? My supervisor just gave me a new task which is to add in the GPS values. I really need your help sir, this means a lot to me. I am grateful and appreciative if you could help me out once more.

Latitude ( 1. x(0-4 (3bits)) x(0-8 (4 bits)) x(0-8 (4bits)) x(0-9(4bits)) x(0-9 (4bits)) x(0-9 (4bits)) )
Longitude ( 1 0 x(0-4 (3bits)). x (0-5 (3bits)) x(0-9 (4bits)) x (0-8 (4bits)) x (0-5 (3bits)) x (0-9 (4bits)) x (0-9 (4bits))
You need something more systematic, perhaps along the lines of
def encode(pattern, numbers):
    result = 0
    for size, n in zip(pattern, numbers):
        result = (result << size) + n
    return result

def decode(pattern, n):
    result = []
    for size in reversed(pattern):
        n, r = divmod(n, 1 << size)
        result.append(r)
    return tuple(reversed(result))


if __name__ == '__main__':
    pat_lat = (1, 3, 4 ,4, 4, 4, 4)
    pat_long = (1, 3, 3, 4, 4, 3, 4, 4)
    data = (1, 2, 5, 5, 7, 6, 3)
    n = encode(pat_lat, data)
    print(data)
    print(bin(n))
    print(decode(pat_lat, n))
Output:
(1, 2, 5, 5, 7, 6, 3) 0b101001010101011101100011 (1, 2, 5, 5, 7, 6, 3)
(Nov-16-2020, 12:29 PM)Gribouillis Wrote: [ -> ]You need something more systematic, perhaps along the lines of
def encode(pattern, numbers):
    result = 0
    for size, n in zip(pattern, numbers):
        result = (result << size) + n
    return result

def decode(pattern, n):
    result = []
    for size in reversed(pattern):
        n, r = divmod(n, 1 << size)
        result.append(r)
    return tuple(reversed(result))


if __name__ == '__main__':
    pat_lat = (1, 3, 4 ,4, 4, 4, 4)
    pat_long = (1, 3, 3, 4, 4, 3, 4, 4)
    data = (1, 2, 5, 5, 7, 6, 3)
    n = encode(pat_lat, data)
    print(data)
    print(bin(n))
    print(decode(pat_lat, n))
Output:
(1, 2, 5, 5, 7, 6, 3) 0b101001010101011101100011 (1, 2, 5, 5, 7, 6, 3)
Hi Sir, I know this is long due and I am so sorry for that, but is there a way to encode and decode the latitude and longitude of the GPS in such a way that it transmits lesser bits?