mirror of
https://github.com/SHC-ASTRA/rover-ros2.git
synced 2026-04-20 11:51:16 -05:00
Compare commits
11 Commits
410d3706ed
...
mcu-versio
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
87237bd841 | ||
|
|
79b2d0020f | ||
|
|
3dd9525833 | ||
|
|
8404999369 | ||
|
|
88574524cf | ||
|
|
30bb32a66b | ||
|
|
010d2da0b6 | ||
|
|
0a257abf43 | ||
|
|
b09b55bee0 | ||
|
|
ec7f272934 | ||
|
|
bc9183d59a |
@@ -68,23 +68,23 @@ Anchor provides a mock connector meant for testing and scripting purposes. You c
|
|||||||
$ ros2 launch anchor_pkg rover.launch.py connector:="mock"
|
$ ros2 launch anchor_pkg rover.launch.py connector:="mock"
|
||||||
```
|
```
|
||||||
|
|
||||||
You can see all data sent to it in a string format with this command:
|
To see all data that would be sent over the CAN network (and thus to the microcontrollers), use this command:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ ros2 topic echo /anchor/to_vic/debug
|
$ ros2 topic echo /anchor/to_vic/debug
|
||||||
```
|
```
|
||||||
|
|
||||||
To send data to it, use the normal topic:
|
To send data to the mock connector (as if you were a ROS2 node), use the normal relay topic:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ ros2 topic pub /anchor/to_vic/relay astra_msgs/msg/VicCAN '{mcu_name: "core", command_id: 50, data: [0.0, 2.0, 0.0, 1.0]}'
|
$ ros2 topic pub /anchor/to_vic/relay astra_msgs/msg/VicCAN '{mcu_name: "core", command_id: 50, data: [0.0, 2.0, 0.0, 1.0]}'
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
To emulate receiving data from a microcontroller, publish to the dedicated topic:
|
To send data to the mock connector (as if you were a microcontroller), publish to the dedicated topic:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ ros2 topic pub /anchor/from_vic/mock_mcu std_msgs/msg/String '{data: "can_relay_fromvic,arm,55,0.0,450.0,900.0,0.0"}'
|
$ ros2 topic pub /anchor/from_vic/mock_mcu astra_msgs/msg/VicCAN '{mcu_name: "arm", command_id: 55, data: [0.0, 450.0, 900.0, 0.0]}'
|
||||||
```
|
```
|
||||||
|
|
||||||
### Testing Serial
|
### Testing Serial
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
from warnings import deprecated
|
from warnings import deprecated
|
||||||
|
import time
|
||||||
import rclpy
|
import rclpy
|
||||||
from rclpy.node import Node
|
from rclpy.node import Node
|
||||||
from rclpy.executors import ExternalShutdownException
|
from rclpy.executors import ExternalShutdownException
|
||||||
@@ -17,8 +18,9 @@ from .connector import (
|
|||||||
from .convert import string_to_viccan
|
from .convert import string_to_viccan
|
||||||
import threading
|
import threading
|
||||||
|
|
||||||
from astra_msgs.msg import VicCAN
|
from builtin_interfaces.msg import Time
|
||||||
from std_msgs.msg import String
|
from std_msgs.msg import String
|
||||||
|
from astra_msgs.msg import VicCAN, McuVersion
|
||||||
|
|
||||||
|
|
||||||
class Anchor(Node):
|
class Anchor(Node):
|
||||||
@@ -37,7 +39,7 @@ class Anchor(Node):
|
|||||||
|
|
||||||
Subscribers:
|
Subscribers:
|
||||||
* /anchor/from_vic/mock_mcu
|
* /anchor/from_vic/mock_mcu
|
||||||
- For testing without an actual MCU, publish strings here as if they came from an MCU
|
- For testing without an actual MCU, publish ViCAN messages here as if they came from an MCU
|
||||||
* /anchor/to_vic/relay
|
* /anchor/to_vic/relay
|
||||||
- Core, Arm, and Bio publish VicCAN messages to this topic to send to the MCU
|
- Core, Arm, and Bio publish VicCAN messages to this topic to send to the MCU
|
||||||
* /anchor/to_vic/relay_string
|
* /anchor/to_vic/relay_string
|
||||||
@@ -47,6 +49,8 @@ class Anchor(Node):
|
|||||||
Instead, it converts them to VicCAN messages first.
|
Instead, it converts them to VicCAN messages first.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
ASTRA_EPOCH = time.struct_time((2022, 1, 1, 0, 0, 0, 0, 0, 0)) # January 1, 2022
|
||||||
|
|
||||||
connector: Connector
|
connector: Connector
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@@ -158,6 +162,12 @@ class Anchor(Node):
|
|||||||
"/anchor/to_vic/debug",
|
"/anchor/to_vic/debug",
|
||||||
20,
|
20,
|
||||||
)
|
)
|
||||||
|
# MCU Version publisher
|
||||||
|
self.mcu_version_pub_ = self.create_publisher(
|
||||||
|
McuVersion,
|
||||||
|
"/anchor/from_vic/mcu_version",
|
||||||
|
20,
|
||||||
|
)
|
||||||
|
|
||||||
# Subscribers
|
# Subscribers
|
||||||
self.tovic_sub_ = self.create_subscription(
|
self.tovic_sub_ = self.create_subscription(
|
||||||
@@ -173,9 +183,9 @@ class Anchor(Node):
|
|||||||
20,
|
20,
|
||||||
)
|
)
|
||||||
self.mock_mcu_sub_ = self.create_subscription(
|
self.mock_mcu_sub_ = self.create_subscription(
|
||||||
String,
|
VicCAN,
|
||||||
"/anchor/from_vic/mock_mcu",
|
"/anchor/from_vic/mock_mcu",
|
||||||
self.on_mock_fromvic,
|
self.relay_fromvic,
|
||||||
20,
|
20,
|
||||||
)
|
)
|
||||||
self.tovic_string_sub_ = self.create_subscription(
|
self.tovic_string_sub_ = self.create_subscription(
|
||||||
@@ -185,6 +195,8 @@ class Anchor(Node):
|
|||||||
20,
|
20,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
self.mcu_versions: dict[str, McuVersion] = {}
|
||||||
|
|
||||||
# Close devices on exit
|
# Close devices on exit
|
||||||
atexit.register(self.cleanup)
|
atexit.register(self.cleanup)
|
||||||
|
|
||||||
@@ -206,7 +218,9 @@ class Anchor(Node):
|
|||||||
self.connector.write(msg)
|
self.connector.write(msg)
|
||||||
self.tovic_debug_pub_.publish(msg)
|
self.tovic_debug_pub_.publish(msg)
|
||||||
|
|
||||||
@deprecated("Use /anchor/to_vic/relay or /anchor/to_vic/relay_string instead of /anchor/relay")
|
@deprecated(
|
||||||
|
"Use /anchor/to_vic/relay or /anchor/to_vic/relay_string instead of /anchor/relay"
|
||||||
|
)
|
||||||
def write_connector_legacy(self, msg: String):
|
def write_connector_legacy(self, msg: String):
|
||||||
"""Write to the connector by first attempting to convert String to VicCAN"""
|
"""Write to the connector by first attempting to convert String to VicCAN"""
|
||||||
# please do not reference this code. ~riley
|
# please do not reference this code. ~riley
|
||||||
@@ -229,16 +243,25 @@ class Anchor(Node):
|
|||||||
elif msg.mcu_name == "citadel" or msg.mcu_name == "digit":
|
elif msg.mcu_name == "citadel" or msg.mcu_name == "digit":
|
||||||
self.fromvic_bio_pub_.publish(msg)
|
self.fromvic_bio_pub_.publish(msg)
|
||||||
|
|
||||||
def on_mock_fromvic(self, msg: String):
|
# MCU Versioning information
|
||||||
"""Relay a message as if it came from the MCU"""
|
if msg.command_id in (46, 47) and msg.mcu_name not in self.mcu_versions:
|
||||||
viccan = string_to_viccan(
|
self.mcu_versions[msg.mcu_name] = McuVersion(mcu_name=msg.mcu_name)
|
||||||
msg.data,
|
|
||||||
"mock",
|
if msg.command_id == 46: # commit hashes
|
||||||
self.get_logger(),
|
self.mcu_versions[msg.mcu_name].project_commit_fragment = msg.data[0]
|
||||||
self.get_clock().now().to_msg(),
|
self.mcu_versions[msg.mcu_name].astra_lib_commit_fragment = msg.data[1]
|
||||||
)
|
elif msg.command_id == 47: # build timestamp and version numbers
|
||||||
if viccan:
|
version_msg = self.mcu_versions[msg.mcu_name]
|
||||||
self.relay_fromvic(viccan)
|
version_msg.build_time = Time(
|
||||||
|
sec=int(time.mktime(self.ASTRA_EPOCH) + msg.data[0])
|
||||||
|
)
|
||||||
|
# is_main and is_dirty is in msg.data[1]
|
||||||
|
# Out of 1 byte, it looks like [lib_isdirty][lib_ismain][proj_isdirty][proj_ismain]
|
||||||
|
version_msg.astra_lib_is_dirty = bool(int(msg.data[1]) >> 3 & 0x1)
|
||||||
|
version_msg.astra_lib_is_main = bool(int(msg.data[1]) >> 2 & 0x1)
|
||||||
|
version_msg.project_is_dirty = bool(int(msg.data[1]) >> 1 & 0x1)
|
||||||
|
version_msg.project_is_main = bool(int(msg.data[1]) & 0x1)
|
||||||
|
self.mcu_version_pub_.publish(version_msg)
|
||||||
|
|
||||||
|
|
||||||
def main(args=None):
|
def main(args=None):
|
||||||
|
|||||||
@@ -257,7 +257,7 @@ class CANConnector(Connector):
|
|||||||
)
|
)
|
||||||
|
|
||||||
if self.can_channel and self.can_channel.startswith("v"):
|
if self.can_channel and self.can_channel.startswith("v"):
|
||||||
self.logger.warn("likely using virtual CAN interface")
|
self.logger.warn("CAN interface is likely virtual")
|
||||||
|
|
||||||
def read(self) -> tuple[VicCAN | None, str | None]:
|
def read(self) -> tuple[VicCAN | None, str | None]:
|
||||||
if not self.can_bus:
|
if not self.can_bus:
|
||||||
@@ -372,10 +372,10 @@ class CANConnector(Connector):
|
|||||||
case 2:
|
case 2:
|
||||||
data_type = 1
|
data_type = 1
|
||||||
data = struct.pack(">ff", *msg.data)
|
data = struct.pack(">ff", *msg.data)
|
||||||
case 3 | 4: # 3 gets padded and is treated as 4
|
case 3 | 4: # 3 gets treated as 4
|
||||||
data_type = 2
|
data_type = 2
|
||||||
# pad till we have 4 otherwise struct.pack will freak out
|
if data_len == 3:
|
||||||
msg.data = (msg.data + [0])[:4]
|
msg.data.append(0)
|
||||||
data = struct.pack(">hhhh", *[int(x) for x in msg.data])
|
data = struct.pack(">hhhh", *[int(x) for x in msg.data])
|
||||||
case _:
|
case _:
|
||||||
self.logger.error(
|
self.logger.error(
|
||||||
|
|||||||
@@ -58,7 +58,8 @@ def string_to_viccan(
|
|||||||
def viccan_to_string(viccan: VicCAN) -> str:
|
def viccan_to_string(viccan: VicCAN) -> str:
|
||||||
"""Converts a ROS2 VicCAN message to the serial string VicCAN format."""
|
"""Converts a ROS2 VicCAN message to the serial string VicCAN format."""
|
||||||
# make sure we accept 3 digits and treat it as 4
|
# make sure we accept 3 digits and treat it as 4
|
||||||
if len(viccan.data) == 3: viccan.data.append("0")
|
if len(viccan.data) == 3:
|
||||||
|
viccan.data.append(0)
|
||||||
# go from [ w, x, y, z ] -> ",w,x,y,z" & round to 7 digits max
|
# go from [ w, x, y, z ] -> ",w,x,y,z" & round to 7 digits max
|
||||||
data = "".join([f",{round(val,7)}" for val in viccan.data])
|
data = "".join([f",{round(val,7)}" for val in viccan.data])
|
||||||
return f"can_relay_tovic,{viccan.mcu_name},{viccan.command_id}{data}\n"
|
return f"can_relay_tovic,{viccan.mcu_name},{viccan.command_id}{data}\n"
|
||||||
|
|||||||
Submodule src/astra_msgs updated: 2264a2cb67...5ffc601cf7
Reference in New Issue
Block a user