Skip to content

Commit

Permalink
Merge pull request 'update mini simulator' (#214) from update-minisim…
Browse files Browse the repository at this point in the history
  • Loading branch information
robamu committed Jan 30, 2025
2 parents d9e0abf + 309e399 commit 738872f
Show file tree
Hide file tree
Showing 17 changed files with 123 additions and 87 deletions.
1 change: 1 addition & 0 deletions satrs-example/pytmtc/main.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#!/usr/bin/env python3
"""Example client for the sat-rs example application"""

import logging
import sys
import time
Expand Down
2 changes: 1 addition & 1 deletion satrs-example/pytmtc/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ authors = [
{name = "Robin Mueller", email = "[email protected]"},
]
dependencies = [
"tmtccmd~=8.0",
"tmtccmd~=8.1",
"pydantic~=2.7"
]

Expand Down
11 changes: 11 additions & 0 deletions satrs-example/pytmtc/pytmtc/acs/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from tmtccmd.config import CmdTreeNode


def create_acs_node(mode_node: CmdTreeNode, hk_node: CmdTreeNode) -> CmdTreeNode:
acs_node = CmdTreeNode("acs", "ACS Subsystem Node")
mgm_node = CmdTreeNode("mgms", "MGM devices node")
mgm_node.add_child(mode_node)
mgm_node.add_child(hk_node)

acs_node.add_child(mgm_node)
return acs_node
File renamed without changes.
2 changes: 1 addition & 1 deletion satrs-example/pytmtc/pytmtc/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

class SatrsConfigHook(HookBase):
def __init__(self, json_cfg_path: str):
super().__init__(json_cfg_path=json_cfg_path)
super().__init__(json_cfg_path)

def get_communication_interface(self, com_if_key: str) -> Optional[ComInterface]:
from tmtccmd.config.com import (
Expand Down
Empty file.
Empty file.
2 changes: 1 addition & 1 deletion satrs-example/pytmtc/pytmtc/hk.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from spacepackets.ecss import PusTm

from pytmtc.common import AcsId, Apid
from pytmtc.mgms import handle_mgm_hk_report
from pytmtc.acs.mgms import handle_mgm_hk_report


_LOGGER = logging.getLogger(__name__)
Expand Down
14 changes: 3 additions & 11 deletions satrs-example/pytmtc/pytmtc/pus_tc.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@
)
from tmtccmd.pus.s11_tc_sched import create_time_tagged_cmd

from pytmtc.acs import create_acs_node
from pytmtc.common import Apid
from pytmtc.mgms import create_mgm_cmds
from pytmtc.acs.mgms import create_mgm_cmds

_LOGGER = logging.getLogger(__name__)

Expand Down Expand Up @@ -67,7 +68,6 @@ def feed_cb(self, info: ProcedureWrapper, wrapper: FeedWrapper):


def create_cmd_definition_tree() -> CmdTreeNode:

root_node = CmdTreeNode.root_node()

hk_node = CmdTreeNode("hk", "Housekeeping Node", hide_children_for_print=True)
Expand Down Expand Up @@ -101,15 +101,7 @@ def create_cmd_definition_tree() -> CmdTreeNode:
)
)
root_node.add_child(scheduler_node)

acs_node = CmdTreeNode("acs", "ACS Subsystem Node")
mgm_node = CmdTreeNode("mgms", "MGM devices node")
mgm_node.add_child(mode_node)
mgm_node.add_child(hk_node)

acs_node.add_child(mgm_node)
root_node.add_child(acs_node)

root_node.add_child(create_acs_node(mode_node, hk_node))
return root_node


Expand Down
9 changes: 5 additions & 4 deletions satrs-minisim/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,12 @@ fern = "0.7"
strum = { version = "0.26", features = ["derive"] }
num_enum = "0.7"
humantime = "2"
tai-time = { version = "0.3", features = ["serde"] }

[dependencies.asynchronix]
version = "0.2.2"
# git = "https://github.com/asynchronics/asynchronix.git"
# branch = "main"
[dependencies.nexosim]
version = "0.3.1"
git = "https://github.com/us-irs/nexosim.git"
branch = "explicit-serde-feature"
features = ["serde"]

[dependencies.satrs]
Expand Down
17 changes: 8 additions & 9 deletions satrs-minisim/src/acs.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use std::{f32::consts::PI, sync::mpsc, time::Duration};

use asynchronix::{
model::{Model, Output},
time::Scheduler,
use nexosim::{
model::{Context, Model},
ports::Output,
};
use satrs::power::SwitchStateBinary;
use satrs_minisim::{
Expand Down Expand Up @@ -55,7 +55,7 @@ impl<ReplyProvider: MgmReplyProvider> MagnetometerModel<ReplyProvider> {
self.switch_state = switch_state;
}

pub async fn send_sensor_values(&mut self, _: (), scheduler: &Scheduler<Self>) {
pub async fn send_sensor_values(&mut self, _: (), scheduler: &mut Context<Self>) {
self.reply_sender
.send(ReplyProvider::create_mgm_reply(MgmReplyCommon {
switch_state: self.switch_state,
Expand Down Expand Up @@ -114,11 +114,11 @@ impl MagnetorquerModel {
pub async fn apply_torque(
&mut self,
duration_and_dipole: (Duration, MgtDipole),
scheduler: &Scheduler<Self>,
cx: &mut Context<Self>,
) {
self.torque_dipole = duration_and_dipole.1;
self.torquing = true;
if scheduler
if cx
.schedule_event(duration_and_dipole.0, Self::clear_torque, ())
.is_err()
{
Expand All @@ -138,12 +138,11 @@ impl MagnetorquerModel {
self.generate_magnetic_field(()).await;
}

pub async fn request_housekeeping_data(&mut self, _: (), scheduler: &Scheduler<Self>) {
pub async fn request_housekeeping_data(&mut self, _: (), cx: &mut Context<Self>) {
if self.switch_state != SwitchStateBinary::On {
return;
}
scheduler
.schedule_event(Duration::from_millis(15), Self::send_housekeeping_data, ())
cx.schedule_event(Duration::from_millis(15), Self::send_housekeeping_data, ())
.expect("requesting housekeeping data failed")
}

Expand Down
100 changes: 66 additions & 34 deletions satrs-minisim/src/controller.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::{sync::mpsc, time::Duration};

use asynchronix::{
simulation::{Address, Simulation},
use nexosim::{
simulation::{Address, Scheduler, Simulation},
time::{Clock, MonotonicTime, SystemClock},
};
use satrs_minisim::{
Expand All @@ -23,35 +23,52 @@ const MGM_REQ_WIRETAPPING: bool = false;
const PCDU_REQ_WIRETAPPING: bool = false;
const MGT_REQ_WIRETAPPING: bool = false;

pub struct ModelAddrWrapper {
mgm_addr: Address<MagnetometerModel<MgmLis3MdlReply>>,
pcdu_addr: Address<PcduModel>,
mgt_addr: Address<MagnetorquerModel>,
}

// The simulation controller processes requests and drives the simulation.
#[allow(dead_code)]
pub struct SimController {
pub sys_clock: SystemClock,
pub request_receiver: mpsc::Receiver<SimRequest>,
pub reply_sender: mpsc::Sender<SimReply>,
pub simulation: Simulation,
pub mgm_addr: Address<MagnetometerModel<MgmLis3MdlReply>>,
pub pcdu_addr: Address<PcduModel>,
pub mgt_addr: Address<MagnetorquerModel>,
pub scheduler: Scheduler,
pub addr_wrapper: ModelAddrWrapper,
}

impl ModelAddrWrapper {
pub fn new(
mgm_addr: Address<MagnetometerModel<MgmLis3MdlReply>>,
pcdu_addr: Address<PcduModel>,
mgt_addr: Address<MagnetorquerModel>,
) -> Self {
Self {
mgm_addr,
pcdu_addr,
mgt_addr,
}
}
}
impl SimController {
pub fn new(
sys_clock: SystemClock,
request_receiver: mpsc::Receiver<SimRequest>,
reply_sender: mpsc::Sender<SimReply>,
simulation: Simulation,
mgm_addr: Address<MagnetometerModel<MgmLis3MdlReply>>,
pcdu_addr: Address<PcduModel>,
mgt_addr: Address<MagnetorquerModel>,
scheduler: Scheduler,
addr_wrapper: ModelAddrWrapper,
) -> Self {
Self {
sys_clock,
request_receiver,
reply_sender,
simulation,
mgm_addr,
pcdu_addr,
mgt_addr,
scheduler,
addr_wrapper,
}
}

Expand All @@ -62,7 +79,7 @@ impl SimController {
// Check for UDP requests every millisecond. Shift the simulator ahead here to prevent
// replies lying in the past.
t += Duration::from_millis(udp_polling_interval_ms);
self.sys_clock.synchronize(t);
let _synch_status = self.sys_clock.synchronize(t);
self.handle_sim_requests(t_old);
self.simulation
.step_until(t)
Expand Down Expand Up @@ -118,11 +135,13 @@ impl SimController {
}
match mgm_request {
MgmRequestLis3Mdl::RequestSensorData => {
self.simulation.send_event(
MagnetometerModel::send_sensor_values,
(),
&self.mgm_addr,
);
self.simulation
.process_event(
MagnetometerModel::send_sensor_values,
(),
&self.addr_wrapper.mgm_addr,
)
.expect("event execution error for mgm");
}
}
Ok(())
Expand All @@ -136,14 +155,21 @@ impl SimController {
match pcdu_request {
PcduRequest::RequestSwitchInfo => {
self.simulation
.send_event(PcduModel::request_switch_info, (), &self.pcdu_addr);
.process_event(
PcduModel::request_switch_info,
(),
&self.addr_wrapper.pcdu_addr,
)
.unwrap();
}
PcduRequest::SwitchDevice { switch, state } => {
self.simulation.send_event(
PcduModel::switch_device,
(switch, state),
&self.pcdu_addr,
);
self.simulation
.process_event(
PcduModel::switch_device,
(switch, state),
&self.addr_wrapper.pcdu_addr,
)
.unwrap();
}
}
Ok(())
Expand All @@ -155,17 +181,23 @@ impl SimController {
log::info!("received MGT request: {:?}", mgt_request);
}
match mgt_request {
MgtRequest::ApplyTorque { duration, dipole } => self.simulation.send_event(
MagnetorquerModel::apply_torque,
(duration, dipole),
&self.mgt_addr,
),
MgtRequest::RequestHk => self.simulation.send_event(
MagnetorquerModel::request_housekeeping_data,
(),
&self.mgt_addr,
),
}
MgtRequest::ApplyTorque { duration, dipole } => self
.simulation
.process_event(
MagnetorquerModel::apply_torque,
(duration, dipole),
&self.addr_wrapper.mgt_addr,
)
.unwrap(),
MgtRequest::RequestHk => self
.simulation
.process_event(
MagnetorquerModel::request_housekeeping_data,
(),
&self.addr_wrapper.mgt_addr,
)
.unwrap(),
};
Ok(())
}

Expand Down
21 changes: 10 additions & 11 deletions satrs-minisim/src/eps.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use std::{sync::mpsc, time::Duration};

use asynchronix::{
model::{Model, Output},
time::Scheduler,
use nexosim::{
model::{Context, Model},
ports::Output,
};
use satrs::power::SwitchStateBinary;
use satrs_minisim::{
Expand All @@ -29,14 +29,13 @@ impl PcduModel {
}
}

pub async fn request_switch_info(&mut self, _: (), scheduler: &Scheduler<Self>) {
scheduler
.schedule_event(
Duration::from_millis(SWITCH_INFO_DELAY_MS),
Self::send_switch_info,
(),
)
.expect("requesting switch info failed");
pub async fn request_switch_info(&mut self, _: (), cx: &mut Context<Self>) {
cx.schedule_event(
Duration::from_millis(SWITCH_INFO_DELAY_MS),
Self::send_switch_info,
(),
)
.expect("requesting switch info failed");
}

pub fn send_switch_info(&mut self) {
Expand Down
2 changes: 1 addition & 1 deletion satrs-minisim/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use asynchronix::time::MonotonicTime;
use nexosim::time::MonotonicTime;
use num_enum::{IntoPrimitive, TryFromPrimitive};
use serde::{de::DeserializeOwned, Deserialize, Serialize};

Expand Down
23 changes: 12 additions & 11 deletions satrs-minisim/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use acs::{MagnetometerModel, MagnetorquerModel};
use asynchronix::simulation::{Mailbox, SimInit};
use asynchronix::time::{MonotonicTime, SystemClock};
use controller::SimController;
use controller::{ModelAddrWrapper, SimController};
use eps::PcduModel;
use nexosim::simulation::{Mailbox, SimInit};
use nexosim::time::{MonotonicTime, SystemClock};
use satrs_minisim::udp::SIM_CTRL_PORT;
use satrs_minisim::{SimReply, SimRequest};
use std::sync::mpsc;
Expand Down Expand Up @@ -63,19 +63,20 @@ fn create_sim_controller(
} else {
SimInit::new()
};
let simulation = sim_init
.add_model(mgm_model, mgm_mailbox)
.add_model(pcdu_model, pcdu_mailbox)
.add_model(mgt_model, mgt_mailbox)
.init(start_time);
let addrs = ModelAddrWrapper::new(mgm_addr, pcdu_addr, mgt_addr);
let (simulation, scheduler) = sim_init
.add_model(mgm_model, mgm_mailbox, "MGM model")
.add_model(pcdu_model, pcdu_mailbox, "PCDU model")
.add_model(mgt_model, mgt_mailbox, "MGT model")
.init(start_time)
.unwrap();
SimController::new(
sys_clock,
request_receiver,
reply_sender,
simulation,
mgm_addr,
pcdu_addr,
mgt_addr,
scheduler,
addrs,
)
}

Expand Down
2 changes: 1 addition & 1 deletion satrs-minisim/src/time.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use asynchronix::time::MonotonicTime;
use nexosim::time::MonotonicTime;

pub fn current_millis(time: MonotonicTime) -> u64 {
(time.as_secs() as u64 * 1000) + (time.subsec_nanos() as u64 / 1_000_000)
Expand Down
Loading

0 comments on commit 738872f

Please sign in to comment.