@@ -56,6 +56,8 @@ CanInterface::~CanInterface() {
5656
5757// Main update loop
5858bool CanInterface::update () {
59+ // clear because data get from state!
60+ current_state_.clear ();
5961
6062 if (is_file_mode_) {
6163 return readFileLine ();
@@ -89,6 +91,7 @@ void CanInterface::parseFrame(
8991 double val = decodeSteering (data);
9092 current_state_.steering_angle_deg = val;
9193 current_state_.is_valid = true ;
94+ current_state_.is_steering_angle = true ;
9295 }
9396}
9497
@@ -109,31 +112,34 @@ double CanInterface::decodeSpeed(const std::vector<uint8_t>& data) {
109112 return static_cast <double >(raw) * 0.01 ;
110113}
111114
112- // SSA (Steering angle) : Start Bit 46 | Length 15 | Signed | Factor 0.1
113- // Format: Motorola (Big Endian: https://en.wikipedia.org/wiki/Endianness)
114- // Bit 46 is in byte 5 (bit 6).
115- // This is complex. We verify strictly against provided logic if possible.
116- // Lacking exact bit-matrix, we assume standard Big Endian alignment crossing byte 5 and 6.
115+ // Steering angle
116+ // SSA (Measured steering angle) : 46|15@0- (0.1,0) [0|0] "-"
117+ // SSAZ (Steering zero point) : 29|15@0- (0.1,0) [0|0] "-"
117118double CanInterface::decodeSteering (const std::vector<uint8_t >& data) {
118-
119- if (data.size () < 8 ) return 0.0 ;
120119
121- // Masking logic based on 15-bit signed integer
122- // Assuming MSB is in byte 5, LSB in byte 6
123- uint16_t raw_high = data[5 ];
124- uint16_t raw_low = data[6 ];
125-
126- // Combine
127- uint16_t raw = (raw_high << 8 ) | raw_low;
128-
129- // If it's 15 bits, we might need to shift or mask.
130- // Assuming the 15 bits are right-aligned in the extraction:
131- // (This is a best-guess implementation until A4 is actually observed in logs)
132-
133- // Convert to signed 16-bit to handle negative values (Two's complement)
134- int16_t signed_val = static_cast <int16_t >(raw);
135-
136- return static_cast <double >(signed_val) * 0.1 ;
120+ // Sanity: need at least 8 bytes
121+ if (data.size () < 8 ) return std::numeric_limits<double >::quiet_NaN ();
122+
123+ // SSAZ
124+ uint16_t b6 = (data[5 ] & 0xC0 ) >> 7 ; // Bit 7 from byte 6 BigEndian
125+ uint16_t b5 = data[4 ]; // Byte 5
126+ bool ssazSign = (data[3 ] & 0x10 ) != 0 ; // bit 4 → sign
127+ int16_t b4 = data[3 ] & 0x0F ; // bits 3..0 → magnitude
128+
129+ uint16_t ssaz = (b4 << 10 ) | (b5 << 2 ) | b6;
130+ int16_t ssazSigned = ssazSign ? -ssaz : ssaz;
131+
132+ // SSA
133+ uint16_t ssa_b7 = data[6 ];
134+ bool ssaSign = (data[5 ] & 0x40 ) != 0 ; // bit 6 = sign
135+ uint16_t ssa_b6 = data[5 ] & 0x3F ; // bits 5..0 = magnitude
136+
137+ int16_t ssa = (ssa_b6 << 7 ) | ssa_b7;
138+ int16_t ssaSigned = ssaSign ? -ssa : ssa;
139+
140+ double steering_angle = ssaSigned - ssazSigned;
141+
142+ return steering_angle;
137143}
138144
139145// ============================== REAL-TIME INFERENCE (SocketCAN) ============================== //
0 commit comments